Ext-more.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:25k
源码类别:

JavaScript

开发平台:

JavaScript

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