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