Function2.html 20 KB

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