// 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; } });