// for old browsers
window
.undefined = window.undefined;

/**
 * @class Ext
 * Ext core utilities and functions.
 * @singleton
 */


Ext = {
   
/**
     * The version of the framework
     * @type String
     */

    version
: '3.0'
};

/**
 * Copies all the properties of config to obj.
 * @param {Object} obj The receiver of the properties
 * @param {Object} config The source of the properties
 * @param {Object} defaults A different object that will also be applied for default values
 * @return {Object} returns obj
 * @member Ext apply
 */

Ext.apply = function(o, c, defaults){
   
// no "this" reference for friendly out of scope calls
   
if(defaults){
       
Ext.apply(o, defaults);
   
}
   
if(o && c && typeof c == 'object'){
       
for(var p in c){
            o
[p] = c[p];
       
}
   
}
   
return o;
};

(function(){
   
var idSeed = 0,
       
toString = Object.prototype.toString,
       
//assume it's not null and not an array
        isIterable
= function(v){
           
//check for array or arguments
           
if(Ext.isArray(v) || v.callee){
               
return true;
           
}
           
//check for node list type
           
if(/NodeList|HTMLCollection/.test(toString.call(v))){
               
return true;
           
}
           
//NodeList has an item and length property
           
//IXMLDOMNodeList has nextNode method, needs to be checked first.
           
return ((v.nextNode || v.item) && Ext.isNumber(v.length));
       
},
        ua
= navigator.userAgent.toLowerCase(),
        check
= function(r){
           
return r.test(ua);
       
},
        DOC
= document,
        isStrict
= DOC.compatMode == "CSS1Compat",
        isOpera
= check(/opera/),
        isChrome
= check(/chrome/),
        isWebKit
= check(/webkit/),
        isSafari
= !isChrome && check(/safari/),
        isSafari2
= isSafari && check(/applewebkit\/4/), // unique to Safari 2
        isSafari3
= isSafari && check(/version\/3/),
        isSafari4
= isSafari && check(/version\/4/),
        isIE
= !isOpera && check(/msie/),
        isIE7
= isIE && check(/msie 7/),
        isIE8
= isIE && check(/msie 8/),
        isIE6
= isIE && !isIE7 && !isIE8,
        isGecko
= !isWebKit && check(/gecko/),
        isGecko2
= isGecko && check(/rv:1\.8/),
        isGecko3
= isGecko && check(/rv:1\.9/),
        isBorderBox
= isIE && !isStrict,
        isWindows
= check(/windows|win32/),
        isMac
= check(/macintosh|mac os x/),
        isAir
= check(/adobeair/),
        isLinux
= check(/linux/),
        isSecure
= /^https/i.test(window.location.protocol);

   
// remove css image flicker
   
if(isIE6){
       
try{
            DOC
.execCommand("BackgroundImageCache", false, true);
       
}catch(e){}
   
}

   
Ext.apply(Ext, {
       
/**
         * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent
         * the IE insecure content warning (defaults to javascript:false).
         * @type String
         */

        SSL_SECURE_URL
: 'javascript:false',
       
/**
         * True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode
         * @type Boolean
         */

        isStrict
: isStrict,
       
/**
         * True if the page is running over SSL
         * @type Boolean
         */

        isSecure
: isSecure,
       
/**
         * True when the document is fully initialized and ready for action
         * @type Boolean
         */

        isReady
: false,

       
/**
         * True if the {@link Ext.Fx} Class is available
         * @type Boolean
         * @property enableFx
         */


       
/**
         * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
         * @type Boolean
         */

        enableGarbageCollector
: true,

       
/**
         * True to automatically purge event listeners after uncaching an element (defaults to false).
         * Note: this only happens if {@link #enableGarbageCollector} is true.
         * @type Boolean
         */

        enableListenerCollection
: false,

       
/**
         * Indicates whether to use native browser parsing for JSON methods.
         * This option is ignored if the browser does not support native JSON methods.
         *
Note: Native JSON methods will not work with objects that have functions.
         * Also, property names must be quoted, otherwise the data will not parse.
(Defaults to false)
         * @type Boolean
         */

        USE_NATIVE_JSON
: false,

       
/**
         * Copies all the properties of config to obj if they don't already exist.
         * @param {Object} obj The receiver of the properties
         * @param {Object} config The source of the properties
         * @return {Object} returns obj
         */

        applyIf
: function(o, c){
           
if(o){
               
for(var p in c){
                   
if(Ext.isEmpty(o[p])){
                        o
[p] = c[p];
                   
}
               
}
           
}
           
return o;
       
},

       
/**
         * Generates unique ids. If the element already has an id, it is unchanged
         * @param {Mixed} el (optional) The element to generate an id for
         * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
         * @return {String} The generated Id.
         */

        id
: function(el, prefix){
           
return (el = Ext.getDom(el) || {}).id = el.id || (prefix || "ext-gen") + (++idSeed);
       
},

       
/**
         * Extends one class with another class and optionally overrides members with the passed literal. This class
         * also adds the function "override()" to the class that can be used to override
         * members on an instance.
         * *


         * This function also supports a 2-argument call in which the subclass's constructor is
         * not passed as an argument. In this form, the parameters are as follows:


         *


         * For example, to create a subclass of the Ext GridPanel:
         *


MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
    constructor: function(config) {
        // Your preprocessing here
        MyGridPanel.superclass.constructor.apply(this, arguments);
        // Your postprocessing here
    },

    yourMethod: function() {
        // etc.
    }
});

         *


         * @param {Function} subclass The class inheriting the functionality
         * @param {Function} superclass The class being extended
         * @param {Object} overrides (optional) A literal with members which are copied into the subclass's
         * prototype, and are therefore shared between all instances of the new class.
         * @return {Function} The subclass constructor.
         * @method extend
         */

        extend
: function(){
           
// inline overrides
           
var io = function(o){
               
for(var m in o){
                   
this[m] = o[m];
               
}
           
};
           
var oc = Object.prototype.constructor;

           
return function(sb, sp, overrides){
               
if(Ext.isObject(sp)){
                    overrides
= sp;
                    sp
= sb;
                    sb
= overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
               
}
               
var F = function(){},
                    sbp
,
                    spp
= sp.prototype;

                F
.prototype = spp;
                sbp
= sb.prototype = new F();
                sbp
.constructor=sb;
                sb
.superclass=spp;
               
if(spp.constructor == oc){
                    spp
.constructor=sp;
               
}
                sb
.override = function(o){
                   
Ext.override(sb, o);
               
};
                sbp
.superclass = sbp.supr = (function(){
                   
return spp;
               
});
                sbp
.override = io;
               
Ext.override(sb, overrides);
                sb
.extend = function(o){Ext.extend(sb, o);};
               
return sb;
           
};
       
}(),

       
/**
         * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
         * Usage:

Ext.override(MyClass, {
    newMethod1: function(){
        // etc.
    },
    newMethod2: function(foo){
        // etc.
    }
});

         * @param {Object} origclass The class to override
         * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
         * containing one or more methods.
         * @method override
         */

        override
: function(origclass, overrides){
           
if(overrides){
               
var p = origclass.prototype;
               
Ext.apply(p, overrides);
               
if(Ext.isIE && overrides.toString != origclass.toString){
                    p
.toString = overrides.toString;
               
}
           
}
       
},

       
/**
         * Creates namespaces to be used for scoping variables and classes so that they are not global.
         * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
         *

Ext.namespace('Company', 'Company.data');
Ext.namespace('Company.data'); // equivalent and preferable to above syntax
Company.Widget = function() { ... }
Company.data.CustomStore = function(config) { ... }

         * @param {String} namespace1
         * @param {String} namespace2
         * @param {String} etc
         * @method namespace
         */

        namespace
: function(){
           
var o, d;
           
Ext.each(arguments, function(v) {
                d
= v.split(".");
                o
= window[d[0]] = window[d[0]] || {};
               
Ext.each(d.slice(1), function(v2){
                    o
= o[v2] = o[v2] || {};
               
});
           
});
           
return o;
       
},

       
/**
         * Takes an object and converts it to an encoded URL. e.g. Ext.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2".  Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
         * @param {Object} o
         * @param {String} pre (optional) A prefix to add to the url encoded string
         * @return {String}
         */

        urlEncode
: function(o, pre){
           
var undef, buf = [], key, e = encodeURIComponent;

           
for(key in o){
                undef
= !Ext.isDefined(o[key]);
               
Ext.each(undef ? key : o[key], function(val, i){
                    buf
.push("&", e(key), "=", (val != key || !undef) ? e(val) : "");
               
});
           
}
           
if(!pre){
                buf
.shift();
                pre
= "";
           
}
           
return pre + buf.join('');
       
},

       
/**
         * Takes an encoded URL and and converts it to an object. Example:

Ext.urlDecode("foo=1&bar=2"); // returns {foo: "1", bar: "2"}
Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2", "3", "4"]}

         * @param {String} string
         * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
         * @return {Object} A literal with members
         */

        urlDecode
: function(string, overwrite){
           
var obj = {},
                pairs
= string.split('&'),
                d
= decodeURIComponent,
                name
,
                value
;
           
Ext.each(pairs, function(pair) {
                pair
= pair.split('=');
                name
= d(pair[0]);
                value
= d(pair[1]);
                obj
[name] = overwrite || !obj[name] ? value :
                           
[].concat(obj[name]).concat(value);
           
});
           
return obj;
       
},

       
/**
         * Appends content to the query string of a URL, which handles logic for whether to place
         * a question mark or ampersand.
         * @param {String} url The url to append to.
         * @@param {String} s The content to append to the url.
         * @return (String) The appended string
         */

        urlAppend
: function(url, s){
           
if(!Ext.isEmpty(s)){
               
return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
           
}
           
return url;
       
},

       
/**
         * Converts any iterable (numeric indices and a length property) into a true array
         * Don't use this on strings. IE doesn't support "abc"[0] which this implementation depends on.
         * For strings, use this instead: "abc".match(/./g) => [a,b,c];
         * @param {Iterable} the iterable object to be turned into a true Array.
         * @return (Array) array
         */

        toArray
: function(){
           
return isIE ?
               
function(a, i, j, res){
                    res
= [];
                   
Ext.each(a, function(v) {
                        res
.push(v);
                   
});
                   
return res.slice(i || 0, j || res.length);
               
} :
               
function(a, i, j){
                   
return Array.prototype.slice.call(a, i || 0, j || a.length);
               
}
       
}(),

       
/**
         * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
         * passed array is not really an array, your function is called once with it.
         * The supplied function is called with (Object item, Number index, Array allItems).
         * @param {Array/NodeList/Mixed} array
         * @param {Function} fn
         * @param {Object} scope
         */

        each
: function(array, fn, scope){
           
if(Ext.isEmpty(array, true)){
               
return;
           
}
           
if(!isIterable(array) || Ext.isPrimitive(array)){
                array
= [array];
           
}
           
for(var i = 0, len = array.length; i < len; i++){
               
if(fn.call(scope || array[i], array[i], i, array) === false){
                   
return i;
               
};
           
}
       
},

       
/**
         * Iterates either the elements in an array, or each of the properties in an object.
         *
Note: If you are only iterating arrays, it is better to call {@link #each}.
         * @param {Object/Array} object The object or array to be iterated
         * @param {Function} fn The function to be called for each iteration.
         * The iteration will stop if the supplied function returns false, or
         * all array elements / object properties have been covered. The signature
         * varies depending on the type of object being interated:
         *

         * @param {Object} scope The scope to call the supplied function with, defaults to
         * the specified
object
         */

        iterate
: function(obj, fn, scope){
           
if(isIterable(obj)){
               
Ext.each(obj, fn, scope);
               
return;
           
}else if(Ext.isObject(obj)){
               
for(var prop in obj){
                   
if(obj.hasOwnProperty(prop)){
                       
if(fn.call(scope || obj, prop, obj[prop]) === false){
                           
return;
                       
};
                   
}
               
}
           
}
       
},

       
/**
         * Return the dom node for the passed String (id), dom node, or Ext.Element.
         * Here are some examples:
         *

// gets dom node based on id
var elDom = Ext.getDom('elId');
// gets dom node based on the dom node
var elDom1 = Ext.getDom(elDom);

// If we don't know if we are working with an
// Ext.Element or a dom node use Ext.getDom
function(el){
    var dom = Ext.getDom(el);
    // do something with the dom node
}
         *

         *
Note: the dom node to be found actually needs to exist (be rendered, etc)
         * when this method is called to be successful.
         * @param {Mixed} el
         * @return HTMLElement
         */

        getDom
: function(el){
           
if(!el || !DOC){
               
return null;
           
}
           
return el.dom ? el.dom : (Ext.isString(el) ? DOC.getElementById(el) : el);
       
},

       
/**
         * Returns the current document body as an {@link Ext.Element}.
         * @return Ext.Element The document body
         */

        getBody
: function(){
           
return Ext.get(DOC.body || DOC.documentElement);
       
},

       
/**
         * Removes a DOM node from the document.  The body node will be ignored if passed in.
         * @param {HTMLElement} node The node to remove
         */

        removeNode
: isIE ? function(){
           
var d;
           
return function(n){
               
if(n && n.tagName != 'BODY'){
                    d
= d || DOC.createElement('div');
                    d
.appendChild(n);
                    d
.innerHTML = '';
               
}
           
}
       
}() : function(n){
           
if(n && n.parentNode && n.tagName != 'BODY'){
                n
.parentNode.removeChild(n);
           
}
       
},

       
/**
         *

Returns true if the passed value is empty.


         *

The value is deemed to be empty if it is


         * @param {Mixed} value The value to test
         * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
         * @return {Boolean}
         */

        isEmpty
: function(v, allowBlank){
           
return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
       
},

       
/**
         * Returns true if the passed object is a JavaScript array, otherwise false.
         * @param {Object} object The object to test
         * @return {Boolean}
         */

        isArray
: function(v){
           
return toString.apply(v) === '[object Array]';
       
},

       
/**
         * Returns true if the passed object is a JavaScript Object, otherwise false.
         * @param {Object} object The object to test
         * @return {Boolean}
         */

        isObject
: function(v){
           
return v && typeof v == "object";
       
},

       
/**
         * Returns true if the passed object is a JavaScript 'primitive', a string, number or boolean.
         * @param {Mixed} value The value to test
         * @return {Boolean}
         */

        isPrimitive
: function(v){
           
return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
       
},

       
/**
         * Returns true if the passed object is a JavaScript Function, otherwise false.
         * @param {Object} object The object to test
         * @return {Boolean}
         */

        isFunction
: function(v){
           
return toString.apply(v) === '[object Function]';
       
},

       
/**
         * Returns true if the passed object is a number. Returns false for non-finite numbers.
         * @param {Object} v The object to test
         * @return {Boolean}
         */

        isNumber
: function(v){
           
return typeof v === 'number' && isFinite(v);
       
},

       
/**
         * Returns true if the passed object is a string.
         * @param {Object} v The object to test
         * @return {Boolean}
         */

        isString
: function(v){
           
return typeof v === 'string';
       
},

       
/**
         * Returns true if the passed object is a boolean.
         * @param {Object} v The object to test
         * @return {Boolean}
         */

        isBoolean
: function(v){
           
return typeof v === 'boolean';
       
},

       
/**
         * Returns true if the passed object is not undefined.
         * @param {Object} v The object to test
         * @return {Boolean}
         */

        isDefined
: function(v){
           
return typeof v !== 'undefined';
       
},

       
/**
         * True if the detected browser is Opera.
         * @type Boolean
         */

        isOpera
: isOpera,
       
/**
         * True if the detected browser uses WebKit.
         * @type Boolean
         */

        isWebKit
: isWebKit,
       
/**
         * True if the detected browser is Chrome.
         * @type Boolean
         */

        isChrome
: isChrome,
       
/**
         * True if the detected browser is Safari.
         * @type Boolean
         */

        isSafari
: isSafari,
       
/**
         * True if the detected browser is Safari 3.x.
         * @type Boolean
         */

        isSafari3
: isSafari3,
       
/**
         * True if the detected browser is Safari 4.x.
         * @type Boolean
         */

        isSafari4
: isSafari4,
       
/**
         * True if the detected browser is Safari 2.x.
         * @type Boolean
         */

        isSafari2
: isSafari2,
       
/**
         * True if the detected browser is Internet Explorer.
         * @type Boolean
         */

        isIE
: isIE,
       
/**
         * True if the detected browser is Internet Explorer 6.x.
         * @type Boolean
         */

        isIE6
: isIE6,
       
/**
         * True if the detected browser is Internet Explorer 7.x.
         * @type Boolean
         */

        isIE7
: isIE7,
       
/**
         * True if the detected browser is Internet Explorer 8.x.
         * @type Boolean
         */

        isIE8
: isIE8,
       
/**
         * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
         * @type Boolean
         */

        isGecko
: isGecko,
       
/**
         * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
         * @type Boolean
         */

        isGecko2
: isGecko2,
       
/**
         * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
         * @type Boolean
         */

        isGecko3
: isGecko3,
       
/**
         * True if the detected browser is Internet Explorer running in non-strict mode.
         * @type Boolean
         */

        isBorderBox
: isBorderBox,
       
/**
         * True if the detected platform is Linux.
         * @type Boolean
         */

        isLinux
: isLinux,
       
/**
         * True if the detected platform is Windows.
         * @type Boolean
         */

        isWindows
: isWindows,
       
/**
         * True if the detected platform is Mac OS.
         * @type Boolean
         */

        isMac
: isMac,
       
/**
         * True if the detected platform is Adobe Air.
         * @type Boolean
         */

        isAir
: isAir
   
});

   
/**
     * Creates namespaces to be used for scoping variables and classes so that they are not global.
     * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
     *

Ext.namespace('Company', 'Company.data');
Ext.namespace('Company.data'); // equivalent and preferable to above syntax
Company.Widget = function() { ... }
Company.data.CustomStore = function(config) { ... }

     * @param {String} namespace1
     * @param {String} namespace2
     * @param {String} etc
     * @method namespace
     */

   
Ext.ns = Ext.namespace;
})();

Ext.ns("Ext", "Ext.util", "Ext.lib", "Ext.data");


/**
 * @class Function
 * These functions are available on every Function object (any JavaScript function).
 */

Ext.apply(Function.prototype, {
     
/**
     * Creates an interceptor function. The passed fcn is called before the original one. If it returns false,
     * the original one is not called. The resulting function returns the results of the original function.
     * The passed fcn is called with the parameters of the original function. Example usage:
     *

var sayHi = function(name){
    alert('Hi, ' + name);
}

sayHi('Fred'); // alerts "Hi, Fred"

// create a new function that validates input without
// directly modifying the original function:
var sayHiToFriend = sayHi.createInterceptor(function(name){
    return name == 'Brian';
});

sayHiToFriend('Fred');  // no alert
sayHiToFriend('Brian'); // alerts "Hi, Brian"

     * @param {Function} fcn The function to call before the original
     * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
     * @return {Function} The new function
     */

    createInterceptor
: function(fcn, scope){
       
var method = this;
       
return !Ext.isFunction(fcn) ?
               
this :
               
function() {
                   
var me = this,
                        args
= arguments;
                    fcn
.target = me;
                    fcn
.method = method;
                   
return (fcn.apply(scope || me || window, args) !== false) ?
                            method
.apply(me || window, args) :
                           
null;
               
};
   
},

     
/**
     * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
     * Call directly on any function. Example:
myFunction.createCallback(arg1, arg2)
     * Will create a function that is bound to those 2 args.
If a specific scope is required in the
     * callback, use {@link #createDelegate} instead.
The function returned by createCallback always
     * executes in the window scope.
     *

This method is required when you want to pass arguments to a callback function.  If no arguments
     * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn).
     * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function
     * would simply execute immediately when the code is parsed. Example usage:
     *


var sayHi = function(name){
    alert('Hi, ' + name);
}

// clicking the button alerts "Hi, Fred"
new Ext.Button({
    text: 'Say Hi',
    renderTo: Ext.getBody(),
    handler: sayHi.createCallback('Fred')
});

     * @return {Function} The new function
    */

    createCallback
: function(/*args...*/){
       
// make args available, in function below
       
var args = arguments,
            method
= this;
       
return function() {
           
return method.apply(window, args);
       
};
   
},

   
/**
     * Creates a delegate (callback) that sets the scope to obj.
     * Call directly on any function. Example:
this.myFunction.createDelegate(this, [arg1, arg2])
     * Will create a function that is automatically scoped to obj so that the
this variable inside the
     * callback points to obj. Example usage:
     *

var sayHi = function(name){
    // Note this use of "this.text" here.  This function expects to
    // execute within a scope that contains a text property.  In this
    // example, the "this" variable is pointing to the btn object that
    // was passed in createDelegate below.
    alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
}

var btn = new Ext.Button({
    text: 'Say Hi',
    renderTo: Ext.getBody()
});

// This callback will execute in the scope of the
// button instance. Clicking the button alerts
// "Hi, Fred. You clicked the "Say Hi" button."
btn.on('click', sayHi.createDelegate(btn, ['Fred']));

     * @param {Object} obj (optional) The object for which the scope is set
     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
     *                                             if a number the args are inserted at the specified position
     * @return {Function} The new function
     */

    createDelegate
: function(obj, args, appendArgs){
       
var method = this;
       
return function() {
           
var callArgs = args || arguments;
           
if (appendArgs === true){
                callArgs
= Array.prototype.slice.call(arguments, 0);
                callArgs
= callArgs.concat(args);
           
}else if (Ext.isNumber(appendArgs)){
                callArgs
= Array.prototype.slice.call(arguments, 0); // copy arguments first
               
var applyArgs = [appendArgs, 0].concat(args); // create method call params
               
Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
           
}
           
return method.apply(obj || window, callArgs);
       
};
   
},

   
/**
     * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
     *

var sayHi = function(name){
    alert('Hi, ' + name);
}

// executes immediately:
sayHi('Fred');

// executes after 2 seconds:
sayHi.defer(2000, this, ['Fred']);

// this syntax is sometimes useful for deferring
// execution of an anonymous function:
(function(){
    alert('Anonymous');
}).defer(100);

     * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
     * @param {Object} obj (optional) The object for which the scope is set
     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
     *                                             if a number the args are inserted at the specified position
     * @return {Number} The timeout id that can be used with clearTimeout
     */

    defer
: function(millis, obj, args, appendArgs){
       
var fn = this.createDelegate(obj, args, appendArgs);
       
if(millis > 0){
           
return setTimeout(fn, millis);
       
}
        fn
();
       
return 0;
   
}
});

/**
 * @class String
 * These functions are available on every String object.
 */

Ext.applyIf(String, {
   
/**
     * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
     * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
     *

var cls = 'my-class', text = 'Some text';
var s = String.format('<div class="{0}">{1}</div>', cls, text);
// s now contains the string: '<div class="my-class">Some text</div>'
     *

     * @param {String} string The tokenized string to be formatted
     * @param {String} value1 The value to replace token {0}
     * @param {String} value2 Etc...
     * @return {String} The formatted string
     * @static
     */

    format
: function(format){
       
var args = Ext.toArray(arguments, 1);
       
return format.replace(/\{(\d+)\}/g, function(m, i){
           
return args[i];
       
});
   
}
});

/**
 * @class Array
 */

Ext.applyIf(Array.prototype, {
   
/**
     * Checks whether or not the specified object exists in the array.
     * @param {Object} o The object to check for
     * @return {Number} The index of o in the array (or -1 if it is not found)
     */

    indexOf
: function(o){
       
for (var i = 0, len = this.length; i < len; i++){
           
if(this[i] == o){
               
return i;
           
}
       
}
       
return -1;
   
},

   
/**
     * Removes the specified object from the array.  If the object is not found nothing happens.
     * @param {Object} o The object to remove
     * @return {Array} this array
     */

    remove
: function(o){
       
var index = this.indexOf(o);
       
if(index != -1){
           
this.splice(index, 1);
       
}
       
return this;
   
}
});