diff options
| author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 | 
|---|---|---|
| committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 | 
| commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
| tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dojox/timing | |
| parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
| download | semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2  | |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dojox/timing')
| -rw-r--r-- | includes/js/dojox/timing/README | 58 | ||||
| -rw-r--r-- | includes/js/dojox/timing/Sequence.js | 145 | ||||
| -rw-r--r-- | includes/js/dojox/timing/Streamer.js | 94 | ||||
| -rw-r--r-- | includes/js/dojox/timing/ThreadPool.js | 157 | ||||
| -rw-r--r-- | includes/js/dojox/timing/_base.js | 58 | ||||
| -rw-r--r-- | includes/js/dojox/timing/tests/test_Sequence.html | 80 | ||||
| -rw-r--r-- | includes/js/dojox/timing/tests/test_ThreadPool.html | 16 | 
7 files changed, 608 insertions, 0 deletions
diff --git a/includes/js/dojox/timing/README b/includes/js/dojox/timing/README new file mode 100644 index 0000000..e9b19b5 --- /dev/null +++ b/includes/js/dojox/timing/README @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------- +DojoX Timing +------------------------------------------------------------------------------- +Version 0.1.0 +Release date: 08/08/2007 +------------------------------------------------------------------------------- +Project state: +experimental +------------------------------------------------------------------------------- +Credits +	Tom Trenka (ttrenka AT gmail.com): original Timer, Streamer, Thread and ThreadPool +	Wolfram Kriesing (http://wolfram.kriesing.de/blog/): Sequence +	Jonathan Bond-Caron (jbondc AT gmail.com): port of Timer and Streamer +	Pete Higgins (phiggins AT gmail.com): port of Sequence +------------------------------------------------------------------------------- +Project description + +DojoX Timing is a project that deals with any kind of advanced use of timing +constructs.  The central object, dojox.timing.Timer (included by default), is +a simple object that fires a callback on each tick of the timer, as well as  +when starting or stopping it.  The interval of each tick is settable, but the +default is 1 second--useful for driving something such as a clock. + +dojox.timing.Streamer is an object designed to facilitate streaming/buffer-type +scenarios; it takes an input and an output function, will execute the output +function onTick, and run the input function when the internal buffer gets  +beneath a certain threshold of items.  This can be useful for something timed-- +such as updating a data plot at every N interval, and getting new data from +a source when there's less than X data points in the internal buffer (think +real-time data updating). + +dojox.timing.Sequencer is an object, similar to Streamer, that will allow you +to set up a set of functions to be executed in a specific order, at specific +intervals. + +The DojoX Timing ThreadPool is a port from the original implementation in the +f(m) library.  It allows a user to feed a set of callback functions (wrapped +in a Thread constructor) to a pool for background processing. +------------------------------------------------------------------------------- +Dependencies: + +DojoX Timing only relies on the Dojo Base. +------------------------------------------------------------------------------- +Documentation + +TBD. +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/timing.js +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/timing/* + +Install into the following directory structure: +/dojox/timing.js +/dojox/timing/ + +...which should be at the same level as your Dojo checkout. diff --git a/includes/js/dojox/timing/Sequence.js b/includes/js/dojox/timing/Sequence.js new file mode 100644 index 0000000..4dc4bdb --- /dev/null +++ b/includes/js/dojox/timing/Sequence.js @@ -0,0 +1,145 @@ +if(!dojo._hasResource["dojox.timing.Sequence"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.timing.Sequence"] = true; +dojo.provide("dojox.timing.Sequence"); +dojo.experimental("dojox.timing.Sequence"); // in case it gets moved/renamed somewhere soon + +dojo.declare("dojox.timing.Sequence",null,{ +	// summary:  +	//	This class provides functionality to really sequentialize  +	//	function calls. You need to provide a list of functions and  +	//	some parameters for each (like: pauseBefore) and they will +	//	be run one after another. This can be very useful for slideshows +	//	or alike things. +	// +	// description:  +	//	This array will contain the sequence defines resolved, so that +	// 	ie. repeat:10 will result in 10 elements in the sequence, so  +	// 	the repeat handling is easier and we don't need to handle that +	// 	many extra cases. Also the doneFunction, if given is added at the +	// 	end of the resolved-sequences. + +	// _defsResolved: Array +	// 	The resolved sequence, for easier handling. +	_defsResolved: [], + +	// This is the time to wait before goOn() calls _go(), which  +	// mostly results from a pauseAfter for a function that returned +	// false and is later continued by the external goOn() call. +	// The time to wait needs to be waited in goOn() where the +	// sequence is continued. + +	// _goOnPause: Integer +	//	The pause to wait before really going on. +	_goOnPause: 0, + +	_running: false, +	 +	go: function(/* Array */defs, /* function|Array? */doneFunction){ +		// summary: +		// +		// defs: Array +		//	the sequence of actions +		// doneFunction: Function|Array? +		//	The function to call when done +		this._running = true; +		var self = this;	 +		dojo.forEach(defs, function(cur){ +			if(cur.repeat > 1){ +				var repeat = cur.repeat; +				for(var j=0; j<repeat ;j++){ +					cur.repeat = 1; +					self._defsResolved.push(cur); +				} +			}else{ +				self._defsResolved.push(cur);				 +			} +		}); +		var last = defs[defs.length-1]; +		if (doneFunction) { +			self._defsResolved.push({func: doneFunction}); +		} +		// stop the sequence, this actually just sets this._running to false +		self._defsResolved.push({func: [this.stop, this]}); +		this._curId = 0; +		this._go(); +	}, + +	_go: function(){ +		// summary: Execute one task of this._defsResolved. +		// +		// if _running was set to false stop the sequence, this is the +		// case when i.e. stop() was called. +		if(!this._running){ +			return; +		} +		var cur = this._defsResolved[this._curId]; +		this._curId += 1; +		// create the function to call, the func property might be an array, which means +		// [function, context, parameter1, parameter2, ...] +		function resolveAndCallFunc(func) { +			var ret = null; +			if(dojo.isArray(func)){ +				// Two elements might only be given when the function+context +				// is given, this is nice for using this, ie: [this.func, this] +				if(func.length>2){ +					ret = func[0].apply(func[1], func.slice(2)); +				}else{ +					ret = func[0].apply(func[1]); +				} +			}else{ +				ret = func(); +			} +			return ret; +		} + +		if(this._curId >= this._defsResolved.length){ +			resolveAndCallFunc(cur.func); // call the last function, since it is the doneFunction we dont need to handle pause stuff +			// don't go on and call this._go() again, we are done +			return; +		} +		var self = this; +		if(cur.pauseAfter){ +			if(resolveAndCallFunc(cur.func)!==false){ +				window.setTimeout(function() {self._go()}, cur.pauseAfter); +			}else{ +				this._goOnPause = cur.pauseAfter; +			} +		}else if(cur.pauseBefore){ +			var x = function(){ +				if(resolveAndCallFunc(cur.func)!==false){ +					self._go() +				} +			}; +			window.setTimeout(x, cur.pauseBefore); +		}else{ +			if(resolveAndCallFunc(cur.func)!==false){ +				this._go(); +			} +		} +	}, + +	goOn: function(){ +		// summary: This method just provides a hook from the outside, so that +		// an interrupted sequence can be continued. +		if(this._goOnPause){ +			var self = this; +			setTimeout(function(){ self._go() }, this._goOnPause); +			this._goOnPause = 0; // reset it, so if the next one doesnt set it we dont use the old pause +		}else{ this._go(); } +	}, +	 +	stop: function(){ +		// summary:  Stop the currently running sequence. +		// description:  +		//	This can only interrupt the sequence not the last function that +		//	had been started. If the last function was i.e. a slideshow +		//	that is handled inside a function that you have given as +		//	one sequence item it cant be stopped, since it is not controlled +		//	by this object here. In this case it would be smarter to  +		//	run the slideshow using a sequence object so you can also stop  +		//	it using this method. +		this._running = false; +	} +});  + +} diff --git a/includes/js/dojox/timing/Streamer.js b/includes/js/dojox/timing/Streamer.js new file mode 100644 index 0000000..a6d0cda --- /dev/null +++ b/includes/js/dojox/timing/Streamer.js @@ -0,0 +1,94 @@ +if(!dojo._hasResource["dojox.timing.Streamer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.timing.Streamer"] = true; +dojo.provide("dojox.timing.Streamer"); + +dojo.require("dojox.timing._base"); + +dojox.timing.Streamer = function( +	/* function */input,  +	/* function */output,  +	/* int */interval,  +	/* int */minimum, +	/* array */initialData +){ +	//	summary +	//	Streamer will take an input function that pushes N datapoints into a +	//		queue, and will pass the next point in that queue out to an +	//		output function at the passed interval; this way you can emulate +	//		a constant buffered stream of data. +	//	input: the function executed when the internal queue reaches minimumSize +	//	output: the function executed on internal tick +	//	interval: the interval in ms at which the output function is fired. +	//	minimum: the minimum number of elements in the internal queue. + +	var self = this; +	var queue = []; + +	//	public properties +	this.interval = interval || 1000; +	this.minimumSize = minimum || 10;	//	latency usually == interval * minimumSize +	this.inputFunction = input || function(q){ }; +	this.outputFunction = output || function(point){ }; + +	//	more setup +	var timer = new dojox.timing.Timer(this.interval); +	var tick = function(){ +		self.onTick(self); + +		if(queue.length < self.minimumSize){ +			self.inputFunction(queue); +		} + +		var obj = queue.shift(); +		while(typeof(obj) == "undefined" && queue.length > 0){ +			obj = queue.shift(); +		} +		 +		//	check to see if the input function needs to be fired +		//	stop before firing the output function +		//	TODO: relegate this to the output function? +		if(typeof(obj) == "undefined"){ +			self.stop(); +			return; +		} + +		//	call the output function. +		self.outputFunction(obj); +	}; + +	this.setInterval = function(/* int */ms){ +		//	summary +		//	sets the interval in milliseconds of the internal timer +		this.interval = ms; +		timer.setInterval(ms); +	}; + +	this.onTick = function(/* dojox.timing.Streamer */obj){ }; +	// wrap the timer functions so that we can connect to them if needed. +	this.start = function(){ +		//	summary +		//	starts the Streamer +		if(typeof(this.inputFunction) == "function" && typeof(this.outputFunction) == "function"){ +			timer.start(); +			return; +		} +		throw new Error("You cannot start a Streamer without an input and an output function."); +	}; +	this.onStart = function(){ }; +	this.stop = function(){ +		//	summary +		//	stops the Streamer +		timer.stop(); +	}; +	this.onStop = function(){ }; + +	//	finish initialization +	timer.onTick = this.tick; +	timer.onStart = this.onStart; +	timer.onStop = this.onStop; +	if(initialData){ +		queue.concat(initialData); +	} +}; + +} diff --git a/includes/js/dojox/timing/ThreadPool.js b/includes/js/dojox/timing/ThreadPool.js new file mode 100644 index 0000000..2166a7d --- /dev/null +++ b/includes/js/dojox/timing/ThreadPool.js @@ -0,0 +1,157 @@ +if(!dojo._hasResource["dojox.timing.ThreadPool"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.timing.ThreadPool"] = true; +dojo.provide("dojox.timing.ThreadPool"); +dojo.require("dojox.timing"); + +dojo.experimental("dojox.timing.ThreadPool"); + +//	dojox.timing.Timer is included as part of _base +/******************************************************************** +	This is a port of the original System.Threading.ThreadPool from  +	the f(m) class library. +	 +	Donated to the Dojo toolkit by the author :) +*********************************************************************/ +(function(){ +	var t=dojox.timing; +	t.threadStates={  +		UNSTARTED:"unstarted",  +		STOPPED:"stopped",  +		PENDING:"pending",  +		RUNNING:"running",  +		SUSPENDED:"suspended",  +		WAITING:"waiting",  +		COMPLETE:"complete", +		ERROR:"error" +	}; + +	//	Before rar says a word, we actually *use* these numbers for a purpose :) +	t.threadPriorities={  +		LOWEST:1,  +		BELOWNORMAL:2,  +		NORMAL:3,  +		ABOVENORMAL:4,  +		HIGHEST:5  +	}; +	 +	t.Thread=function(/* Function */fn, /* dojox.timing.threadPriorities? */priority){ +		var self=this; +		this.state=t.threadStates.UNSTARTED; +		this.priority=priority||t.threadPriorities.NORMAL; +		this.lastError=null; +		this.func=fn;	//	for lookup purposes. +		this.invoke=function(){ +			self.state=t.threadStates.RUNNING; +			try{ +				fn(this); +				self.state=t.threadStates.COMPLETE; +			}catch(e){ +				self.lastError=e; +				self.state=t.threadStates.ERROR; +			} +		}; +	}; + +	//	TODO: allow for changing of maxThreads and tick interval +	t.ThreadPool=new (function(/* Number */mxthrs, /* Number */intvl){ +		var self=this; +		var maxThreads=mxthrs; +		var availableThreads=maxThreads; +		var interval=intvl; +		var fireInterval=Math.floor((interval/2)/maxThreads); +		var queue=[]; +		var timers=new Array(maxThreads+1); +		var timer=new dojox.timing.Timer(); +		var invoke=function(){ +			var tracker=timers[0]={}; +			for(var i=0; i<timers.length; i++){ +				window.clearTimeout(timers[i]); +				var thread=queue.shift(); +				if(typeof(thread)=="undefined"){ break; } +				tracker["thread-"+i]=thread; +				timers[i]=window.setTimeout(thread.invoke,(fireInterval*i)); +			} +			availableThreads=maxThreads-(i-1); +		}; + +		//	public methods +		this.getMaxThreads=function(){ return maxThreads; }; +		this.getAvailableThreads=function(){ return availableThreads; }; +		this.getTickInterval=function(){ return interval; }; +		this.queueUserWorkItem=function(/* Function || dojox.timing.Thread */fn){ +			var item=fn; +			if(item instanceof Function){ +				item=new t.Thread(item); +			} +			var idx=queue.length; +			for(var i=0; i<queue.length; i++){ +				if(queue[i].priority<item.priority){ +					idx=i; +					break; +				} +			} +			if(idx<queue.length){ +				queue.splice(idx, 0, item); +			} else { +				queue.push(item); +			} +			return true; +		}; +		this.removeQueuedUserWorkItem=function(/* Function || dojox.timing.Thread */item){ +			if(item instanceof Function){ +				var idx=-1; +				for(var i=0; i<queue.length; i++){ +					if(queue[i].func==item){ +						idx=i; +						break; +					} +				} +				if(idx>-1){ +					queue.splice(idx,1); +					return true; +				} +				return false; +			} + +			var idx=-1; +			for(var i=0; i<queue.length; i++){ +				if(queue[i]==item){ +					idx=i; +					break; +				} +			} +			if(idx>-1){ +				queue.splice(idx,1); +				return true; +			} +			return false; +		}; +		this.start=function(){ timer.start(); }; +		this.stop=function(){ timer.stop(); }; +		this.abort=function(){ +			this.stop(); +			for(var i=1; i<timers.length; i++){ +				if(timers[i]){ +					window.clearTimeout(timers[i]); +				} +			} +			for(var thread in timers[0]){ +				this.queueUserWorkItem(thread); +			} +			timers[0]={}; +		}; +		this.reset=function(){ +			this.abort(); +			queue=[]; +		}; +		this.sleep=function(/* Number */nSleep){ +			timer.stop(); +			window.setTimeout(timer.start, nSleep); +		}; + +		//	dedicate the timer to us. +		timer.onTick=self.invoke; +	})(16, 5000); +})(); + +} diff --git a/includes/js/dojox/timing/_base.js b/includes/js/dojox/timing/_base.js new file mode 100644 index 0000000..4dabebd --- /dev/null +++ b/includes/js/dojox/timing/_base.js @@ -0,0 +1,58 @@ +if(!dojo._hasResource["dojox.timing._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.timing._base"] = true; +dojo.provide("dojox.timing._base"); +dojo.experimental("dojox.timing");  + +dojox.timing.Timer = function(/*int*/ interval){ +	// summary: Timer object executes an "onTick()" method repeatedly at a specified interval.  +	//			repeatedly at a given interval. +	// interval: Interval between function calls, in milliseconds. +	this.timer = null; +	this.isRunning = false; +	this.interval = interval; + +	this.onStart = null; +	this.onStop = null; +}; + +dojo.extend(dojox.timing.Timer, { +	onTick : function(){ +		// summary: Method called every time the interval passes.  Override to do something useful. +	}, +		 +	setInterval : function(interval){ +		// summary: Reset the interval of a timer, whether running or not. +		// interval: New interval, in milliseconds. +		if (this.isRunning){ +			window.clearInterval(this.timer); +		} +		this.interval = interval; +		if (this.isRunning){ +			this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval); +		} +	}, +	 +	start : function(){ +		// summary: Start the timer ticking. +		// description: Calls the "onStart()" handler, if defined. +		// 				Note that the onTick() function is not called right away,  +		//				only after first interval passes. +		if (typeof this.onStart == "function"){ +			this.onStart(); +		} +		this.isRunning = true; +		this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval); +	}, +	 +	stop : function(){ +		// summary: Stop the timer. +		// description: Calls the "onStop()" handler, if defined. +		if (typeof this.onStop == "function"){ +			this.onStop(); +		} +		this.isRunning = false; +		window.clearInterval(this.timer); +	} +}); + +} diff --git a/includes/js/dojox/timing/tests/test_Sequence.html b/includes/js/dojox/timing/tests/test_Sequence.html new file mode 100644 index 0000000..84f4bfb --- /dev/null +++ b/includes/js/dojox/timing/tests/test_Sequence.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +        "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +	<title>dojox.timing.Sequence class</title> +		 +	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script> +	<script type="text/javascript" src="../Sequence.js"></script> +	<style type="text/css"> +		@import "../../../dojo/resources/dojo.css"; +		@import "../../../dijit/themes/dijit.css"; +		@import "../../../dijit/themes/tundra/tundra.css"; +		@import "../../../dijit/tests/css/dijitTests.css"; +	</style> +	<script type="text/javascript"> +		// dojo.require("dojox.timing.Sequence");  + +		var seqObj = null; var outputNode = null; + +		dojo.addOnLoad(function(){ +			outputNode = dojo.byId('logBox');  +			seqObj = new dojox.timing.Sequence({}); +		}); + +		function runSequence(){ +			outputNode.innerHTML = "";  +       			seqObj.go(seq, function() { logMsg('done') }); +		}; + +		function logMsg(msg){ +			outputNode.innerHTML += msg + "<br>";  +		} +	 +		function showMessage(msg) { +                      logMsg(msg); +		} + +              function returnWhenDone() { +                      logMsg("in returnWhenDone"); +                      window.setTimeout(continueSequence,1000); +                      return false; +              } +              function continueSequence() { +                      // continue the sequence run +                      seqObj.goOn(); +              } + +	      // this is our example sequence array: +              var seq = [ +                      {func: [showMessage, window, "i am first"], pauseAfter: 1000}, +                      {func: [showMessage, window, "after 1000ms pause this should be seen"], pauseAfter: 2000}, +                      {func: [showMessage, window, "another 2000ms pause and 1000ms pause before"], pauseAfter: 1000}, +                      {func: [showMessage, window, "repeat 10 times and pause 100ms after"], repeat: 10, pauseAfter: 100}, +                      {func: returnWhenDone} // no array, just a function to call  +              ]; + +	 + + +	</script> +</head> +<body class="tundra"> + +	<h1>dojox.timing.Sequence tests</h1> +	 +	<br>(example code in page source)<br> +	<input type="button" onClick="runSequence()" value="Run Sequence"> + +	<h3>Sequence output:</h3> +	<div id="logBox" style="width:420px; height:250px; overflow:auto; border:1px solid #ccc;"> +	</div> + +	<p>TODO: maybe need to put an _Animation sequence example here? seems much more robust  +	than using chains and combines with delays and durations to hack timing ... also, need +	examples for stop() and other methods of class</p> + +	 + +</body> +</html> diff --git a/includes/js/dojox/timing/tests/test_ThreadPool.html b/includes/js/dojox/timing/tests/test_ThreadPool.html new file mode 100644 index 0000000..53e4bfb --- /dev/null +++ b/includes/js/dojox/timing/tests/test_ThreadPool.html @@ -0,0 +1,16 @@ +<html> +	<head> +		<title>Quick Thread Pool Test</title> +		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true" ></script> +		<script type="text/javascript" src="../ThreadPool.js"></script> +		<style type="text/css"> +			@import "../../../dojo/resources/dojo.css"; +		</style> +		<script type="text/javascript"> +			dojo.require("dojox.timing.ThreadPool"); +		</script> +	</head> +	<body> +		testing. +	</body> +</html>  | 
