1/**
2 * jQuery.timers - Timer abstractions for jQuery
3 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
4 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
5 * Date: 2009/02/08
6 *
7 * @author Blair Mitchelmore
8 * @version 1.1.2
9 *
10 **/
11
12jQuery.fn.extend({
13	everyTime: function(interval, label, fn, times, belay) {
14		return this.each(function() {
15			jQuery.timer.add(this, interval, label, fn, times, belay);
16		});
17	},
18	oneTime: function(interval, label, fn) {
19		return this.each(function() {
20			jQuery.timer.add(this, interval, label, fn, 1);
21		});
22	},
23	stopTime: function(label, fn) {
24		return this.each(function() {
25			jQuery.timer.remove(this, label, fn);
26		});
27	}
28});
29
30jQuery.event.special
31
32jQuery.extend({
33	timer: {
34		global: [],
35		guid: 1,
36		dataKey: "jQuery.timer",
37		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
38		powers: {
39			// Yeah this is major overkill...
40			'ms': 1,
41			'cs': 10,
42			'ds': 100,
43			's': 1000,
44			'das': 10000,
45			'hs': 100000,
46			'ks': 1000000
47		},
48		timeParse: function(value) {
49			if (value == undefined || value == null)
50				return null;
51			var result = this.regex.exec(jQuery.trim(value.toString()));
52			if (result[2]) {
53				var num = parseFloat(result[1]);
54				var mult = this.powers[result[2]] || 1;
55				return num * mult;
56			} else {
57				return value;
58			}
59		},
60		add: function(element, interval, label, fn, times, belay) {
61			var counter = 0;
62
63			if (jQuery.isFunction(label)) {
64				if (!times)
65					times = fn;
66				fn = label;
67				label = interval;
68			}
69
70			interval = jQuery.timer.timeParse(interval);
71
72			if (typeof interval != 'number' || isNaN(interval) || interval <= 0)
73				return;
74
75			if (times && times.constructor != Number) {
76				belay = !!times;
77				times = 0;
78			}
79
80			times = times || 0;
81			belay = belay || false;
82
83			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
84
85			if (!timers[label])
86				timers[label] = {};
87
88			fn.timerID = fn.timerID || this.guid++;
89
90			var handler = function() {
91				if (belay && this.inProgress)
92					return;
93				this.inProgress = true;
94				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
95					jQuery.timer.remove(element, label, fn);
96				this.inProgress = false;
97			};
98
99			handler.timerID = fn.timerID;
100
101			if (!timers[label][fn.timerID])
102				timers[label][fn.timerID] = window.setInterval(handler,interval);
103
104			this.global.push( element );
105
106		},
107		remove: function(element, label, fn) {
108			var timers = jQuery.data(element, this.dataKey), ret;
109
110			if ( timers ) {
111
112				if (!label) {
113					for ( label in timers )
114						this.remove(element, label, fn);
115				} else if ( timers[label] ) {
116					if ( fn ) {
117						if ( fn.timerID ) {
118							window.clearInterval(timers[label][fn.timerID]);
119							delete timers[label][fn.timerID];
120						}
121					} else {
122						for ( var fn in timers[label] ) {
123							window.clearInterval(timers[label][fn]);
124							delete timers[label][fn];
125						}
126					}
127
128					for ( ret in timers[label] ) break;
129					if ( !ret ) {
130						ret = null;
131						delete timers[label];
132					}
133				}
134
135				for ( ret in timers ) break;
136				if ( !ret )
137					jQuery.removeData(element, this.dataKey);
138			}
139		}
140	}
141});
142
143jQuery(window).bind("unload", function() {
144	jQuery.each(jQuery.timer.global, function(index, item) {
145		jQuery.timer.remove(item);
146	});
147});