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> |