Upgrade to ExtJS 3.3.0 - Released 10/06/2010
[extjs.git] / src / util / Function.js
1 /*!
2  * Ext JS Library 3.3.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.util.Functions
9  * @singleton
10  */
11 Ext.util.Functions = {
12     /**
13      * Creates an interceptor function. The passed function is called before the original one. If it returns false,
14      * the original one is not called. The resulting function returns the results of the original function.
15      * The passed function is called with the parameters of the original function. Example usage:
16      * <pre><code>
17 var sayHi = function(name){
18     alert('Hi, ' + name);
19 }
20
21 sayHi('Fred'); // alerts "Hi, Fred"
22
23 // create a new function that validates input without
24 // directly modifying the original function:
25 var sayHiToFriend = Ext.createInterceptor(sayHi, function(name){
26     return name == 'Brian';
27 });
28
29 sayHiToFriend('Fred');  // no alert
30 sayHiToFriend('Brian'); // alerts "Hi, Brian"
31        </code></pre>
32      * @param {Function} origFn The original function.
33      * @param {Function} newFn The function to call before the original
34      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
35      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
36      * @return {Function} The new function
37      */
38     createInterceptor: function(origFn, newFn, scope) { 
39         var method = origFn;
40         if (!Ext.isFunction(newFn)) {
41             return origFn;
42         }
43         else {
44             return function() {
45                 var me = this,
46                     args = arguments;
47                 newFn.target = me;
48                 newFn.method = origFn;
49                 return (newFn.apply(scope || me || window, args) !== false) ?
50                         origFn.apply(me || window, args) :
51                         null;
52             };
53         }
54     },
55
56     /**
57      * Creates a delegate (callback) that sets the scope to obj.
58      * Call directly on any function. Example: <code>Ext.createDelegate(this.myFunction, this, [arg1, arg2])</code>
59      * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
60      * callback points to obj. Example usage:
61      * <pre><code>
62 var sayHi = function(name){
63     // Note this use of "this.text" here.  This function expects to
64     // execute within a scope that contains a text property.  In this
65     // example, the "this" variable is pointing to the btn object that
66     // was passed in createDelegate below.
67     alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
68 }
69
70 var btn = new Ext.Button({
71     text: 'Say Hi',
72     renderTo: Ext.getBody()
73 });
74
75 // This callback will execute in the scope of the
76 // button instance. Clicking the button alerts
77 // "Hi, Fred. You clicked the "Say Hi" button."
78 btn.on('click', Ext.createDelegate(sayHi, btn, ['Fred']));
79        </code></pre>
80      * @param {Function} fn The function to delegate.
81      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
82      * <b>If omitted, defaults to the browser window.</b>
83      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
84      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
85      * if a number the args are inserted at the specified position
86      * @return {Function} The new function
87      */
88     createDelegate: function(fn, obj, args, appendArgs) {
89         if (!Ext.isFunction(fn)) {
90             return fn;
91         }
92         return function() {
93             var callArgs = args || arguments;
94             if (appendArgs === true) {
95                 callArgs = Array.prototype.slice.call(arguments, 0);
96                 callArgs = callArgs.concat(args);
97             }
98             else if (Ext.isNumber(appendArgs)) {
99                 callArgs = Array.prototype.slice.call(arguments, 0);
100                 // copy arguments first
101                 var applyArgs = [appendArgs, 0].concat(args);
102                 // create method call params
103                 Array.prototype.splice.apply(callArgs, applyArgs);
104                 // splice them in
105             }
106             return fn.apply(obj || window, callArgs);
107         };
108     },
109
110     /**
111      * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
112      * <pre><code>
113 var sayHi = function(name){
114     alert('Hi, ' + name);
115 }
116
117 // executes immediately:
118 sayHi('Fred');
119
120 // executes after 2 seconds:
121 Ext.defer(sayHi, 2000, this, ['Fred']);
122
123 // this syntax is sometimes useful for deferring
124 // execution of an anonymous function:
125 Ext.defer(function(){
126     alert('Anonymous');
127 }, 100);
128        </code></pre>
129      * @param {Function} fn The function to defer.
130      * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
131      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
132      * <b>If omitted, defaults to the browser window.</b>
133      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
134      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
135      * if a number the args are inserted at the specified position
136      * @return {Number} The timeout id that can be used with clearTimeout
137      */
138     defer: function(fn, millis, obj, args, appendArgs) {
139         fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
140         if (millis > 0) {
141             return setTimeout(fn, millis);
142         }
143         fn();
144         return 0;
145     },
146
147
148     /**
149      * Create a combined function call sequence of the original function + the passed function.
150      * The resulting function returns the results of the original function.
151      * The passed fcn is called with the parameters of the original function. Example usage:
152      * 
153
154 var sayHi = function(name){
155     alert('Hi, ' + name);
156 }
157
158 sayHi('Fred'); // alerts "Hi, Fred"
159
160 var sayGoodbye = Ext.createSequence(sayHi, function(name){
161     alert('Bye, ' + name);
162 });
163
164 sayGoodbye('Fred'); // both alerts show
165
166      * @param {Function} origFn The original function.
167      * @param {Function} newFn The function to sequence
168      * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
169      * If omitted, defaults to the scope in which the original function is called or the browser window.
170      * @return {Function} The new function
171      */
172     createSequence: function(origFn, newFn, scope) {
173         if (!Ext.isFunction(newFn)) {
174             return origFn;
175         }
176         else {
177             return function() {
178                 var retval = origFn.apply(this || window, arguments);
179                 newFn.apply(scope || this || window, arguments);
180                 return retval;
181             };
182         }
183     }
184 };
185
186 /**
187  * Shorthand for {@link Ext.util.Functions#defer}   
188  * @param {Function} fn The function to defer.
189  * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
190  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
191  * <b>If omitted, defaults to the browser window.</b>
192  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
193  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
194  * if a number the args are inserted at the specified position
195  * @return {Number} The timeout id that can be used with clearTimeout
196  * @member Ext
197  * @method defer
198  */
199
200 Ext.defer = Ext.util.Functions.defer;
201
202 /**
203  * Shorthand for {@link Ext.util.Functions#createInterceptor}   
204  * @param {Function} origFn The original function.
205  * @param {Function} newFn The function to call before the original
206  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
207  * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
208  * @return {Function} The new function
209  * @member Ext
210  * @method defer
211  */
212
213 Ext.createInterceptor = Ext.util.Functions.createInterceptor;
214
215 /**
216  * Shorthand for {@link Ext.util.Functions#createSequence}
217  * @param {Function} origFn The original function.
218  * @param {Function} newFn The function to sequence
219  * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
220  * If omitted, defaults to the scope in which the original function is called or the browser window.
221  * @return {Function} The new function
222  * @member Ext
223  * @method defer
224  */
225
226 Ext.createSequence = Ext.util.Functions.createSequence;
227
228 /**
229  * Shorthand for {@link Ext.util.Functions#createDelegate}
230  * @param {Function} fn The function to delegate.
231  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
232  * <b>If omitted, defaults to the browser window.</b>
233  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
234  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
235  * if a number the args are inserted at the specified position
236  * @return {Function} The new function
237  * @member Ext
238  * @method defer
239  */
240 Ext.createDelegate = Ext.util.Functions.createDelegate;