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