Upgrade to ExtJS 3.2.1 - Released 04/27/2010
[extjs.git] / docs / source / Ext-more.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.2.1
11  * Copyright(c) 2006-2010 Ext JS, Inc.
12  * licensing@extjs.com
13  * http://www.extjs.com/license
14  */
15 /**
16  * @class Ext
17  */
18
19 Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
20        "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
21     <div id="prop-Ext-ux"></div>/**
22      * Namespace alloted for extensions to the framework.
23      * @property ux
24      * @type Object
25      */
26
27 Ext.apply(Ext, function(){
28     var E = Ext,
29         idSeed = 0,
30         scrollWidth = null;
31
32     return {
33         <div id="prop-Ext-emptyFn"></div>/**
34         * A reusable empty function
35         * @property
36         * @type Function
37         */
38         emptyFn : function(){},
39
40         <div id="prop-Ext-BLANK_IMAGE_URL"></div>/**
41          * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images.
42          * In older versions of IE, this defaults to "http://extjs.com/s.gif" and you should change this to a URL on your server.
43          * For other browsers it uses an inline data URL.
44          * @type String
45          */
46         BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
47                             'http:/' + '/www.extjs.com/s.gif' :
48                             'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
49
50         extendX : function(supr, fn){
51             return Ext.extend(supr, fn(supr.prototype));
52         },
53
54         <div id="method-Ext-getDoc"></div>/**
55          * Returns the current HTML document object as an {@link Ext.Element}.
56          * @return Ext.Element The document
57          */
58         getDoc : function(){
59             return Ext.get(document);
60         },
61
62         <div id="method-Ext-num"></div>/**
63          * Utility method for validating that a value is numeric, returning the specified default value if it is not.
64          * @param {Mixed} value Should be a number, but any type will be handled appropriately
65          * @param {Number} defaultValue The value to return if the original value is non-numeric
66          * @return {Number} Value, if numeric, else defaultValue
67          */
68         num : function(v, defaultValue){
69             v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
70             return isNaN(v) ? defaultValue : v;
71         },
72
73         <div id="method-Ext-value"></div>/**
74          * <p>Utility method for returning a default value if the passed value is empty.</p>
75          * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
76          * <li>null</li>
77          * <li>undefined</li>
78          * <li>an empty array</li>
79          * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
80          * </ul></div>
81          * @param {Mixed} value The value to test
82          * @param {Mixed} defaultValue The value to return if the original value is empty
83          * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
84          * @return {Mixed} value, if non-empty, else defaultValue
85          */
86         value : function(v, defaultValue, allowBlank){
87             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
88         },
89
90         <div id="method-Ext-escapeRe"></div>/**
91          * Escapes the passed string for use in a regular expression
92          * @param {String} str
93          * @return {String}
94          */
95         escapeRe : function(s) {
96             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
97         },
98
99         sequence : function(o, name, fn, scope){
100             o[name] = o[name].createSequence(fn, scope);
101         },
102
103         <div id="method-Ext-addBehaviors"></div>/**
104          * Applies event listeners to elements by selectors when the document is ready.
105          * The event name is specified with an <tt>&#64;</tt> suffix.
106          * <pre><code>
107 Ext.addBehaviors({
108     // add a listener for click on all anchors in element with id foo
109     '#foo a&#64;click' : function(e, t){
110         // do something
111     },
112
113     // add the same listener to multiple selectors (separated by comma BEFORE the &#64;)
114     '#foo a, #bar span.some-class&#64;mouseover' : function(){
115         // do something
116     }
117 });
118          * </code></pre>
119          * @param {Object} obj The list of behaviors to apply
120          */
121         addBehaviors : function(o){
122             if(!Ext.isReady){
123                 Ext.onReady(function(){
124                     Ext.addBehaviors(o);
125                 });
126             } else {
127                 var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
128                     parts,
129                     b,
130                     s;
131                 for (b in o) {
132                     if ((parts = b.split('@'))[1]) { // for Object prototype breakers
133                         s = parts[0];
134                         if(!cache[s]){
135                             cache[s] = Ext.select(s);
136                         }
137                         cache[s].on(parts[1], o[b]);
138                     }
139                 }
140                 cache = null;
141             }
142         },
143
144         <div id="method-Ext-getScrollBarWidth"></div>/**
145          * Utility method for getting the width of the browser scrollbar. This can differ depending on
146          * operating system settings, such as the theme or font size.
147          * @param {Boolean} force (optional) true to force a recalculation of the value.
148          * @return {Number} The width of the scrollbar.
149          */
150         getScrollBarWidth: function(force){
151             if(!Ext.isReady){
152                 return 0;
153             }
154
155             if(force === true || scrollWidth === null){
156                     // Append our div, do our calculation and then remove it
157                 var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
158                     child = div.child('div', true);
159                 var w1 = child.offsetWidth;
160                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
161                 var w2 = child.offsetWidth;
162                 div.remove();
163                 // Need to add 2 to ensure we leave enough space
164                 scrollWidth = w1 - w2 + 2;
165             }
166             return scrollWidth;
167         },
168
169
170         // deprecated
171         combine : function(){
172             var as = arguments, l = as.length, r = [];
173             for(var i = 0; i < l; i++){
174                 var a = as[i];
175                 if(Ext.isArray(a)){
176                     r = r.concat(a);
177                 }else if(a.length !== undefined && !a.substr){
178                     r = r.concat(Array.prototype.slice.call(a, 0));
179                 }else{
180                     r.push(a);
181                 }
182             }
183             return r;
184         },
185
186         <div id="method-Ext-copyTo"></div>/**
187          * Copies a set of named properties fom the source object to the destination object.
188          * <p>example:<pre><code>
189 ImageComponent = Ext.extend(Ext.BoxComponent, {
190     initComponent: function() {
191         this.autoEl = { tag: 'img' };
192         MyComponent.superclass.initComponent.apply(this, arguments);
193         this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
194     }
195 });
196          * </code></pre>
197          * @param {Object} dest The destination object.
198          * @param {Object} source The source object.
199          * @param {Array/String} names Either an Array of property names, or a comma-delimited list
200          * of property names to copy.
201          * @return {Object} The modified object.
202         */
203         copyTo : function(dest, source, names){
204             if(typeof names == 'string'){
205                 names = names.split(/[,;\s]/);
206             }
207             Ext.each(names, function(name){
208                 if(source.hasOwnProperty(name)){
209                     dest[name] = source[name];
210                 }
211             }, this);
212             return dest;
213         },
214
215         <div id="method-Ext-destroy"></div>/**
216          * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
217          * DOM (if applicable) and calling their destroy functions (if available).  This method is primarily
218          * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
219          * {@link Ext.util.Observable} can be passed in.  Any number of elements and/or components can be
220          * passed into this function in a single call as separate arguments.
221          * @param {Mixed} arg1 An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
222          * @param {Mixed} arg2 (optional)
223          * @param {Mixed} etc... (optional)
224          */
225         destroy : function(){
226             Ext.each(arguments, function(arg){
227                 if(arg){
228                     if(Ext.isArray(arg)){
229                         this.destroy.apply(this, arg);
230                     }else if(typeof arg.destroy == 'function'){
231                         arg.destroy();
232                     }else if(arg.dom){
233                         arg.remove();
234                     }
235                 }
236             }, this);
237         },
238
239         <div id="method-Ext-destroyMembers"></div>/**
240          * Attempts to destroy and then remove a set of named properties of the passed object.
241          * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
242          * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
243          * @param {Mixed} etc... More property names to destroy and remove.
244          */
245         destroyMembers : function(o, arg1, arg2, etc){
246             for(var i = 1, a = arguments, len = a.length; i < len; i++) {
247                 Ext.destroy(o[a[i]]);
248                 delete o[a[i]];
249             }
250         },
251
252         <div id="method-Ext-clean"></div>/**
253          * Creates a copy of the passed Array with falsy values removed.
254          * @param {Array/NodeList} arr The Array from which to remove falsy values.
255          * @return {Array} The new, compressed Array.
256          */
257         clean : function(arr){
258             var ret = [];
259             Ext.each(arr, function(v){
260                 if(!!v){
261                     ret.push(v);
262                 }
263             });
264             return ret;
265         },
266
267         <div id="method-Ext-unique"></div>/**
268          * Creates a copy of the passed Array, filtered to contain only unique values.
269          * @param {Array} arr The Array to filter
270          * @return {Array} The new Array containing unique values.
271          */
272         unique : function(arr){
273             var ret = [],
274                 collect = {};
275
276             Ext.each(arr, function(v) {
277                 if(!collect[v]){
278                     ret.push(v);
279                 }
280                 collect[v] = true;
281             });
282             return ret;
283         },
284
285         <div id="method-Ext-flatten"></div>/**
286          * Recursively flattens into 1-d Array. Injects Arrays inline.
287          * @param {Array} arr The array to flatten
288          * @return {Array} The new, flattened array.
289          */
290         flatten : function(arr){
291             var worker = [];
292             function rFlatten(a) {
293                 Ext.each(a, function(v) {
294                     if(Ext.isArray(v)){
295                         rFlatten(v);
296                     }else{
297                         worker.push(v);
298                     }
299                 });
300                 return worker;
301             }
302             return rFlatten(arr);
303         },
304
305         <div id="method-Ext-min"></div>/**
306          * Returns the minimum value in the Array.
307          * @param {Array|NodeList} arr The Array from which to select the minimum value.
308          * @param {Function} comp (optional) a function to perform the comparision which determines minimization.
309          *                   If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
310          * @return {Object} The minimum value in the Array.
311          */
312         min : function(arr, comp){
313             var ret = arr[0];
314             comp = comp || function(a,b){ return a < b ? -1 : 1; };
315             Ext.each(arr, function(v) {
316                 ret = comp(ret, v) == -1 ? ret : v;
317             });
318             return ret;
319         },
320
321         <div id="method-Ext-max"></div>/**
322          * Returns the maximum value in the Array
323          * @param {Array|NodeList} arr The Array from which to select the maximum value.
324          * @param {Function} comp (optional) a function to perform the comparision which determines maximization.
325          *                   If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
326          * @return {Object} The maximum value in the Array.
327          */
328         max : function(arr, comp){
329             var ret = arr[0];
330             comp = comp || function(a,b){ return a > b ? 1 : -1; };
331             Ext.each(arr, function(v) {
332                 ret = comp(ret, v) == 1 ? ret : v;
333             });
334             return ret;
335         },
336
337         <div id="method-Ext-mean"></div>/**
338          * Calculates the mean of the Array
339          * @param {Array} arr The Array to calculate the mean value of.
340          * @return {Number} The mean.
341          */
342         mean : function(arr){
343            return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
344         },
345
346         <div id="method-Ext-sum"></div>/**
347          * Calculates the sum of the Array
348          * @param {Array} arr The Array to calculate the sum value of.
349          * @return {Number} The sum.
350          */
351         sum : function(arr){
352            var ret = 0;
353            Ext.each(arr, function(v) {
354                ret += v;
355            });
356            return ret;
357         },
358
359         <div id="method-Ext-partition"></div>/**
360          * Partitions the set into two sets: a true set and a false set.
361          * Example:
362          * Example2:
363          * <pre><code>
364 // Example 1:
365 Ext.partition([true, false, true, true, false]); // [[true, true, true], [false, false]]
366
367 // Example 2:
368 Ext.partition(
369     Ext.query("p"),
370     function(val){
371         return val.className == "class1"
372     }
373 );
374 // true are those paragraph elements with a className of "class1",
375 // false set are those that do not have that className.
376          * </code></pre>
377          * @param {Array|NodeList} arr The array to partition
378          * @param {Function} truth (optional) a function to determine truth.  If this is omitted the element
379          *                   itself must be able to be evaluated for its truthfulness.
380          * @return {Array} [true<Array>,false<Array>]
381          */
382         partition : function(arr, truth){
383             var ret = [[],[]];
384             Ext.each(arr, function(v, i, a) {
385                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
386             });
387             return ret;
388         },
389
390         <div id="method-Ext-invoke"></div>/**
391          * Invokes a method on each item in an Array.
392          * <pre><code>
393 // Example:
394 Ext.invoke(Ext.query("p"), "getAttribute", "id");
395 // [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
396          * </code></pre>
397          * @param {Array|NodeList} arr The Array of items to invoke the method on.
398          * @param {String} methodName The method name to invoke.
399          * @param {...*} args Arguments to send into the method invocation.
400          * @return {Array} The results of invoking the method on each item in the array.
401          */
402         invoke : function(arr, methodName){
403             var ret = [],
404                 args = Array.prototype.slice.call(arguments, 2);
405             Ext.each(arr, function(v,i) {
406                 if (v && typeof v[methodName] == 'function') {
407                     ret.push(v[methodName].apply(v, args));
408                 } else {
409                     ret.push(undefined);
410                 }
411             });
412             return ret;
413         },
414
415         <div id="method-Ext-pluck"></div>/**
416          * Plucks the value of a property from each item in the Array
417          * <pre><code>
418 // Example:
419 Ext.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
420          * </code></pre>
421          * @param {Array|NodeList} arr The Array of items to pluck the value from.
422          * @param {String} prop The property name to pluck from each element.
423          * @return {Array} The value from each item in the Array.
424          */
425         pluck : function(arr, prop){
426             var ret = [];
427             Ext.each(arr, function(v) {
428                 ret.push( v[prop] );
429             });
430             return ret;
431         },
432
433         <div id="method-Ext-zip"></div>/**
434          * <p>Zips N sets together.</p>
435          * <pre><code>
436 // Example 1:
437 Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
438 // Example 2:
439 Ext.zip(
440     [ "+", "-", "+"],
441     [  12,  10,  22],
442     [  43,  15,  96],
443     function(a, b, c){
444         return "$" + a + "" + b + "." + c
445     }
446 ); // ["$+12.43", "$-10.15", "$+22.96"]
447          * </code></pre>
448          * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
449          * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
450          * @return {Array} The zipped set.
451          */
452         zip : function(){
453             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
454                 arrs = parts[0],
455                 fn = parts[1][0],
456                 len = Ext.max(Ext.pluck(arrs, "length")),
457                 ret = [];
458
459             for (var i = 0; i < len; i++) {
460                 ret[i] = [];
461                 if(fn){
462                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
463                 }else{
464                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
465                         ret[i].push( arrs[j][i] );
466                     }
467                 }
468             }
469             return ret;
470         },
471
472         <div id="method-Ext-getCmp"></div>/**
473          * This is shorthand reference to {@link Ext.ComponentMgr#get}.
474          * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
475          * @param {String} id The component {@link Ext.Component#id id}
476          * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a
477          * Class was found.
478         */
479         getCmp : function(id){
480             return Ext.ComponentMgr.get(id);
481         },
482
483         <div id="prop-Ext-useShims"></div>/**
484          * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
485          * you may want to set this to true.
486          * @type Boolean
487          */
488         useShims: E.isIE6 || (E.isMac && E.isGecko2),
489
490         // inpired by a similar function in mootools library
491         <div id="method-Ext-type"></div>/**
492          * Returns the type of object that is passed in. If the object passed in is null or undefined it
493          * return false otherwise it returns one of the following values:<div class="mdetail-params"><ul>
494          * <li><b>string</b>: If the object passed is a string</li>
495          * <li><b>number</b>: If the object passed is a number</li>
496          * <li><b>boolean</b>: If the object passed is a boolean value</li>
497          * <li><b>date</b>: If the object passed is a Date object</li>
498          * <li><b>function</b>: If the object passed is a function reference</li>
499          * <li><b>object</b>: If the object passed is an object</li>
500          * <li><b>array</b>: If the object passed is an array</li>
501          * <li><b>regexp</b>: If the object passed is a regular expression</li>
502          * <li><b>element</b>: If the object passed is a DOM Element</li>
503          * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
504          * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
505          * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
506          * </ul></div>
507          * @param {Mixed} object
508          * @return {String}
509          */
510         type : function(o){
511             if(o === undefined || o === null){
512                 return false;
513             }
514             if(o.htmlElement){
515                 return 'element';
516             }
517             var t = typeof o;
518             if(t == 'object' && o.nodeName) {
519                 switch(o.nodeType) {
520                     case 1: return 'element';
521                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
522                 }
523             }
524             if(t == 'object' || t == 'function') {
525                 switch(o.constructor) {
526                     case Array: return 'array';
527                     case RegExp: return 'regexp';
528                     case Date: return 'date';
529                 }
530                 if(typeof o.length == 'number' && typeof o.item == 'function') {
531                     return 'nodelist';
532                 }
533             }
534             return t;
535         },
536
537         intercept : function(o, name, fn, scope){
538             o[name] = o[name].createInterceptor(fn, scope);
539         },
540
541         // internal
542         callback : function(cb, scope, args, delay){
543             if(typeof cb == 'function'){
544                 if(delay){
545                     cb.defer(delay, scope, args || []);
546                 }else{
547                     cb.apply(scope, args || []);
548                 }
549             }
550         }
551     };
552 }());
553
554 /**
555  * @class Function
556  * These functions are available on every Function object (any JavaScript function).
557  */
558 Ext.apply(Function.prototype, {
559     <div id="method-Function-createSequence"></div>/**
560      * Create a combined function call sequence of the original function + the passed function.
561      * The resulting function returns the results of the original function.
562      * The passed fcn is called with the parameters of the original function. Example usage:
563      * <pre><code>
564 var sayHi = function(name){
565     alert('Hi, ' + name);
566 }
567
568 sayHi('Fred'); // alerts "Hi, Fred"
569
570 var sayGoodbye = sayHi.createSequence(function(name){
571     alert('Bye, ' + name);
572 });
573
574 sayGoodbye('Fred'); // both alerts show
575 </code></pre>
576      * @param {Function} fcn The function to sequence
577      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
578      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
579      * @return {Function} The new function
580      */
581     createSequence : function(fcn, scope){
582         var method = this;
583         return (typeof fcn != 'function') ?
584                 this :
585                 function(){
586                     var retval = method.apply(this || window, arguments);
587                     fcn.apply(scope || this || window, arguments);
588                     return retval;
589                 };
590     }
591 });
592
593
594 /**
595  * @class String
596  * These functions are available as static methods on the JavaScript String object.
597  */
598 Ext.applyIf(String, {
599
600     <div id="method-String-escape"></div>/**
601      * Escapes the passed string for ' and \
602      * @param {String} string The string to escape
603      * @return {String} The escaped string
604      * @static
605      */
606     escape : function(string) {
607         return string.replace(/('|\\)/g, "\\$1");
608     },
609
610     <div id="method-String-leftPad"></div>/**
611      * Pads the left side of a string with a specified character.  This is especially useful
612      * for normalizing number and date strings.  Example usage:
613      * <pre><code>
614 var s = String.leftPad('123', 5, '0');
615 // s now contains the string: '00123'
616      * </code></pre>
617      * @param {String} string The original string
618      * @param {Number} size The total length of the output string
619      * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
620      * @return {String} The padded string
621      * @static
622      */
623     leftPad : function (val, size, ch) {
624         var result = String(val);
625         if(!ch) {
626             ch = " ";
627         }
628         while (result.length < size) {
629             result = ch + result;
630         }
631         return result;
632     }
633 });
634
635 <div id="method-String-toggle"></div>/**
636  * Utility function that allows you to easily switch a string between two alternating values.  The passed value
637  * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
638  * they are already different, the first value passed in is returned.  Note that this method returns the new value
639  * but does not change the current string.
640  * <pre><code>
641 // alternate sort directions
642 sort = sort.toggle('ASC', 'DESC');
643
644 // instead of conditional logic:
645 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
646 </code></pre>
647  * @param {String} value The value to compare to the current string
648  * @param {String} other The new value to use if the string already equals the first value passed in
649  * @return {String} The new value
650  */
651 String.prototype.toggle = function(value, other){
652     return this == value ? other : value;
653 };
654
655 <div id="method-String-trim"></div>/**
656  * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
657  * <pre><code>
658 var s = '  foo bar  ';
659 alert('-' + s + '-');         //alerts "- foo bar -"
660 alert('-' + s.trim() + '-');  //alerts "-foo bar-"
661 </code></pre>
662  * @return {String} The trimmed string
663  */
664 String.prototype.trim = function(){
665     var re = /^\s+|\s+$/g;
666     return function(){ return this.replace(re, ""); };
667 }();
668
669 // here to prevent dependency on Date.js
670 <div id="method-Date-getElapsed"></div>/**
671  Returns the number of milliseconds between this date and date
672  @param {Date} date (optional) Defaults to now
673  @return {Number} The diff in milliseconds
674  @member Date getElapsed
675  */
676 Date.prototype.getElapsed = function(date) {
677     return Math.abs((date || new Date()).getTime()-this.getTime());
678 };
679
680
681 <div id="cls-Number"></div>/**
682  * @class Number
683  */
684 Ext.applyIf(Number.prototype, {
685     <div id="method-Number-constrain"></div>/**
686      * Checks whether or not the current number is within a desired range.  If the number is already within the
687      * range it is returned, otherwise the min or max value is returned depending on which side of the range is
688      * exceeded.  Note that this method returns the constrained value but does not change the current number.
689      * @param {Number} min The minimum number in the range
690      * @param {Number} max The maximum number in the range
691      * @return {Number} The constrained value if outside the range, otherwise the current value
692      */
693     constrain : function(min, max){
694         return Math.min(Math.max(this, min), max);
695     }
696 });
697 </pre>    
698 </body>
699 </html>