aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dojox/timing
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/timing')
-rw-r--r--includes/js/dojox/timing/README58
-rw-r--r--includes/js/dojox/timing/Sequence.js145
-rw-r--r--includes/js/dojox/timing/Streamer.js94
-rw-r--r--includes/js/dojox/timing/ThreadPool.js157
-rw-r--r--includes/js/dojox/timing/_base.js58
-rw-r--r--includes/js/dojox/timing/tests/test_Sequence.html80
-rw-r--r--includes/js/dojox/timing/tests/test_ThreadPool.html16
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>