aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dojox/timing/Sequence.js
blob: 4dc4bdba0b7787ce9e70150969c28a342bb946a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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;
	}
}); 

}