<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='Ext'>/**
</span> * @class Ext
 */

Ext.ns(&quot;Ext.grid&quot;, &quot;Ext.list&quot;, &quot;Ext.dd&quot;, &quot;Ext.tree&quot;, &quot;Ext.form&quot;, &quot;Ext.menu&quot;,
       &quot;Ext.state&quot;, &quot;Ext.layout.boxOverflow&quot;, &quot;Ext.app&quot;, &quot;Ext.ux&quot;, &quot;Ext.chart&quot;, &quot;Ext.direct&quot;, &quot;Ext.slider&quot;);
<span id='Ext-property-ux'>    /**
</span>     * Namespace alloted for extensions to the framework.
     * @property ux
     * @type Object
     */

Ext.apply(Ext, function(){
    var E = Ext,
        idSeed = 0,
        scrollWidth = null;

    return {
<span id='Ext-property-emptyFn'>        /**
</span>        * A reusable empty function
        * @property
        * @type Function
        */
        emptyFn : function(){},

<span id='Ext-property-BLANK_IMAGE_URL'>        /**
</span>         * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images.
         * In older versions of IE, this defaults to &quot;http://extjs.com/s.gif&quot; and you should change this to a URL on your server.
         * For other browsers it uses an inline data URL.
         * @type String
         */
        BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
                            'http:/' + '/www.extjs.com/s.gif' :
                            'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',

        extendX : function(supr, fn){
            return Ext.extend(supr, fn(supr.prototype));
        },

<span id='Ext-method-getDoc'>        /**
</span>         * Returns the current HTML document object as an {@link Ext.Element}.
         * @return Ext.Element The document
         */
        getDoc : function(){
            return Ext.get(document);
        },

<span id='Ext-method-num'>        /**
</span>         * Utility method for validating that a value is numeric, returning the specified default value if it is not.
         * @param {Mixed} value Should be a number, but any type will be handled appropriately
         * @param {Number} defaultValue The value to return if the original value is non-numeric
         * @return {Number} Value, if numeric, else defaultValue
         */
        num : function(v, defaultValue){
            v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' &amp;&amp; v.trim().length == 0) ? NaN : v);
            return isNaN(v) ? defaultValue : v;
        },

<span id='Ext-method-value'>        /**
</span>         * &lt;p&gt;Utility method for returning a default value if the passed value is empty.&lt;/p&gt;
         * &lt;p&gt;The value is deemed to be empty if it is&lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
         * &lt;li&gt;null&lt;/li&gt;
         * &lt;li&gt;undefined&lt;/li&gt;
         * &lt;li&gt;an empty array&lt;/li&gt;
         * &lt;li&gt;a zero length string (Unless the &lt;tt&gt;allowBlank&lt;/tt&gt; parameter is &lt;tt&gt;true&lt;/tt&gt;)&lt;/li&gt;
         * &lt;/ul&gt;&lt;/div&gt;
         * @param {Mixed} value The value to test
         * @param {Mixed} defaultValue The value to return if the original value is empty
         * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
         * @return {Mixed} value, if non-empty, else defaultValue
         */
        value : function(v, defaultValue, allowBlank){
            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
        },

<span id='Ext-method-escapeRe'>        /**
</span>         * Escapes the passed string for use in a regular expression
         * @param {String} str
         * @return {String}
         */
        escapeRe : function(s) {
            return s.replace(/([-.*+?^${}()|[\]\/\\])/g, &quot;\\$1&quot;);
        },

        sequence : function(o, name, fn, scope){
            o[name] = o[name].createSequence(fn, scope);
        },

<span id='Ext-method-addBehaviors'>        /**
</span>         * Applies event listeners to elements by selectors when the document is ready.
         * The event name is specified with an &lt;tt&gt;&amp;#64;&lt;/tt&gt; suffix.
         * &lt;pre&gt;&lt;code&gt;
Ext.addBehaviors({
    // add a listener for click on all anchors in element with id foo
    '#foo a&amp;#64;click' : function(e, t){
        // do something
    },

    // add the same listener to multiple selectors (separated by comma BEFORE the &amp;#64;)
    '#foo a, #bar span.some-class&amp;#64;mouseover' : function(){
        // do something
    }
});
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Object} obj The list of behaviors to apply
         */
        addBehaviors : function(o){
            if(!Ext.isReady){
                Ext.onReady(function(){
                    Ext.addBehaviors(o);
                });
            } else {
                var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
                    parts,
                    b,
                    s;
                for (b in o) {
                    if ((parts = b.split('@'))[1]) { // for Object prototype breakers
                        s = parts[0];
                        if(!cache[s]){
                            cache[s] = Ext.select(s);
                        }
                        cache[s].on(parts[1], o[b]);
                    }
                }
                cache = null;
            }
        },

<span id='Ext-method-getScrollBarWidth'>        /**
</span>         * Utility method for getting the width of the browser scrollbar. This can differ depending on
         * operating system settings, such as the theme or font size.
         * @param {Boolean} force (optional) true to force a recalculation of the value.
         * @return {Number} The width of the scrollbar.
         */
        getScrollBarWidth: function(force){
            if(!Ext.isReady){
                return 0;
            }

            if(force === true || scrollWidth === null){
                    // Append our div, do our calculation and then remove it
                var div = Ext.getBody().createChild('&lt;div class=&quot;x-hide-offsets&quot; style=&quot;width:100px;height:50px;overflow:hidden;&quot;&gt;&lt;div style=&quot;height:200px;&quot;&gt;&lt;/div&gt;&lt;/div&gt;'),
                    child = div.child('div', true);
                var w1 = child.offsetWidth;
                div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
                var w2 = child.offsetWidth;
                div.remove();
                // Need to add 2 to ensure we leave enough space
                scrollWidth = w1 - w2 + 2;
            }
            return scrollWidth;
        },


        // deprecated
        combine : function(){
            var as = arguments, l = as.length, r = [];
            for(var i = 0; i &lt; l; i++){
                var a = as[i];
                if(Ext.isArray(a)){
                    r = r.concat(a);
                }else if(a.length !== undefined &amp;&amp; !a.substr){
                    r = r.concat(Array.prototype.slice.call(a, 0));
                }else{
                    r.push(a);
                }
            }
            return r;
        },

<span id='Ext-method-copyTo'>        /**
</span>         * Copies a set of named properties fom the source object to the destination object.
         * &lt;p&gt;example:&lt;pre&gt;&lt;code&gt;
ImageComponent = Ext.extend(Ext.BoxComponent, {
    initComponent: function() {
        this.autoEl = { tag: 'img' };
        MyComponent.superclass.initComponent.apply(this, arguments);
        this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
    }
});
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Object} dest The destination object.
         * @param {Object} source The source object.
         * @param {Array/String} names Either an Array of property names, or a comma-delimited list
         * of property names to copy.
         * @return {Object} The modified object.
        */
        copyTo : function(dest, source, names){
            if(typeof names == 'string'){
                names = names.split(/[,;\s]/);
            }
            Ext.each(names, function(name){
                if(source.hasOwnProperty(name)){
                    dest[name] = source[name];
                }
            }, this);
            return dest;
        },

<span id='Ext-method-destroy'>        /**
</span>         * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
         * DOM (if applicable) and calling their destroy functions (if available).  This method is primarily
         * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
         * {@link Ext.util.Observable} can be passed in.  Any number of elements and/or components can be
         * passed into this function in a single call as separate arguments.
         * @param {Mixed...} args An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
         */
        destroy : function(){
            Ext.each(arguments, function(arg){
                if(arg){
                    if(Ext.isArray(arg)){
                        this.destroy.apply(this, arg);
                    }else if(typeof arg.destroy == 'function'){
                        arg.destroy();
                    }else if(arg.dom){
                        arg.remove();
                    }
                }
            }, this);
        },

<span id='Ext-method-destroyMembers'>        /**
</span>         * Attempts to destroy and then remove a set of named properties of the passed object.
         * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
         * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
         * @param {Mixed} etc... More property names to destroy and remove.
         */
        destroyMembers : function(o, arg1, arg2, etc){
            for(var i = 1, a = arguments, len = a.length; i &lt; len; i++) {
                Ext.destroy(o[a[i]]);
                delete o[a[i]];
            }
        },

<span id='Ext-method-clean'>        /**
</span>         * Creates a copy of the passed Array with falsy values removed.
         * @param {Array/NodeList} arr The Array from which to remove falsy values.
         * @return {Array} The new, compressed Array.
         */
        clean : function(arr){
            var ret = [];
            Ext.each(arr, function(v){
                if(!!v){
                    ret.push(v);
                }
            });
            return ret;
        },

<span id='Ext-method-unique'>        /**
</span>         * Creates a copy of the passed Array, filtered to contain only unique values.
         * @param {Array} arr The Array to filter
         * @return {Array} The new Array containing unique values.
         */
        unique : function(arr){
            var ret = [],
                collect = {};

            Ext.each(arr, function(v) {
                if(!collect[v]){
                    ret.push(v);
                }
                collect[v] = true;
            });
            return ret;
        },

<span id='Ext-method-flatten'>        /**
</span>         * Recursively flattens into 1-d Array. Injects Arrays inline.
         * @param {Array} arr The array to flatten
         * @return {Array} The new, flattened array.
         */
        flatten : function(arr){
            var worker = [];
            function rFlatten(a) {
                Ext.each(a, function(v) {
                    if(Ext.isArray(v)){
                        rFlatten(v);
                    }else{
                        worker.push(v);
                    }
                });
                return worker;
            }
            return rFlatten(arr);
        },

<span id='Ext-method-min'>        /**
</span>         * Returns the minimum value in the Array.
         * @param {Array|NodeList} arr The Array from which to select the minimum value.
         * @param {Function} comp (optional) a function to perform the comparision which determines minimization.
         *                   If omitted the &quot;&lt;&quot; operator will be used. Note: gt = 1; eq = 0; lt = -1
         * @return {Object} The minimum value in the Array.
         */
        min : function(arr, comp){
            var ret = arr[0];
            comp = comp || function(a,b){ return a &lt; b ? -1 : 1; };
            Ext.each(arr, function(v) {
                ret = comp(ret, v) == -1 ? ret : v;
            });
            return ret;
        },

<span id='Ext-method-max'>        /**
</span>         * Returns the maximum value in the Array
         * @param {Array|NodeList} arr The Array from which to select the maximum value.
         * @param {Function} comp (optional) a function to perform the comparision which determines maximization.
         *                   If omitted the &quot;&gt;&quot; operator will be used. Note: gt = 1; eq = 0; lt = -1
         * @return {Object} The maximum value in the Array.
         */
        max : function(arr, comp){
            var ret = arr[0];
            comp = comp || function(a,b){ return a &gt; b ? 1 : -1; };
            Ext.each(arr, function(v) {
                ret = comp(ret, v) == 1 ? ret : v;
            });
            return ret;
        },

<span id='Ext-method-mean'>        /**
</span>         * Calculates the mean of the Array
         * @param {Array} arr The Array to calculate the mean value of.
         * @return {Number} The mean.
         */
        mean : function(arr){
           return arr.length &gt; 0 ? Ext.sum(arr) / arr.length : undefined;
        },

<span id='Ext-method-sum'>        /**
</span>         * Calculates the sum of the Array
         * @param {Array} arr The Array to calculate the sum value of.
         * @return {Number} The sum.
         */
        sum : function(arr){
           var ret = 0;
           Ext.each(arr, function(v) {
               ret += v;
           });
           return ret;
        },

<span id='Ext-method-partition'>        /**
</span>         * Partitions the set into two sets: a true set and a false set.
         * Example:
         * Example2:
         * &lt;pre&gt;&lt;code&gt;
// Example 1:
Ext.partition([true, false, true, true, false]); // [[true, true, true], [false, false]]

// Example 2:
Ext.partition(
    Ext.query(&quot;p&quot;),
    function(val){
        return val.className == &quot;class1&quot;
    }
);
// true are those paragraph elements with a className of &quot;class1&quot;,
// false set are those that do not have that className.
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Array|NodeList} arr The array to partition
         * @param {Function} truth (optional) a function to determine truth.  If this is omitted the element
         *                   itself must be able to be evaluated for its truthfulness.
         * @return {Array} [true&lt;Array&gt;,false&lt;Array&gt;]
         */
        partition : function(arr, truth){
            var ret = [[],[]];
            Ext.each(arr, function(v, i, a) {
                ret[ (truth &amp;&amp; truth(v, i, a)) || (!truth &amp;&amp; v) ? 0 : 1].push(v);
            });
            return ret;
        },

<span id='Ext-method-invoke'>        /**
</span>         * Invokes a method on each item in an Array.
         * &lt;pre&gt;&lt;code&gt;
// Example:
Ext.invoke(Ext.query(&quot;p&quot;), &quot;getAttribute&quot;, &quot;id&quot;);
// [el1.getAttribute(&quot;id&quot;), el2.getAttribute(&quot;id&quot;), ..., elN.getAttribute(&quot;id&quot;)]
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Array|NodeList} arr The Array of items to invoke the method on.
         * @param {String} methodName The method name to invoke.
         * @param {...*} args Arguments to send into the method invocation.
         * @return {Array} The results of invoking the method on each item in the array.
         */
        invoke : function(arr, methodName){
            var ret = [],
                args = Array.prototype.slice.call(arguments, 2);
            Ext.each(arr, function(v,i) {
                if (v &amp;&amp; typeof v[methodName] == 'function') {
                    ret.push(v[methodName].apply(v, args));
                } else {
                    ret.push(undefined);
                }
            });
            return ret;
        },

<span id='Ext-method-pluck'>        /**
</span>         * Plucks the value of a property from each item in the Array
         * &lt;pre&gt;&lt;code&gt;
// Example:
Ext.pluck(Ext.query(&quot;p&quot;), &quot;className&quot;); // [el1.className, el2.className, ..., elN.className]
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Array|NodeList} arr The Array of items to pluck the value from.
         * @param {String} prop The property name to pluck from each element.
         * @return {Array} The value from each item in the Array.
         */
        pluck : function(arr, prop){
            var ret = [];
            Ext.each(arr, function(v) {
                ret.push( v[prop] );
            });
            return ret;
        },

<span id='Ext-method-zip'>        /**
</span>         * &lt;p&gt;Zips N sets together.&lt;/p&gt;
         * &lt;pre&gt;&lt;code&gt;
// Example 1:
Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
// Example 2:
Ext.zip(
    [ &quot;+&quot;, &quot;-&quot;, &quot;+&quot;],
    [  12,  10,  22],
    [  43,  15,  96],
    function(a, b, c){
        return &quot;$&quot; + a + &quot;&quot; + b + &quot;.&quot; + c
    }
); // [&quot;$+12.43&quot;, &quot;$-10.15&quot;, &quot;$+22.96&quot;]
         * &lt;/code&gt;&lt;/pre&gt;
         * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
         * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
         * @return {Array} The zipped set.
         */
        zip : function(){
            var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
                arrs = parts[0],
                fn = parts[1][0],
                len = Ext.max(Ext.pluck(arrs, &quot;length&quot;)),
                ret = [];

            for (var i = 0; i &lt; len; i++) {
                ret[i] = [];
                if(fn){
                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
                }else{
                    for (var j = 0, aLen = arrs.length; j &lt; aLen; j++){
                        ret[i].push( arrs[j][i] );
                    }
                }
            }
            return ret;
        },

<span id='Ext-method-getCmp'>        /**
</span>         * This is shorthand reference to {@link Ext.ComponentMgr#get}.
         * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
         * @param {String} id The component {@link Ext.Component#id id}
         * @return Ext.Component The Component, &lt;tt&gt;undefined&lt;/tt&gt; if not found, or &lt;tt&gt;null&lt;/tt&gt; if a
         * Class was found.
        */
        getCmp : function(id){
            return Ext.ComponentMgr.get(id);
        },

<span id='Ext-property-useShims'>        /**
</span>         * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
         * you may want to set this to true.
         * @type Boolean
         */
        useShims: E.isIE6 || (E.isMac &amp;&amp; E.isGecko2),

        // inpired by a similar function in mootools library
<span id='Ext-method-type'>        /**
</span>         * Returns the type of object that is passed in. If the object passed in is null or undefined it
         * return false otherwise it returns one of the following values:&lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
         * &lt;li&gt;&lt;b&gt;string&lt;/b&gt;: If the object passed is a string&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;number&lt;/b&gt;: If the object passed is a number&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;boolean&lt;/b&gt;: If the object passed is a boolean value&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;date&lt;/b&gt;: If the object passed is a Date object&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;function&lt;/b&gt;: If the object passed is a function reference&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;object&lt;/b&gt;: If the object passed is an object&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;array&lt;/b&gt;: If the object passed is an array&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;regexp&lt;/b&gt;: If the object passed is a regular expression&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;element&lt;/b&gt;: If the object passed is a DOM Element&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;nodelist&lt;/b&gt;: If the object passed is a DOM NodeList&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;textnode&lt;/b&gt;: If the object passed is a DOM text node and contains something other than whitespace&lt;/li&gt;
         * &lt;li&gt;&lt;b&gt;whitespace&lt;/b&gt;: If the object passed is a DOM text node and contains only whitespace&lt;/li&gt;
         * &lt;/ul&gt;&lt;/div&gt;
         * @param {Mixed} object
         * @return {String}
         */
        type : function(o){
            if(o === undefined || o === null){
                return false;
            }
            if(o.htmlElement){
                return 'element';
            }
            var t = typeof o;
            if(t == 'object' &amp;&amp; o.nodeName) {
                switch(o.nodeType) {
                    case 1: return 'element';
                    case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
                }
            }
            if(t == 'object' || t == 'function') {
                switch(o.constructor) {
                    case Array: return 'array';
                    case RegExp: return 'regexp';
                    case Date: return 'date';
                }
                if(typeof o.length == 'number' &amp;&amp; typeof o.item == 'function') {
                    return 'nodelist';
                }
            }
            return t;
        },

        intercept : function(o, name, fn, scope){
            o[name] = o[name].createInterceptor(fn, scope);
        },

        // internal
        callback : function(cb, scope, args, delay){
            if(typeof cb == 'function'){
                if(delay){
                    cb.defer(delay, scope, args || []);
                }else{
                    cb.apply(scope, args || []);
                }
            }
        }
    };
}());

<span id='Function'>/**
</span> * @class Function
 * These functions are available on every Function object (any JavaScript function).
 */
Ext.apply(Function.prototype, {
<span id='Function-method-createSequence'>    /**
</span>     * Create a combined function call sequence of the original function + the passed function.
     * The resulting function returns the results of the original function.
     * The passed fcn is called with the parameters of the original function. Example usage:
     * &lt;pre&gt;&lt;code&gt;
var sayHi = function(name){
    alert('Hi, ' + name);
}

sayHi('Fred'); // alerts &quot;Hi, Fred&quot;

var sayGoodbye = sayHi.createSequence(function(name){
    alert('Bye, ' + name);
});

sayGoodbye('Fred'); // both alerts show
&lt;/code&gt;&lt;/pre&gt;
     * @param {Function} fcn The function to sequence
     * @param {Object} scope (optional) The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the passed function is executed.
     * &lt;b&gt;If omitted, defaults to the scope in which the original function is called or the browser window.&lt;/b&gt;
     * @return {Function} The new function
     */
    createSequence : function(fcn, scope){
        var method = this;
        return (typeof fcn != 'function') ?
                this :
                function(){
                    var retval = method.apply(this || window, arguments);
                    fcn.apply(scope || this || window, arguments);
                    return retval;
                };
    }
});


<span id='String'>/**
</span> * @class String
 * These functions are available as static methods on the JavaScript String object.
 */
Ext.applyIf(String, {

<span id='String-static-method-escape'>    /**
</span>     * Escapes the passed string for ' and \
     * @param {String} string The string to escape
     * @return {String} The escaped string
     * @static
     */
    escape : function(string) {
        return string.replace(/('|\\)/g, &quot;\\$1&quot;);
    },

<span id='String-static-method-leftPad'>    /**
</span>     * Pads the left side of a string with a specified character.  This is especially useful
     * for normalizing number and date strings.  Example usage:
     * &lt;pre&gt;&lt;code&gt;
var s = String.leftPad('123', 5, '0');
// s now contains the string: '00123'
     * &lt;/code&gt;&lt;/pre&gt;
     * @param {String} string The original string
     * @param {Number} size The total length of the output string
     * @param {String} char (optional) The character with which to pad the original string (defaults to empty string &quot; &quot;)
     * @return {String} The padded string
     * @static
     */
    leftPad : function (val, size, ch) {
        var result = String(val);
        if(!ch) {
            ch = &quot; &quot;;
        }
        while (result.length &lt; size) {
            result = ch + result;
        }
        return result;
    }
});

<span id='String-method-toggle'>/**
</span> * Utility function that allows you to easily switch a string between two alternating values.  The passed value
 * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
 * they are already different, the first value passed in is returned.  Note that this method returns the new value
 * but does not change the current string.
 * &lt;pre&gt;&lt;code&gt;
// alternate sort directions
sort = sort.toggle('ASC', 'DESC');

// instead of conditional logic:
sort = (sort == 'ASC' ? 'DESC' : 'ASC');
&lt;/code&gt;&lt;/pre&gt;
 * @param {String} value The value to compare to the current string
 * @param {String} other The new value to use if the string already equals the first value passed in
 * @return {String} The new value
 */
String.prototype.toggle = function(value, other){
    return this == value ? other : value;
};

<span id='String-method-trim'>/**
</span> * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
 * &lt;pre&gt;&lt;code&gt;
var s = '  foo bar  ';
alert('-' + s + '-');         //alerts &quot;- foo bar -&quot;
alert('-' + s.trim() + '-');  //alerts &quot;-foo bar-&quot;
&lt;/code&gt;&lt;/pre&gt;
 * @return {String} The trimmed string
 */
String.prototype.trim = function(){
    var re = /^\s+|\s+$/g;
    return function(){ return this.replace(re, &quot;&quot;); };
}();

// here to prevent dependency on Date.js
<span id='Date-method-getElapsed'>/**
</span> Returns the number of milliseconds between this date and date
 @param {Date} date (optional) Defaults to now
 @return {Number} The diff in milliseconds
 @member Date getElapsed
 */
Date.prototype.getElapsed = function(date) {
    return Math.abs((date || new Date()).getTime()-this.getTime());
};


<span id='Number'>/**
</span> * @class Number
 */
Ext.applyIf(Number.prototype, {
<span id='Number-method-constrain'>    /**
</span>     * Checks whether or not the current number is within a desired range.  If the number is already within the
     * range it is returned, otherwise the min or max value is returned depending on which side of the range is
     * exceeded.  Note that this method returns the constrained value but does not change the current number.
     * @param {Number} min The minimum number in the range
     * @param {Number} max The maximum number in the range
     * @return {Number} The constrained value if outside the range, otherwise the current value
     */
    constrain : function(min, max){
        return Math.min(Math.max(this, min), max);
    }
});
</pre>
</body>
</html>