<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js">// @tag foundation,core
|
// @require Array.js
|
// @define Ext.Function
|
|
<span id='Ext-Function'>/**
|
</span> * @class Ext.Function
|
*
|
* A collection of useful static methods to deal with function callbacks
|
* @singleton
|
* @alternateClassName Ext.util.Functions
|
*/
|
Ext.Function = {
|
|
<span id='Ext-Function-method-flexSetter'> /**
|
</span> * A very commonly used method throughout the framework. It acts as a wrapper around another method
|
* which originally accepts 2 arguments for `name` and `value`.
|
* The wrapped function then allows "flexible" value setting of either:
|
*
|
* - `name` and `value` as 2 arguments
|
* - one single object argument with multiple key - value pairs
|
*
|
* For example:
|
*
|
* var setValue = Ext.Function.flexSetter(function(name, value) {
|
* this[name] = value;
|
* });
|
*
|
* // Afterwards
|
* // Setting a single name - value
|
* setValue('name1', 'value1');
|
*
|
* // Settings multiple name - value pairs
|
* setValue({
|
* name1: 'value1',
|
* name2: 'value2',
|
* name3: 'value3'
|
* });
|
*
|
* @param {Function} setter
|
* @returns {Function} flexSetter
|
*/
|
flexSetter: function(fn) {
|
return function(a, b) {
|
var k, i;
|
|
if (a === null) {
|
return this;
|
}
|
|
if (typeof a !== 'string') {
|
for (k in a) {
|
if (a.hasOwnProperty(k)) {
|
fn.call(this, k, a[k]);
|
}
|
}
|
|
if (Ext.enumerables) {
|
for (i = Ext.enumerables.length; i--;) {
|
k = Ext.enumerables[i];
|
if (a.hasOwnProperty(k)) {
|
fn.call(this, k, a[k]);
|
}
|
}
|
}
|
} else {
|
fn.call(this, a, b);
|
}
|
|
return this;
|
};
|
},
|
|
<span id='Ext-Function-method-bind'> /**
|
</span> * Create a new function from the provided `fn`, change `this` to the provided scope, optionally
|
* overrides arguments for the call. (Defaults to the arguments passed by the caller)
|
*
|
* {@link Ext#bind Ext.bind} is alias for {@link Ext.Function#bind Ext.Function.bind}
|
*
|
* @param {Function} fn The function to delegate.
|
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
|
* **If omitted, defaults to the default global environment object (usually the browser window).**
|
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
|
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
|
* if a number the args are inserted at the specified position
|
* @return {Function} The new function
|
*/
|
bind: function(fn, scope, args, appendArgs) {
|
if (arguments.length === 2) {
|
return function() {
|
return fn.apply(scope, arguments);
|
};
|
}
|
|
var method = fn,
|
slice = Array.prototype.slice;
|
|
return function() {
|
var callArgs = args || arguments;
|
|
if (appendArgs === true) {
|
callArgs = slice.call(arguments, 0);
|
callArgs = callArgs.concat(args);
|
}
|
else if (typeof appendArgs == 'number') {
|
callArgs = slice.call(arguments, 0); // copy arguments first
|
Ext.Array.insert(callArgs, appendArgs, args);
|
}
|
|
return method.apply(scope || Ext.global, callArgs);
|
};
|
},
|
|
<span id='Ext-Function-method-pass'> /**
|
</span> * Create a new function from the provided `fn`, the arguments of which are pre-set to `args`.
|
* New arguments passed to the newly created callback when it's invoked are appended after the pre-set ones.
|
* This is especially useful when creating callbacks.
|
*
|
* For example:
|
*
|
* var originalFunction = function(){
|
* alert(Ext.Array.from(arguments).join(' '));
|
* };
|
*
|
* var callback = Ext.Function.pass(originalFunction, ['Hello', 'World']);
|
*
|
* callback(); // alerts 'Hello World'
|
* callback('by Me'); // alerts 'Hello World by Me'
|
*
|
* {@link Ext#pass Ext.pass} is alias for {@link Ext.Function#pass Ext.Function.pass}
|
*
|
* @param {Function} fn The original function
|
* @param {Array} args The arguments to pass to new callback
|
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
|
* @return {Function} The new callback function
|
*/
|
pass: function(fn, args, scope) {
|
if (!Ext.isArray(args)) {
|
if (Ext.isIterable(args)) {
|
args = Ext.Array.clone(args);
|
} else {
|
args = args !== undefined ? [args] : [];
|
}
|
}
|
|
return function() {
|
var fnArgs = [].concat(args);
|
fnArgs.push.apply(fnArgs, arguments);
|
return fn.apply(scope || this, fnArgs);
|
};
|
},
|
|
<span id='Ext-Function-method-alias'> /**
|
</span> * Create an alias to the provided method property with name `methodName` of `object`.
|
* Note that the execution scope will still be bound to the provided `object` itself.
|
*
|
* @param {Object/Function} object
|
* @param {String} methodName
|
* @return {Function} aliasFn
|
*/
|
alias: function(object, methodName) {
|
return function() {
|
return object[methodName].apply(object, arguments);
|
};
|
},
|
|
<span id='Ext-Function-method-clone'> /**
|
</span> * Create a "clone" of the provided method. The returned method will call the given
|
* method passing along all arguments and the "this" pointer and return its result.
|
*
|
* @param {Function} method
|
* @return {Function} cloneFn
|
*/
|
clone: function(method) {
|
return function() {
|
return method.apply(this, arguments);
|
};
|
},
|
|
<span id='Ext-Function-method-createInterceptor'> /**
|
</span> * Creates an interceptor function. The passed function is called before the original one. If it returns false,
|
* the original one is not called. The resulting function returns the results of the original function.
|
* The passed function is called with the parameters of the original function. Example usage:
|
*
|
* var sayHi = function(name){
|
* alert('Hi, ' + name);
|
* }
|
*
|
* sayHi('Fred'); // alerts "Hi, Fred"
|
*
|
* // create a new function that validates input without
|
* // directly modifying the original function:
|
* var sayHiToFriend = Ext.Function.createInterceptor(sayHi, function(name){
|
* return name == 'Brian';
|
* });
|
*
|
* sayHiToFriend('Fred'); // no alert
|
* sayHiToFriend('Brian'); // alerts "Hi, Brian"
|
*
|
* @param {Function} origFn The original function.
|
* @param {Function} newFn The function to call before the original
|
* @param {Object} [scope] The scope (`this` reference) in which the passed function is executed.
|
* **If omitted, defaults to the scope in which the original function is called or the browser window.**
|
* @param {Object} [returnValue=null] The value to return if the passed function return false.
|
* @return {Function} The new function
|
*/
|
createInterceptor: function(origFn, newFn, scope, returnValue) {
|
var method = origFn;
|
if (!Ext.isFunction(newFn)) {
|
return origFn;
|
} else {
|
returnValue = Ext.isDefined(returnValue) ? returnValue : null;
|
return function() {
|
var me = this,
|
args = arguments;
|
|
newFn.target = me;
|
newFn.method = origFn;
|
return (newFn.apply(scope || me || Ext.global, args) !== false) ? origFn.apply(me || Ext.global, args) : returnValue;
|
};
|
}
|
},
|
|
<span id='Ext-Function-method-createDelayed'> /**
|
</span> * Creates a delegate (callback) which, when called, executes after a specific delay.
|
*
|
* @param {Function} fn The function which will be called on a delay when the returned function is called.
|
* Optionally, a replacement (or additional) argument list may be specified.
|
* @param {Number} delay The number of milliseconds to defer execution by whenever called.
|
* @param {Object} scope (optional) The scope (`this` reference) used by the function at execution time.
|
* @param {Array} args (optional) Override arguments for the call. (Defaults to the arguments passed by the caller)
|
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
|
* if a number the args are inserted at the specified position.
|
* @return {Function} A function which, when called, executes the original function after the specified delay.
|
*/
|
createDelayed: function(fn, delay, scope, args, appendArgs) {
|
if (scope || args) {
|
fn = Ext.Function.bind(fn, scope, args, appendArgs);
|
}
|
|
return function() {
|
var me = this,
|
args = Array.prototype.slice.call(arguments);
|
|
setTimeout(function() {
|
fn.apply(me, args);
|
}, delay);
|
};
|
},
|
|
<span id='Ext-Function-method-defer'> /**
|
</span> * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
|
*
|
* var sayHi = function(name){
|
* alert('Hi, ' + name);
|
* }
|
*
|
* // executes immediately:
|
* sayHi('Fred');
|
*
|
* // executes after 2 seconds:
|
* Ext.Function.defer(sayHi, 2000, this, ['Fred']);
|
*
|
* // this syntax is sometimes useful for deferring
|
* // execution of an anonymous function:
|
* Ext.Function.defer(function(){
|
* alert('Anonymous');
|
* }, 100);
|
*
|
* {@link Ext#defer Ext.defer} is alias for {@link Ext.Function#defer Ext.Function.defer}
|
*
|
* @param {Function} fn The function to defer.
|
* @param {Number} millis The number of milliseconds for the setTimeout call
|
* (if less than or equal to 0 the function is executed immediately)
|
* @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
|
* **If omitted, defaults to the browser window.**
|
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
|
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
|
* if a number the args are inserted at the specified position
|
* @return {Number} The timeout id that can be used with clearTimeout
|
*/
|
defer: function(fn, millis, scope, args, appendArgs) {
|
fn = Ext.Function.bind(fn, scope, args, appendArgs);
|
if (millis > 0) {
|
return setTimeout(Ext.supports.TimeoutActualLateness ? function () {
|
fn();
|
} : fn, millis);
|
}
|
fn();
|
return 0;
|
},
|
|
<span id='Ext-Function-method-createSequence'> /**
|
</span> * Create a combined function call sequence of the original function + the passed function.
|
* The resulting function returns the results of the original function.
|
* The passed function is called with the parameters of the original function. Example usage:
|
*
|
* var sayHi = function(name){
|
* alert('Hi, ' + name);
|
* }
|
*
|
* sayHi('Fred'); // alerts "Hi, Fred"
|
*
|
* var sayGoodbye = Ext.Function.createSequence(sayHi, function(name){
|
* alert('Bye, ' + name);
|
* });
|
*
|
* sayGoodbye('Fred'); // both alerts show
|
*
|
* @param {Function} originalFn The original function.
|
* @param {Function} newFn The function to sequence
|
* @param {Object} scope (optional) The scope (`this` reference) in which the passed function is executed.
|
* If omitted, defaults to the scope in which the original function is called or the default global environment object (usually the browser window).
|
* @return {Function} The new function
|
*/
|
createSequence: function(originalFn, newFn, scope) {
|
if (!newFn) {
|
return originalFn;
|
}
|
else {
|
return function() {
|
var result = originalFn.apply(this, arguments);
|
newFn.apply(scope || this, arguments);
|
return result;
|
};
|
}
|
},
|
|
<span id='Ext-Function-method-createBuffered'> /**
|
</span> * Creates a delegate function, optionally with a bound scope which, when called, buffers
|
* the execution of the passed function for the configured number of milliseconds.
|
* If called again within that period, the impending invocation will be canceled, and the
|
* timeout period will begin again.
|
*
|
* @param {Function} fn The function to invoke on a buffered timer.
|
* @param {Number} buffer The number of milliseconds by which to buffer the invocation of the
|
* function.
|
* @param {Object} scope (optional) The scope (`this` reference) in which
|
* the passed function is executed. If omitted, defaults to the scope specified by the caller.
|
* @param {Array} args (optional) Override arguments for the call. Defaults to the arguments
|
* passed by the caller.
|
* @return {Function} A function which invokes the passed function after buffering for the specified time.
|
*/
|
createBuffered: function(fn, buffer, scope, args) {
|
var timerId;
|
|
return function() {
|
var callArgs = args || Array.prototype.slice.call(arguments, 0),
|
me = scope || this;
|
|
if (timerId) {
|
clearTimeout(timerId);
|
}
|
|
timerId = setTimeout(function(){
|
fn.apply(me, callArgs);
|
}, buffer);
|
};
|
},
|
|
<span id='Ext-Function-method-createThrottled'> /**
|
</span> * Creates a throttled version of the passed function which, when called repeatedly and
|
* rapidly, invokes the passed function only after a certain interval has elapsed since the
|
* previous invocation.
|
*
|
* This is useful for wrapping functions which may be called repeatedly, such as
|
* a handler of a mouse move event when the processing is expensive.
|
*
|
* @param {Function} fn The function to execute at a regular time interval.
|
* @param {Number} interval The interval **in milliseconds** on which the passed function is executed.
|
* @param {Object} scope (optional) The scope (`this` reference) in which
|
* the passed function is executed. If omitted, defaults to the scope specified by the caller.
|
* @returns {Function} A function which invokes the passed function at the specified interval.
|
*/
|
createThrottled: function(fn, interval, scope) {
|
var lastCallTime, elapsed, lastArgs, timer, execute = function() {
|
fn.apply(scope || this, lastArgs);
|
lastCallTime = Ext.Date.now();
|
};
|
|
return function() {
|
elapsed = Ext.Date.now() - lastCallTime;
|
lastArgs = arguments;
|
|
clearTimeout(timer);
|
if (!lastCallTime || (elapsed >= interval)) {
|
execute();
|
} else {
|
timer = setTimeout(execute, interval - elapsed);
|
}
|
};
|
},
|
|
|
<span id='Ext-Function-method-interceptBefore'> /**
|
</span> * Adds behavior to an existing method that is executed before the
|
* original behavior of the function. For example:
|
*
|
* var soup = {
|
* contents: [],
|
* add: function(ingredient) {
|
* this.contents.push(ingredient);
|
* }
|
* };
|
* Ext.Function.interceptBefore(soup, "add", function(ingredient){
|
* if (!this.contents.length && ingredient !== "water") {
|
* // Always add water to start with
|
* this.contents.push("water");
|
* }
|
* });
|
* soup.add("onions");
|
* soup.add("salt");
|
* soup.contents; // will contain: water, onions, salt
|
*
|
* @param {Object} object The target object
|
* @param {String} methodName Name of the method to override
|
* @param {Function} fn Function with the new behavior. It will
|
* be called with the same arguments as the original method. The
|
* return value of this function will be the return value of the
|
* new method.
|
* @param {Object} [scope] The scope to execute the interceptor function. Defaults to the object.
|
* @return {Function} The new function just created.
|
*/
|
interceptBefore: function(object, methodName, fn, scope) {
|
var method = object[methodName] || Ext.emptyFn;
|
|
return (object[methodName] = function() {
|
var ret = fn.apply(scope || this, arguments);
|
method.apply(this, arguments);
|
|
return ret;
|
});
|
},
|
|
<span id='Ext-Function-method-interceptAfter'> /**
|
</span> * Adds behavior to an existing method that is executed after the
|
* original behavior of the function. For example:
|
*
|
* var soup = {
|
* contents: [],
|
* add: function(ingredient) {
|
* this.contents.push(ingredient);
|
* }
|
* };
|
* Ext.Function.interceptAfter(soup, "add", function(ingredient){
|
* // Always add a bit of extra salt
|
* this.contents.push("salt");
|
* });
|
* soup.add("water");
|
* soup.add("onions");
|
* soup.contents; // will contain: water, salt, onions, salt
|
*
|
* @param {Object} object The target object
|
* @param {String} methodName Name of the method to override
|
* @param {Function} fn Function with the new behavior. It will
|
* be called with the same arguments as the original method. The
|
* return value of this function will be the return value of the
|
* new method.
|
* @param {Object} [scope] The scope to execute the interceptor function. Defaults to the object.
|
* @return {Function} The new function just created.
|
*/
|
interceptAfter: function(object, methodName, fn, scope) {
|
var method = object[methodName] || Ext.emptyFn;
|
|
return (object[methodName] = function() {
|
method.apply(this, arguments);
|
return fn.apply(scope || this, arguments);
|
});
|
}
|
};
|
|
<span id='Ext-method-defer'>/**
|
</span> * @method
|
* @member Ext
|
* @inheritdoc Ext.Function#defer
|
*/
|
Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
|
|
<span id='Ext-method-pass'>/**
|
</span> * @method
|
* @member Ext
|
* @inheritdoc Ext.Function#pass
|
*/
|
Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
|
|
<span id='Ext-method-bind'>/**
|
</span> * @method
|
* @member Ext
|
* @inheritdoc Ext.Function#bind
|
*/
|
Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
|
</pre>
|
</body>
|
</html>
|