|
1 | 1 | /** |
2 | 2 | * jquery.wait - insert simple delays into your jquery method chains |
3 | | - * |
4 | | - * jquery.wait allows you to easily insert a delay into a chain of jquery |
5 | | - * methods. This allows you to use timeouts without uglifying your code and |
6 | | - * without having to use a custom queue. |
7 | | - * |
8 | | - * example: |
9 | | - * // add a class to element #foo, then remove 5 seconds later |
10 | | - * |
11 | | - * // without jquery.wait |
12 | | - * $('#foo').addClass('myClass'); |
13 | | - * window.setTimeout(function(){ |
14 | | - * $('#foo').removeClass('myClass'); |
15 | | - * }, 5000); |
16 | | - * |
17 | | - * // with jquery.wait |
18 | | - * $('#foo').addClass('myClass').wait(5000).removeClass('myClass'); |
19 | | - * |
20 | | - * jquery.wait will work with any default jquery object methods, as well as any |
21 | | - * methods provided by plugins loaded *before* jquery.wait. |
22 | | - * |
23 | | - * !important - if you are using jquery.wait to add/remove classes that controll |
24 | | - * css transitions, the duration of the wait needs to be slightly longer than |
25 | | - * the transition time. So, if in the example above the class .myClass added a |
26 | | - * 5 second transition of some sort, i would need to make the wait time longer. |
27 | | - * I recommend 100ms longer, though your needs may vary depending on the |
28 | | - * complexity of the animation. |
29 | | - * |
30 | | - * If you are chaining jQuery transitions, it is better to use the default |
31 | | - * jquery .delay method, which has the same syntax but works with jquery queues |
32 | | - * |
33 | 3 | * @author Matthew Lee [email protected] |
34 | 4 | */ |
35 | 5 |
|
36 | 6 | (function($){ |
| 7 | + // fake jQuery object that allows us to resolve the entire jQuery method |
| 8 | + // chain, pause, and resume execution later. |
37 | 9 | function jQueryDummy($real, delay, _fncQueue){ |
38 | 10 | var dummy = this; |
39 | | - this.fncQueue = (!!_fncQueue) ? _fncQueue : []; |
40 | | - this.delayCompleted = false; |
41 | | - this.real = $real; |
| 11 | + this._fncQueue = (typeof _fncQueue === 'undefined') ? [] : _fncQueue; |
| 12 | + this._delayCompleted = false; |
| 13 | + this._$real = $real; |
42 | 14 |
|
43 | | - this.timeoutKey = window.setTimeout(function(){ |
44 | | - dummy.performDummyQueueActions.call(dummy); |
45 | | - }, delay); |
| 15 | + if (typeof delay === 'number' && delay > 0 && delay < Infinity) { |
| 16 | + // if a number between 0 and Infinity is given, set a timeout |
| 17 | + this.timeoutKey = window.setTimeout(function(){ |
| 18 | + dummy._performDummyQueueActions(); |
| 19 | + }, delay); |
| 20 | + } else if ((delay !== null) && (typeof delay === 'object') && (typeof delay.promise === 'function')) { |
| 21 | + // if a promise is given, use it |
| 22 | + delay.then(function () { |
| 23 | + dummy._performDummyQueueActions(); |
| 24 | + }); |
| 25 | + } else { |
| 26 | + // otherwise, just return the actual jQuery object and nothing will happen |
| 27 | + return $real; |
| 28 | + } |
46 | 29 | } |
47 | 30 |
|
48 | | - jQueryDummy.prototype.addToQueue = function(fnc, arg){ |
49 | | - if (!this.delayCompleted || this.fncQueue.length > 0) { |
50 | | - this.fncQueue.unshift({ fnc: fnc, arg: arg }); |
51 | | - } |
52 | | - else { |
53 | | - this.real[fnc].apply(this.real, arg); |
| 31 | + // when dummy functions are called, the name of the function and arguments are |
| 32 | + // put into a queue to execute later |
| 33 | + jQueryDummy.prototype._addToQueue = function(fnc, arg){ |
| 34 | + this._fncQueue.unshift({ fnc: fnc, arg: arg }); |
| 35 | + // if we've already finished the wait for some reason, just call them as |
| 36 | + // they get added |
| 37 | + if (this._delayCompleted) { |
| 38 | + return this._performDummyQueueActions(); |
54 | 39 | } |
55 | 40 | return this; |
56 | 41 | }; |
57 | 42 |
|
58 | | - jQueryDummy.prototype.performDummyQueueActions = function(){ |
59 | | - this.delayCompleted = true; |
| 43 | + // when the delay is finished |
| 44 | + jQueryDummy.prototype._performDummyQueueActions = function(){ |
| 45 | + this._delayCompleted = true; |
60 | 46 |
|
61 | 47 | var next; |
62 | | - while (this.fncQueue.length > 0) { |
63 | | - next = this.fncQueue.pop(); |
64 | | - // console.log('performing delayed function '+next.fnc+'('+next.arg+')'); |
| 48 | + while (this._fncQueue.length > 0) { |
| 49 | + next = this._fncQueue.pop(); |
| 50 | + |
| 51 | + console.log(next); |
| 52 | + // if we find another `wait` call in the queue, stop dequeing and pass the |
| 53 | + // remaining queued-up function calls to that wait call |
65 | 54 | if (next.fnc === 'wait') { |
66 | | - next.arg.push(this.fncQueue); |
67 | | - this.real[next.fnc].apply(this.real, next.arg); |
68 | | - break; |
69 | | - } else { |
70 | | - this.real[next.fnc].apply(this.real, next.arg); |
| 55 | + next.arg.push(this._fncQueue); |
| 56 | + return this._$real[next.fnc].apply(this._$real, next.arg); |
71 | 57 | } |
| 58 | + |
| 59 | + this._$real[next.fnc].apply(this._$real, next.arg); |
72 | 60 | } |
73 | | - }; |
74 | 61 |
|
| 62 | + return this; |
| 63 | + }; |
75 | 64 |
|
| 65 | + // creates dummy object that dequeues after a times delay OR promise |
76 | 66 | $.fn.wait = function(delay, _queue) { |
77 | 67 | return new jQueryDummy(this, delay, _queue); |
78 | 68 | }; |
79 | 69 |
|
| 70 | + // |
80 | 71 | for (var fnc in $.fn) { |
| 72 | + // skip non-function properties or properties of Object.prototype |
| 73 | + if ((typeof $.fn[fnc] !== 'function') || !($.fn.hasOwnProperty(fnc))) { |
| 74 | + continue; |
| 75 | + } |
| 76 | + // create a dummy function that queues up a call |
81 | 77 | jQueryDummy.prototype[fnc] = (function(fnc){ |
82 | | - |
83 | 78 | return function(){ |
84 | 79 | var arg = Array.prototype.slice.call(arguments); |
85 | | - return this.addToQueue(fnc, arg); |
| 80 | + return this._addToQueue(fnc, arg); |
86 | 81 | }; |
87 | | - |
88 | 82 | })(fnc); |
89 | 83 | } |
90 | 84 |
|
|
0 commit comments