All Downloads are FREE. Search and download functionalities are using the official Maven repository.

js.rt.js Maven / Gradle / Ivy

There is a newer version: 4.1
Show newest version
/**
 * RT Javascript client
 * for RT Servlet
 * Version ${project.version}
 */
(function(global){

	/**
	 * Extender function
	 */
	var extend = function(base, defaults){
		for (var name in defaults){
			if (typeof(base[name]) === "undefined")
				//no default value in base, use from defaults
				base[name] = defaults[name];
		}
		//No recursion (yet)
	};
	
	/**
	 * JSONP requester
	 */
	var JSONP = function(opts){
		
		extend(opts, {
			url: "",
			timeout: 35000,
			success: function(data){},
			error: function(){}
		});
		
		
		//http://stackoverflow.com/questions/5907777/help-on-making-and-handling-jsonp-request-usin-javascript
		var cbName = "jsonp" + Math.floor( Math.random() * 1000000 ),
			script = document.createElement('SCRIPT'),
			//Cleanup job
			cleanup = function(){
				delete window[cbName];
				document.body.removeChild(script);
			},
			//Start timeout job
			timeoutJob = setTimeout(function(){
				cleanup();
				//error state
				opts.error();
			}, opts.timeout);
			
		//Source attribute with callback
		script.src = opts.url.replace("callback=?", "callback=" + cbName);
		
		//Global callback
		window[cbName] = function(data){
			
			//cancel timeout
			clearTimeout(timeoutJob);
			
			//callback
			opts.success(data);
			
			//cleanup
			cleanup();
		};
		
		//Start "request"
		document.body.appendChild(script);
	};

	/**
	 * RT with long poll implementation
	 */
	/*
	var RTLongPollImpl = function(url){
		var id = Math.floor( Math.random() * 10000 );

		//enhance url
		url = url + "?id=" + id + "&mode=longpoll&callback=?";
		
		var listeners = {};
		
		var doRequest = function(){
			JSONP({
				url: url,
				success: handler,
				error: doRequest //start request again after timeout
			});
		};
		
		var handler = function(list){
			if (list instanceof Array)
				list.forEach(function(e){
					var l = listeners[e.type];
					if (typeof l !== "undefined")
						l.forEach(function(l){
							l(e.data);
						});
				});
			doRequest();
		};
		
		//Start polling
		doRequest();
		
		this.on = function(name, fn){
			if (typeof listeners[name] === "undefined")
				listeners[name] = [];
			listeners[name].push(fn);
		};
	};
	*/

	/**
	 * RT with EventSource implementation
	 */
	/*
	var RTEventSourceImpl = function(url, error){
		var id = Math.floor( Math.random() * 10000 ),
			source = new EventSource(url + "?id=" + id + "&mode=sse"),
			initReceived = false;
		
		this.on = function(name, fn){
			source.addEventListener(name, function(e){
				fn(JSON.parse(e.data));
			});
		};
		
		//Watch for init event
		source.addEventListener("__init__", function(e){
			initReceived = true;
		});
		
		setTimeout(function(){
			//Check connection, fail over to longpoll
			if (initReceived)
				return;
			
			//Close source
			source.close();
			error();			
		}, 2000);
		
	
	};
	*/
	

	/**
	 * RT function
	 */
	var RT = function(url, cfg){
		
		cfg = cfg || {};
		
		/**
		 * Default config
		 */
		extend(cfg, {
			jsonp: true
		});
		
		var self = this;
		
		/**
		 * Client id
		 */
		this.id = Math.floor( Math.random() * 10000 );
			
		/**
		 * Map to listeners id -> [l,l]
		 */
		this.listenerMap = {};
		
		/**
		 * Run flag
		 */
		this.run = true;
		
		/**
		 * Create url
		 */
		url += "?mode=longpoll";
		
		//Check jsonp flag
		if (cfg.jsonp)
			url += "&callback=?";

		
		/**
		 * Handles a response
		 */
		var handler = function(list){
			if (list instanceof Array)
				list.forEach(function(e){
					self.fire(e.type, e.data)
				});
			self.doRequest();
		};
		
		/**
		 * Starts a request
		 */
		this.doRequest = function(){
			if (self.run)
				JSONP({
					url: url,
					success: handler,
					error: self.doRequest //start request again after timeout
				});
		};

		//Initial request (deferred)
		setTimeout(this.doRequest, 0);

	};
	
	/**
	 * Stops all further requests
	 */
	RT.prototype.stop = function(){
		this.run = false;
	};
	
	/**
	 * Restarts after stop
	 */
	RT.prototype.start = function(){
		if (!this.run){
			this.run = true;
			this.doRequest();
		}
	};
	
	/**
	 * Fires an event
	 */
	RT.prototype.fire = function(changeId, event){
		var listeners = this.listenerMap[changeId];
		
		if (listeners !== undefined)
			listeners.forEach(function(listener){
				listener(event);
			});
	}
	
	/**
	 * Registers a listener
	 */
	RT.prototype.on = function(changeId, listener){
		if (this.listenerMap[changeId] === undefined)
			//No listeners by that changeId, create new array
			this.listenerMap[changeId] = [];
		
		//append
		this.listenerMap[changeId].push(listener);
	};

	
	/**
	 * Generate linked observable
	 */
	RT.prototype.observable = function(changeId, cfg){
		
		
		if (typeof(ko) === "undefined")
			throw "knockoutjs required for Observable feature";

		var o = ko.observable();
		
		//Register observable listener
		this.on(changeId, function(e){
			
			var value = e;
			
			//Filter event
			if (cfg && typeof cfg.filter === "function" && !cfg.filter(value))
				return;
			
			//Dereference event
			if (cfg && typeof cfg.accessor === "function")
				value = cfg.accessor(value);
			
			
			//Set new value
			o(value);
		});
		
		return o;
			
	};

	/**
	 * Generate linked observable array
	 */
	RT.prototype.observableArray = function(changeId, cfg){
		
		if (typeof(ko) === "undefined")
			throw "knockoutjs required for ObservableArray feature";
		
		var o = ko.observableArray();
			
		//Register observable listener
		this.on(changeId, function(e){
			
			switch(e.op){
			case "INIT":
				e.item.forEach(function(item){
					o.push(item);
				});
				break;
			case "APPEND":
				o.push(e.item);
				break;
			case "ADD":
				//TODO
				break;
			case "REMOVE":
				o.remove( o()[e.index] );
				break;
			case "REPLACE":
				//TODO
				break;
			case "CLEAR":
				o.removeAll();
				break;
			}
			
		});
			
		return o;
			
	};

	
	//Export RT function
	if (typeof define === 'function' && define.amd)
		//requirejs
		define(function(require){
			ko = require("knockout");
			return RT;
		});
	else
		//script
		global.RT = RT;

})(this);




© 2015 - 2024 Weber Informatics LLC | Privacy Policy