Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Function.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-Function'>/**
2 </span> * @class Ext.Function
3  *
4  * A collection of useful static methods to deal with function callbacks
5  * @singleton
6  */
7
8 Ext.Function = {
9
10 <span id='Ext-Function-method-flexSetter'>    /**
11 </span>     * A very commonly used method throughout the framework. It acts as a wrapper around another method
12      * which originally accepts 2 arguments for &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;.
13      * The wrapped function then allows &quot;flexible&quot; value setting of either:
14      *
15      * &lt;ul&gt;
16      *      &lt;li&gt;&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; as 2 arguments&lt;/li&gt;
17      *      &lt;li&gt;one single object argument with multiple key - value pairs&lt;/li&gt;
18      * &lt;/ul&gt;
19      *
20      * For example:
21      * &lt;pre&gt;&lt;code&gt;
22 var setValue = Ext.Function.flexSetter(function(name, value) {
23     this[name] = value;
24 });
25
26 // Afterwards
27 // Setting a single name - value
28 setValue('name1', 'value1');
29
30 // Settings multiple name - value pairs
31 setValue({
32     name1: 'value1',
33     name2: 'value2',
34     name3: 'value3'
35 });
36      * &lt;/code&gt;&lt;/pre&gt;
37      * @param {Function} setter
38      * @returns {Function} flexSetter
39      */
40     flexSetter: function(fn) {
41         return function(a, b) {
42             var k, i;
43
44             if (a === null) {
45                 return this;
46             }
47
48             if (typeof a !== 'string') {
49                 for (k in a) {
50                     if (a.hasOwnProperty(k)) {
51                         fn.call(this, k, a[k]);
52                     }
53                 }
54
55                 if (Ext.enumerables) {
56                     for (i = Ext.enumerables.length; i--;) {
57                         k = Ext.enumerables[i];
58                         if (a.hasOwnProperty(k)) {
59                             fn.call(this, k, a[k]);
60                         }
61                     }
62                 }
63             } else {
64                 fn.call(this, a, b);
65             }
66
67             return this;
68         };
69     },
70
71 <span id='Ext-Function-method-bind'>   /**
72 </span>     * Create a new function from the provided &lt;code&gt;fn&lt;/code&gt;, change &lt;code&gt;this&lt;/code&gt; to the provided scope, optionally
73      * overrides arguments for the call. (Defaults to the arguments passed by the caller)
74      *
75      * @param {Function} fn The function to delegate.
76      * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the function is executed.
77      * &lt;b&gt;If omitted, defaults to the browser window.&lt;/b&gt;
78      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
79      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
80      * if a number the args are inserted at the specified position
81      * @return {Function} The new function
82      */
83     bind: function(fn, scope, args, appendArgs) {
84         var method = fn,
85             applyArgs;
86
87         return function() {
88             var callArgs = args || arguments;
89
90             if (appendArgs === true) {
91                 callArgs = Array.prototype.slice.call(arguments, 0);
92                 callArgs = callArgs.concat(args);
93             }
94             else if (Ext.isNumber(appendArgs)) {
95                 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
96                 applyArgs = [appendArgs, 0].concat(args); // create method call params
97                 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
98             }
99
100             return method.apply(scope || window, callArgs);
101         };
102     },
103
104 <span id='Ext-Function-method-pass'>    /**
105 </span>     * Create a new function from the provided &lt;code&gt;fn&lt;/code&gt;, the arguments of which are pre-set to `args`.
106      * New arguments passed to the newly created callback when it's invoked are appended after the pre-set ones.
107      * This is especially useful when creating callbacks.
108      * For example:
109      *
110     var originalFunction = function(){
111         alert(Ext.Array.from(arguments).join(' '));
112     };
113
114     var callback = Ext.Function.pass(originalFunction, ['Hello', 'World']);
115
116     callback(); // alerts 'Hello World'
117     callback('by Me'); // alerts 'Hello World by Me'
118
119      * @param {Function} fn The original function
120      * @param {Array} args The arguments to pass to new callback
121      * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the function is executed.
122      * @return {Function} The new callback function
123      */
124     pass: function(fn, args, scope) {
125         if (args) {
126             args = Ext.Array.from(args);
127         }
128
129         return function() {
130             return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
131         };
132     },
133
134 <span id='Ext-Function-method-alias'>    /**
135 </span>     * Create an alias to the provided method property with name &lt;code&gt;methodName&lt;/code&gt; of &lt;code&gt;object&lt;/code&gt;.
136      * Note that the execution scope will still be bound to the provided &lt;code&gt;object&lt;/code&gt; itself.
137      *
138      * @param {Object/Function} object
139      * @param {String} methodName
140      * @return {Function} aliasFn
141      */
142     alias: function(object, methodName) {
143         return function() {
144             return object[methodName].apply(object, arguments);
145         };
146     },
147
148 <span id='Ext-Function-method-createInterceptor'>    /**
149 </span>     * Creates an interceptor function. The passed function is called before the original one. If it returns false,
150      * the original one is not called. The resulting function returns the results of the original function.
151      * The passed function is called with the parameters of the original function. Example usage:
152      * &lt;pre&gt;&lt;code&gt;
153 var sayHi = function(name){
154     alert('Hi, ' + name);
155 }
156
157 sayHi('Fred'); // alerts &quot;Hi, Fred&quot;
158
159 // create a new function that validates input without
160 // directly modifying the original function:
161 var sayHiToFriend = Ext.Function.createInterceptor(sayHi, function(name){
162     return name == 'Brian';
163 });
164
165 sayHiToFriend('Fred');  // no alert
166 sayHiToFriend('Brian'); // alerts &quot;Hi, Brian&quot;
167      &lt;/code&gt;&lt;/pre&gt;
168      * @param {Function} origFn The original function.
169      * @param {Function} newFn The function to call before the original
170      * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the passed function is executed.
171      * &lt;b&gt;If omitted, defaults to the scope in which the original function is called or the browser window.&lt;/b&gt;
172      * @param {Mixed} returnValue (optional) The value to return if the passed function return false (defaults to null).
173      * @return {Function} The new function
174      */
175     createInterceptor: function(origFn, newFn, scope, returnValue) {
176         var method = origFn;
177         if (!Ext.isFunction(newFn)) {
178             return origFn;
179         }
180         else {
181             return function() {
182                 var me = this,
183                     args = arguments;
184                 newFn.target = me;
185                 newFn.method = origFn;
186                 return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
187             };
188         }
189     },
190
191 <span id='Ext-Function-method-createDelayed'>    /**
192 </span>    * Creates a delegate (callback) which, when called, executes after a specific delay.
193     * @param {Function} fn The function which will be called on a delay when the returned function is called.
194     * Optionally, a replacement (or additional) argument list may be specified.
195     * @param {Number} delay The number of milliseconds to defer execution by whenever called.
196     * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) used by the function at execution time.
197     * @param {Array} args (optional) Override arguments for the call. (Defaults to the arguments passed by the caller)
198     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
199     * if a number the args are inserted at the specified position.
200     * @return {Function} A function which, when called, executes the original function after the specified delay.
201     */
202     createDelayed: function(fn, delay, scope, args, appendArgs) {
203         if (scope || args) {
204             fn = Ext.Function.bind(fn, scope, args, appendArgs);
205         }
206         return function() {
207             var me = this;
208             setTimeout(function() {
209                 fn.apply(me, arguments);
210             }, delay);
211         };
212     },
213
214 <span id='Ext-Function-method-defer'>    /**
215 </span>     * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
216      * &lt;pre&gt;&lt;code&gt;
217 var sayHi = function(name){
218     alert('Hi, ' + name);
219 }
220
221 // executes immediately:
222 sayHi('Fred');
223
224 // executes after 2 seconds:
225 Ext.Function.defer(sayHi, 2000, this, ['Fred']);
226
227 // this syntax is sometimes useful for deferring
228 // execution of an anonymous function:
229 Ext.Function.defer(function(){
230     alert('Anonymous');
231 }, 100);
232      &lt;/code&gt;&lt;/pre&gt;
233      * @param {Function} fn The function to defer.
234      * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
235      * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the function is executed.
236      * &lt;b&gt;If omitted, defaults to the browser window.&lt;/b&gt;
237      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
238      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
239      * if a number the args are inserted at the specified position
240      * @return {Number} The timeout id that can be used with clearTimeout
241      */
242     defer: function(fn, millis, obj, args, appendArgs) {
243         fn = Ext.Function.bind(fn, obj, args, appendArgs);
244         if (millis &gt; 0) {
245             return setTimeout(fn, millis);
246         }
247         fn();
248         return 0;
249     },
250
251 <span id='Ext-Function-method-createSequence'>    /**
252 </span>     * Create a combined function call sequence of the original function + the passed function.
253      * The resulting function returns the results of the original function.
254      * The passed function is called with the parameters of the original function. Example usage:
255      *
256      * &lt;pre&gt;&lt;code&gt;
257 var sayHi = function(name){
258     alert('Hi, ' + name);
259 }
260
261 sayHi('Fred'); // alerts &quot;Hi, Fred&quot;
262
263 var sayGoodbye = Ext.Function.createSequence(sayHi, function(name){
264     alert('Bye, ' + name);
265 });
266
267 sayGoodbye('Fred'); // both alerts show
268      * &lt;/code&gt;&lt;/pre&gt;
269      *
270      * @param {Function} origFn The original function.
271      * @param {Function} newFn The function to sequence
272      * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
273      * If omitted, defaults to the scope in which the original function is called or the browser window.
274      * @return {Function} The new function
275      */
276     createSequence: function(origFn, newFn, scope) {
277         if (!Ext.isFunction(newFn)) {
278             return origFn;
279         }
280         else {
281             return function() {
282                 var retval = origFn.apply(this || window, arguments);
283                 newFn.apply(scope || this || window, arguments);
284                 return retval;
285             };
286         }
287     },
288
289 <span id='Ext-Function-method-createBuffered'>    /**
290 </span>     * &lt;p&gt;Creates a delegate function, optionally with a bound scope which, when called, buffers
291      * the execution of the passed function for the configured number of milliseconds.
292      * If called again within that period, the impending invocation will be canceled, and the
293      * timeout period will begin again.&lt;/p&gt;
294      *
295      * @param {Function} fn The function to invoke on a buffered timer.
296      * @param {Number} buffer The number of milliseconds by which to buffer the invocation of the
297      * function.
298      * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which
299      * the passed function is executed. If omitted, defaults to the scope specified by the caller.
300      * @param {Array} args (optional) Override arguments for the call. Defaults to the arguments
301      * passed by the caller.
302      * @return {Function} A function which invokes the passed function after buffering for the specified time.
303      */
304     createBuffered: function(fn, buffer, scope, args) {
305         return function(){
306             var timerId;
307             return function() {
308                 var me = this;
309                 if (timerId) {
310                     clearInterval(timerId);
311                     timerId = null;
312                 }
313                 timerId = setTimeout(function(){
314                     fn.apply(scope || me, args || arguments);
315                 }, buffer);
316             };
317         }();
318     },
319
320 <span id='Ext-Function-method-createThrottled'>    /**
321 </span>     * &lt;p&gt;Creates a throttled version of the passed function which, when called repeatedly and
322      * rapidly, invokes the passed function only after a certain interval has elapsed since the
323      * previous invocation.&lt;/p&gt;
324      *
325      * &lt;p&gt;This is useful for wrapping functions which may be called repeatedly, such as
326      * a handler of a mouse move event when the processing is expensive.&lt;/p&gt;
327      *
328      * @param fn {Function} The function to execute at a regular time interval.
329      * @param interval {Number} The interval &lt;b&gt;in milliseconds&lt;/b&gt; on which the passed function is executed.
330      * @param scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which
331      * the passed function is executed. If omitted, defaults to the scope specified by the caller.
332      * @returns {Function} A function which invokes the passed function at the specified interval.
333      */
334     createThrottled: function(fn, interval, scope) {
335         var lastCallTime, elapsed, lastArgs, timer, execute = function() {
336             fn.apply(scope || this, lastArgs);
337             lastCallTime = new Date().getTime();
338         };
339
340         return function() {
341             elapsed = new Date().getTime() - lastCallTime;
342             lastArgs = arguments;
343
344             clearTimeout(timer);
345             if (!lastCallTime || (elapsed &gt;= interval)) {
346                 execute();
347             } else {
348                 timer = setTimeout(execute, interval - elapsed);
349             }
350         };
351     }
352 };
353
354 <span id='Ext-method-defer'>/**
355 </span> * Shorthand for {@link Ext.Function#defer}
356  * @member Ext
357  * @method defer
358  */
359 Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
360
361 <span id='Ext-method-pass'>/**
362 </span> * Shorthand for {@link Ext.Function#pass}
363  * @member Ext
364  * @method pass
365  */
366 Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
367
368 <span id='Ext-method-bind'>/**
369 </span> * Shorthand for {@link Ext.Function#bind}
370  * @member Ext
371  * @method bind
372  */
373 Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
374 </pre></pre></body></html>