source: ext/3.4.1/adapter/jquery/ext-jquery-adapter-debug.js @ 2909

Last change on this file since 2909 was 2909, checked in by fredj, 5 years ago

Adding Ext 3.4.1

File size: 77.5 KB
Line 
1/*
2This file is part of Ext JS 3.4
3
4Copyright (c) 2011-2013 Sencha Inc
5
6Contact:  http://www.sencha.com/contact
7
8GNU General Public License Usage
9This file may be used under the terms of the GNU General Public License version 3.0 as
10published by the Free Software Foundation and appearing in the file LICENSE included in the
11packaging of this file.
12
13Please review the following information to ensure the GNU General Public License version 3.0
14requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15
16If you are unsure which license is appropriate for your use, please contact the sales department
17at http://www.sencha.com/contact.
18
19Build date: 2013-04-03 15:07:25
20*/
21// for old browsers
22window.undefined = window.undefined;
23
24/**
25 * @class Ext
26 * Ext core utilities and functions.
27 * @singleton
28 */
29
30Ext = {
31    /**
32     * The version of the framework
33     * @type String
34     */
35    version : '3.4.1.1',
36    versionDetail : {
37        major : 3,
38        minor : 4,
39        patch : 1.1
40    }
41};
42
43/**
44 * Copies all the properties of config to obj.
45 * @param {Object} obj The receiver of the properties
46 * @param {Object} config The source of the properties
47 * @param {Object} defaults A different object that will also be applied for default values
48 * @return {Object} returns obj
49 * @member Ext apply
50 */
51Ext.apply = function(o, c, defaults){
52    // no "this" reference for friendly out of scope calls
53    if(defaults){
54        Ext.apply(o, defaults);
55    }
56    if(o && c && typeof c == 'object'){
57        for(var p in c){
58            o[p] = c[p];
59        }
60    }
61    return o;
62};
63
64(function(){
65    var idSeed = 0,
66        toString = Object.prototype.toString,
67        ua = navigator.userAgent.toLowerCase(),
68        check = function(r){
69            return r.test(ua);
70        },
71        DOC = document,
72        docMode = DOC.documentMode,
73        isStrict = DOC.compatMode == "CSS1Compat",
74        isOpera = check(/opera/),
75        isChrome = check(/\bchrome\b/),
76        isWebKit = check(/webkit/),
77        isSafari = !isChrome && check(/safari/),
78        isSafari2 = isSafari && check(/applewebkit\/4/), // unique to Safari 2
79        isSafari3 = isSafari && check(/version\/3/),
80        isSafari4 = isSafari && check(/version\/4/),
81        isIE = !isOpera && check(/msie/),
82        isIE7 = isIE && ((check(/msie 7/) && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 7),
83        isIE8 = isIE && ((check(/msie 8/) && docMode != 7 && docMode != 9 && docMode != 10) || docMode == 8),
84        isIE9 = isIE && ((check(/msie 9/) && docMode != 7 && docMode != 8 && docMode != 10) || docMode == 9),
85        isIE10 = isIE && ((check(/msie 10/) && docMode != 7 && docMode != 8 && docMode != 9) || docMode == 10),
86        isIE6 = isIE && check(/msie 6/),
87        isIE9m = isIE && (isIE6 || isIE7 || isIE8 || isIE9),
88        isGecko = !isWebKit && check(/gecko/),
89        isGecko2 = isGecko && check(/rv:1\.8/),
90        isGecko3 = isGecko && check(/rv:1\.9/),
91        isBorderBox = isIE9m && !isStrict,
92        isWindows = check(/windows|win32/),
93        isMac = check(/macintosh|mac os x/),
94        isAir = check(/adobeair/),
95        isLinux = check(/linux/),
96        isSecure = /^https/i.test(window.location.protocol),
97        noArgs = [],
98        nonEnumerables = [],
99        emptyFn = Ext.emptyFn,
100        t = Ext.apply({}, {
101            constructor: emptyFn,
102            toString: emptyFn,
103            valueOf: emptyFn
104        }),
105        callOverrideParent = function () {
106            var method = callOverrideParent.caller.caller; // skip callParent (our caller)
107            return method.$owner.prototype[method.$name].apply(this, arguments);
108        };
109
110    if (t.constructor !== emptyFn) {
111        nonEnumerables.push('constructor');
112    }
113    if (t.toString !== emptyFn) {
114        nonEnumerables.push('toString');
115    }
116    if (t.valueOf !== emptyFn) {
117        nonEnumerables.push('valueOf');
118    }
119    if (!nonEnumerables.length) {
120        nonEnumerables = null;
121    }
122
123    // Create the abstract Base class to provide an empty constructor and callParent implementations
124    function Base () {
125        //
126    }
127
128    Ext.apply(Base, {
129        $isClass: true,
130
131        callParent: function (args) {
132            var method;
133
134            // This code is intentionally inlined for the least number of debugger stepping
135            return (method = this.callParent.caller) && (method.$previous ||
136                ((method = method.$owner ? method : method.caller) &&
137                        method.$owner.superclass.self[method.$name])).apply(this, args || noArgs);
138        }
139    });
140
141    Base.prototype = {
142        constructor: function() {
143        },
144        callParent: function(args) {
145            // NOTE: this code is deliberately as few expressions (and no function calls)
146            // as possible so that a debugger can skip over this noise with the minimum number
147            // of steps. Basically, just hit Step Into until you are where you really wanted
148            // to be.
149            var method,
150                superMethod = (method = this.callParent.caller) && (method.$previous ||
151                        ((method = method.$owner ? method : method.caller) &&
152                                method.$owner.superclass[method.$name]));
153
154            return superMethod.apply(this, args || noArgs);
155        }
156    };
157
158    // remove css image flicker
159    if(isIE6){
160        try{
161            DOC.execCommand("BackgroundImageCache", false, true);
162        }catch(e){}
163    }
164
165    Ext.apply(Ext, {
166        /**
167         * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent
168         * the IE insecure content warning (<tt>'about:blank'</tt>, except for IE in secure mode, which is <tt>'javascript:""'</tt>).
169         * @type String
170         */
171        SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
172        /**
173         * True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode
174         * @type Boolean
175         */
176        isStrict : isStrict,
177        /**
178         * True if the page is running over SSL
179         * @type Boolean
180         */
181        isSecure : isSecure,
182        /**
183         * True when the document is fully initialized and ready for action
184         * @type Boolean
185         */
186        isReady : false,
187
188        /**
189         * True if the {@link Ext.Fx} Class is available
190         * @type Boolean
191         * @property enableFx
192         */
193
194        /**
195         * HIGHLY EXPERIMENTAL
196         * True to force css based border-box model override and turning off javascript based adjustments. This is a
197         * runtime configuration and must be set before onReady.
198         * @type Boolean
199         */
200        enableForcedBoxModel : false,
201
202        /**
203         * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
204         * @type Boolean
205         */
206        enableGarbageCollector : true,
207
208        /**
209         * True to automatically purge event listeners during garbageCollection (defaults to false).
210         * @type Boolean
211         */
212        enableListenerCollection : false,
213
214        /**
215         * EXPERIMENTAL - True to cascade listener removal to child elements when an element is removed.
216         * Currently not optimized for performance.
217         * @type Boolean
218         */
219        enableNestedListenerRemoval : false,
220
221        /**
222         * Indicates whether to use native browser parsing for JSON methods.
223         * This option is ignored if the browser does not support native JSON methods.
224         * <b>Note: Native JSON methods will not work with objects that have functions.
225         * Also, property names must be quoted, otherwise the data will not parse.</b> (Defaults to false)
226         * @type Boolean
227         */
228        USE_NATIVE_JSON : false,
229
230        /**
231         * Copies all the properties of config to obj if they don't already exist.
232         * @param {Object} obj The receiver of the properties
233         * @param {Object} config The source of the properties
234         * @return {Object} returns obj
235         */
236        applyIf : function(o, c){
237            if(o){
238                for(var p in c){
239                    if(!Ext.isDefined(o[p])){
240                        o[p] = c[p];
241                    }
242                }
243            }
244            return o;
245        },
246
247        /**
248         * Generates unique ids. If the element already has an id, it is unchanged
249         * @param {Mixed} el (optional) The element to generate an id for
250         * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
251         * @return {String} The generated Id.
252         */
253        id : function(el, prefix){
254            el = Ext.getDom(el, true) || {};
255            if (!el.id) {
256                el.id = (prefix || "ext-gen") + (++idSeed);
257            }
258            return el.id;
259        },
260
261        /**
262         * <p>Extends one class to create a subclass and optionally overrides members with the passed literal. This method
263         * also adds the function "override()" to the subclass that can be used to override members of the class.</p>
264         * For example, to create a subclass of Ext GridPanel:
265         * <pre><code>
266MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
267    constructor: function(config) {
268
269//      Create configuration for this Grid.
270        var store = new Ext.data.Store({...});
271        var colModel = new Ext.grid.ColumnModel({...});
272
273//      Create a new config object containing our computed properties
274//      *plus* whatever was in the config parameter.
275        config = Ext.apply({
276            store: store,
277            colModel: colModel
278        }, config);
279
280        MyGridPanel.superclass.constructor.call(this, config);
281
282//      Your postprocessing here
283    },
284
285    yourMethod: function() {
286        // etc.
287    }
288});
289</code></pre>
290         *
291         * <p>This function also supports a 3-argument call in which the subclass's constructor is
292         * passed as an argument. In this form, the parameters are as follows:</p>
293         * <div class="mdetail-params"><ul>
294         * <li><code>subclass</code> : Function <div class="sub-desc">The subclass constructor.</div></li>
295         * <li><code>superclass</code> : Function <div class="sub-desc">The constructor of class being extended</div></li>
296         * <li><code>overrides</code> : Object <div class="sub-desc">A literal with members which are copied into the subclass's
297         * prototype, and are therefore shared among all instances of the new class.</div></li>
298         * </ul></div>
299         *
300         * @param {Function} superclass The constructor of class being extended.
301         * @param {Object} overrides <p>A literal with members which are copied into the subclass's
302         * prototype, and are therefore shared between all instances of the new class.</p>
303         * <p>This may contain a special member named <tt><b>constructor</b></tt>. This is used
304         * to define the constructor of the new class, and is returned. If this property is
305         * <i>not</i> specified, a constructor is generated and returned which just calls the
306         * superclass's constructor passing on its parameters.</p>
307         * <p><b>It is essential that you call the superclass constructor in any provided constructor. See example code.</b></p>
308         * @return {Function} The subclass constructor from the <code>overrides</code> parameter, or a generated one if not provided.
309         */
310        extend : function(){
311            // inline overrides
312            var io = function(o){
313                for(var m in o){
314                    this[m] = o[m];
315                }
316            };
317            var oc = Object.prototype.constructor;
318
319            return function(sb, sp, overrides){
320                if(typeof sp == 'object'){
321                    overrides = sp;
322                    sp = sb;
323                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
324                }
325                var F = function(){},
326                    sbp,
327                    spp = sp.prototype;
328
329                F.prototype = spp;
330                sbp = sb.prototype = new F();
331                sbp.constructor=sb;
332                sb.superclass=spp;
333                if(spp.constructor == oc){
334                    spp.constructor=sp;
335                }
336                sb.override = function(o){
337                    Ext.override(sb, o);
338                };
339                sbp.superclass = sbp.supr = (function(){
340                    return spp;
341                });
342                sbp.override = io;
343                Ext.override(sb, overrides);
344                sb.extend = function(o){return Ext.extend(sb, o);};
345                return sb;
346            };
347        }(),
348
349        global: (function () {
350            return this;
351        })(),
352
353        Base: Base,
354
355        namespaceCache: {},
356
357        createNamespace: function (namespaceOrClass, isClass) {
358            var cache = Ext.namespaceCache,
359                namespace = isClass ? namespaceOrClass.substring(0, namespaceOrClass.lastIndexOf('.'))
360                            : namespaceOrClass,
361                ns = cache[namespace],
362                i, n, part, parts, partials;
363
364            if (!ns) {
365                ns = Ext.global;
366                if (namespace) {
367                    partials = [];
368                    parts = namespace.split('.');
369
370                    for (i = 0, n = parts.length; i < n; ++i) {
371                        part = parts[i];
372
373                        ns = ns[part] || (ns[part] = {});
374                        partials.push(part);
375
376                        cache[partials.join('.')] = ns; // build up prefixes as we go
377                    }
378                }
379            }
380
381            return ns;
382        },
383
384        getClassByName: function (className) {
385            var parts = className.split('.'),
386                cls = Ext.global,
387                n = parts.length,
388                i;
389
390            for (i = 0; cls && i < n; ++i) {
391                cls = cls[parts[i]];
392            }
393
394            return cls || null;
395        },
396
397        addMembers: function (cls, target, members, handleNonEnumerables) {
398            var i, name, member;
399
400            for (name in members) {
401                if (members.hasOwnProperty(name)) {
402                    member = members[name];
403                    if (typeof member == 'function') {
404                        member.$owner = cls;
405                        member.$name = name;
406                    }
407
408                    target[name] = member;
409                }
410            }
411
412            if (handleNonEnumerables && nonEnumerables) {
413                for (i = nonEnumerables.length; i-- > 0; ) {
414                    name = nonEnumerables[i];
415                    if (members.hasOwnProperty(name)) {
416                        member = members[name];
417                        if (typeof member == 'function') {
418                            member.$owner = cls;
419                            member.$name = name;
420                        }
421
422                        target[name] = member;
423                    }
424                }
425            }
426        },
427
428        /**
429         * @method
430         * Defines a class or override. A basic class is defined like this:
431         *
432         *      Ext.define('My.awesome.Class', {
433         *          someProperty: 'something',
434         *
435         *          someMethod: function(s) {
436         *              alert(s + this.someProperty);
437         *          }
438         *
439         *          ...
440         *      });
441         *
442         *      var obj = new My.awesome.Class();
443         *
444         *      obj.someMethod('Say '); // alerts 'Say something'
445         *
446         * To create an anonymous class, pass `null` for the `className`:
447         *
448         *      Ext.define(null, {
449         *          constructor: function () {
450         *              // ...
451         *          }
452         *      });
453         *
454         * In some cases, it is helpful to create a nested scope to contain some private
455         * properties. The best way to do this is to pass a function instead of an object
456         * as the second parameter. This function will be called to produce the class
457         * body:
458         *
459         *      Ext.define('MyApp.foo.Bar', function () {
460         *          var id = 0;
461         *         
462         *          return {
463         *              nextId: function () {
464         *                  return ++id;
465         *              }
466         *          };
467         *      });
468         *
469         * When using this form of `Ext.define`, the function is passed a reference to its
470         * class. This can be used as an efficient way to access any static properties you
471         * may have:
472         *
473         *      Ext.define('MyApp.foo.Bar', function (Bar) {
474         *          return {
475         *              statics: {
476         *                  staticMethod: function () {
477         *                      // ...
478         *                  }
479         *              },
480         *             
481         *              method: function () {
482         *                  return Bar.staticMethod();
483         *              }
484         *          };
485         *      });
486         *
487         * To define an override, include the `override` property. The content of an
488         * override is aggregated with the specified class in order to extend or modify
489         * that class. This can be as simple as setting default property values or it can
490         * extend and/or replace methods. This can also extend the statics of the class.
491         *
492         * One use for an override is to break a large class into manageable pieces.
493         *
494         *      // File: /src/app/Panel.js
495         *
496         *      Ext.define('My.app.Panel', {
497         *          extend: 'Ext.panel.Panel',
498         *
499         *          constructor: function (config) {
500         *              this.callParent(arguments); // calls Ext.panel.Panel's constructor
501         *              //...
502         *          },
503         *
504         *          statics: {
505         *              method: function () {
506         *                  return 'abc';
507         *              }
508         *          }
509         *      });
510         *
511         *      // File: /src/app/PanelPart2.js
512         *      Ext.define('My.app.PanelPart2', {
513         *          override: 'My.app.Panel',
514         *
515         *          constructor: function (config) {
516         *              this.callParent(arguments); // calls My.app.Panel's constructor
517         *              //...
518         *          }
519         *      });
520         *
521         * Another use of overrides is to provide optional parts of classes that can be
522         * independently required. In this case, the class may even be unaware of the
523         * override altogether.
524         *
525         *      Ext.define('My.ux.CoolTip', {
526         *          override: 'Ext.tip.ToolTip',
527         *
528         *          constructor: function (config) {
529         *              this.callParent(arguments); // calls Ext.tip.ToolTip's constructor
530         *              //...
531         *          }
532         *      });
533         *
534         * Overrides can also contain statics:
535         *
536         *      Ext.define('My.app.BarMod', {
537         *          override: 'Ext.foo.Bar',
538         *
539         *          statics: {
540         *              method: function (x) {
541         *                  return this.callParent([x * 2]); // call Ext.foo.Bar.method
542         *              }
543         *          }
544         *      });
545         *
546         * @param {String} className The class name to create in string dot-namespaced format, for example:
547         * 'My.very.awesome.Class', 'FeedViewer.plugin.CoolPager'
548         * It is highly recommended to follow this simple convention:
549         *  - The root and the class name are 'CamelCased'
550         *  - Everything else is lower-cased
551         * Pass `null` to create an anonymous class.
552         * @param {Object} data The key - value pairs of properties to apply to this class. Property names can be of any valid
553         * strings, except those in the reserved listed below:
554         *  - `mixins`
555         *  - `statics`
556         *  - `config`
557         *  - `alias`
558         *  - `self`
559         *  - `singleton`
560         *  - `alternateClassName`
561         *  - `override`
562         *
563         * @param {Function} createdFn Optional callback to execute after the class is created, the execution scope of which
564         * (`this`) will be the newly created class itself.
565         * @return {Ext.Base}
566         * @markdown
567         * @member Ext
568         * @method define
569         */
570        define: function (className, body, createdFn) {
571            var override = body.override,
572                cls, extend, name, namespace;
573
574            if (override) {
575                delete body.override;
576                cls = Ext.getClassByName(override);
577                Ext.override(cls, body);
578            } else {
579                if (className) {
580                    namespace = Ext.createNamespace(className, true);
581                    name = className.substring(className.lastIndexOf('.')+1);
582                }
583
584                cls = function ctor () {
585                    this.constructor.apply(this, arguments);
586                }
587
588                if (className) {
589                    cls.displayName = className;
590                }
591                cls.$isClass = true;
592                cls.callParent = Ext.Base.callParent;
593
594                if (typeof body == 'function') {
595                    body = body(cls);
596                }
597
598                extend = body.extend;
599                if (extend) {
600                    delete body.extend;
601                    if (typeof extend == 'string') {
602                        extend = Ext.getClassByName(extend);
603                    }
604                } else {
605                    extend = Base;
606                }
607
608                Ext.extend(cls, extend, body);
609                if (cls.prototype.constructor === cls) {
610                    delete cls.prototype.constructor;
611                }
612
613                // Not extending a class which derives from Base...
614                if (!cls.prototype.$isClass) {
615                    Ext.applyIf(cls.prototype, Base.prototype);
616                }
617                cls.prototype.self = cls;
618               
619                if (body.xtype) {
620                    Ext.reg(body.xtype, cls);
621                }
622                cls = body.singleton ? new cls() : cls;
623                if (className) {
624                    namespace[name] = cls;
625                }
626            }
627
628            if (createdFn) {
629                createdFn.call(cls);
630            }
631
632            return cls;
633        },
634
635        /**
636         * Overrides members of the specified `target` with the given values.
637         *
638         * If the `target` is a function, it is assumed to be a constructor and the contents
639         * of `overrides` are applied to its `prototype` using {@link Ext#apply Ext.apply}.
640         *
641         * If the `target` is an instance of a class created using {@link #define},
642         * the `overrides` are applied to only that instance. In this case, methods are
643         * specially processed to allow them to use {@link Ext.Base#callParent}.
644         *
645         *      var panel = new Ext.Panel({ ... });
646         *     
647         *      Ext.override(panel, {
648         *          initComponent: function () {
649         *              // extra processing...
650         *             
651         *              this.callParent();
652         *          }
653         *      });
654         *
655         * If the `target` is none of these, the `overrides` are applied to the `target`
656         * using {@link Ext#apply Ext.apply}.
657         *
658         * Please refer to {@link Ext#define Ext.define} for further details.
659         *
660         * @param {Object} target The target to override.
661         * @param {Object} overrides The properties to add or replace on `target`.
662         * @method override
663         */
664        override: function (target, overrides) {
665            var proto, statics;
666
667            if (overrides) {
668                if (target.$isClass) {
669                    statics = overrides.statics;
670                    if (statics) {
671                        delete overrides.statics;
672                    }
673
674                    Ext.addMembers(target, target.prototype, overrides, true);
675                    if (statics) {
676                        Ext.addMembers(target, target, statics);
677                    }
678                } else if (typeof target == 'function') {
679                    proto = target.prototype;
680                    Ext.apply(proto, overrides);
681                    if(Ext.isIE && overrides.hasOwnProperty('toString')){
682                        proto.toString = overrides.toString;
683                    }
684                } else {
685                    var owner = target.self,
686                        name, value;
687
688                    if (owner && owner.$isClass) {
689                        for (name in overrides) {
690                            if (overrides.hasOwnProperty(name)) {
691                                value = overrides[name];
692
693                                if (typeof value == 'function') {
694                                    //<debug>
695                                    if (owner.$className) {
696                                        value.displayName = owner.$className + '#' + name;
697                                    }
698                                    //</debug>
699
700                                    value.$name = name;
701                                    value.$owner = owner;
702                                    value.$previous = target.hasOwnProperty(name)
703                                        ? target[name] // already hooked, so call previous hook
704                                        : callOverrideParent; // calls by name on prototype
705                                }
706
707                                target[name] = value;
708                            }
709                        }
710                    } else {
711                        Ext.apply(target, overrides);
712
713                        if (!target.constructor.$isClass) {
714                            target.constructor.prototype.callParent = Base.prototype.callParent;
715                            target.constructor.callParent = Base.callParent;
716                        }
717                    }
718                }
719            }
720        },
721
722        /**
723         * Creates namespaces to be used for scoping variables and classes so that they are not global.
724         * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
725         * <pre><code>
726Ext.namespace('Company', 'Company.data');
727Ext.namespace('Company.data'); // equivalent and preferable to above syntax
728Company.Widget = function() { ... }
729Company.data.CustomStore = function(config) { ... }
730</code></pre>
731         * @param {String} namespace1
732         * @param {String} namespace2
733         * @param {String} etc
734         * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
735         * @method namespace
736         */
737        namespace : function(){
738            var len1 = arguments.length,
739                i = 0,
740                len2,
741                j,
742                main,
743                ns,
744                sub,
745                current;
746
747            for(; i < len1; ++i) {
748                main = arguments[i];
749                ns = arguments[i].split('.');
750                current = window[ns[0]];
751                if (current === undefined) {
752                    current = window[ns[0]] = {};
753                }
754                sub = ns.slice(1);
755                len2 = sub.length;
756                for(j = 0; j < len2; ++j) {
757                    current = current[sub[j]] = current[sub[j]] || {};
758                }
759            }
760            return current;
761        },
762
763        /**
764         * 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.
765         * @param {Object} o
766         * @param {String} pre (optional) A prefix to add to the url encoded string
767         * @return {String}
768         */
769        urlEncode : function(o, pre){
770            var empty,
771                buf = [],
772                e = encodeURIComponent;
773
774            Ext.iterate(o, function(key, item){
775                empty = Ext.isEmpty(item);
776                Ext.each(empty ? key : item, function(val){
777                    buf.push('&', e(key), '=', (!Ext.isEmpty(val) && (val != key || !empty)) ? (Ext.isDate(val) ? Ext.encode(val).replace(/"/g, '') : e(val)) : '');
778                });
779            });
780            if(!pre){
781                buf.shift();
782                pre = '';
783            }
784            return pre + buf.join('');
785        },
786
787        /**
788         * Takes an encoded URL and and converts it to an object. Example: <pre><code>
789Ext.urlDecode("foo=1&bar=2"); // returns {foo: "1", bar: "2"}
790Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2", "3", "4"]}
791</code></pre>
792         * @param {String} string
793         * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
794         * @return {Object} A literal with members
795         */
796        urlDecode : function(string, overwrite){
797            if(Ext.isEmpty(string)){
798                return {};
799            }
800            var obj = {},
801                pairs = string.split('&'),
802                d = decodeURIComponent,
803                name,
804                value;
805            Ext.each(pairs, function(pair) {
806                pair = pair.split('=');
807                name = d(pair[0]);
808                value = d(pair[1]);
809                obj[name] = overwrite || !obj[name] ? value :
810                            [].concat(obj[name]).concat(value);
811            });
812            return obj;
813        },
814
815        /**
816         * Appends content to the query string of a URL, handling logic for whether to place
817         * a question mark or ampersand.
818         * @param {String} url The URL to append to.
819         * @param {String} s The content to append to the URL.
820         * @return (String) The resulting URL
821         */
822        urlAppend : function(url, s){
823            if(!Ext.isEmpty(s)){
824                return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
825            }
826            return url;
827        },
828
829        /**
830         * Converts any iterable (numeric indices and a length property) into a true array
831         * Don't use this on strings. IE doesn't support "abc"[0] which this implementation depends on.
832         * For strings, use this instead: "abc".match(/./g) => [a,b,c];
833         * @param {Iterable} the iterable object to be turned into a true Array.
834         * @return (Array) array
835         */
836         toArray : function(){
837             return isIE ?
838                 function(a, i, j, res){
839                     res = [];
840                     for(var x = 0, len = a.length; x < len; x++) {
841                         res.push(a[x]);
842                     }
843                     return res.slice(i || 0, j || res.length);
844                 } :
845                 function(a, i, j){
846                     return Array.prototype.slice.call(a, i || 0, j || a.length);
847                 };
848         }(),
849
850        isIterable : function(v){
851            //check for array or arguments
852            if(Ext.isArray(v) || v.callee){
853                return true;
854            }
855            //check for node list type
856            if(/NodeList|HTMLCollection/.test(toString.call(v))){
857                return true;
858            }
859            //NodeList has an item and length property
860            //IXMLDOMNodeList has nextNode method, needs to be checked first.
861            return ((typeof v.nextNode != 'undefined' || v.item) && Ext.isNumber(v.length));
862        },
863
864        /**
865         * Iterates an array calling the supplied function.
866         * @param {Array/NodeList/Mixed} array The array to be iterated. If this
867         * argument is not really an array, the supplied function is called once.
868         * @param {Function} fn The function to be called with each item. If the
869         * supplied function returns false, iteration stops and this method returns
870         * the current <code>index</code>. This function is called with
871         * the following arguments:
872         * <div class="mdetail-params"><ul>
873         * <li><code>item</code> : <i>Mixed</i>
874         * <div class="sub-desc">The item at the current <code>index</code>
875         * in the passed <code>array</code></div></li>
876         * <li><code>index</code> : <i>Number</i>
877         * <div class="sub-desc">The current index within the array</div></li>
878         * <li><code>allItems</code> : <i>Array</i>
879         * <div class="sub-desc">The <code>array</code> passed as the first
880         * argument to <code>Ext.each</code>.</div></li>
881         * </ul></div>
882         * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed.
883         * Defaults to the <code>item</code> at the current <code>index</code>
884         * within the passed <code>array</code>.
885         * @return See description for the fn parameter.
886         */
887        each : function(array, fn, scope){
888            if(Ext.isEmpty(array, true)){
889                return;
890            }
891            if(!Ext.isIterable(array) || Ext.isPrimitive(array)){
892                array = [array];
893            }
894            for(var i = 0, len = array.length; i < len; i++){
895                if(fn.call(scope || array[i], array[i], i, array) === false){
896                    return i;
897                };
898            }
899        },
900
901        /**
902         * Iterates either the elements in an array, or each of the properties in an object.
903         * <b>Note</b>: If you are only iterating arrays, it is better to call {@link #each}.
904         * @param {Object/Array} object The object or array to be iterated
905         * @param {Function} fn The function to be called for each iteration.
906         * The iteration will stop if the supplied function returns false, or
907         * all array elements / object properties have been covered. The signature
908         * varies depending on the type of object being interated:
909         * <div class="mdetail-params"><ul>
910         * <li>Arrays : <tt>(Object item, Number index, Array allItems)</tt>
911         * <div class="sub-desc">
912         * When iterating an array, the supplied function is called with each item.</div></li>
913         * <li>Objects : <tt>(String key, Object value, Object)</tt>
914         * <div class="sub-desc">
915         * When iterating an object, the supplied function is called with each key-value pair in
916         * the object, and the iterated object</div></li>
917         * </ul></div>
918         * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed. Defaults to
919         * the <code>object</code> being iterated.
920         */
921        iterate : function(obj, fn, scope){
922            if(Ext.isEmpty(obj)){
923                return;
924            }
925            if(Ext.isIterable(obj)){
926                Ext.each(obj, fn, scope);
927                return;
928            }else if(typeof obj == 'object'){
929                for(var prop in obj){
930                    if(obj.hasOwnProperty(prop)){
931                        if(fn.call(scope || obj, prop, obj[prop], obj) === false){
932                            return;
933                        };
934                    }
935                }
936            }
937        },
938
939        /**
940         * Return the dom node for the passed String (id), dom node, or Ext.Element.
941         * Optional 'strict' flag is needed for IE since it can return 'name' and
942         * 'id' elements by using getElementById.
943         * Here are some examples:
944         * <pre><code>
945// gets dom node based on id
946var elDom = Ext.getDom('elId');
947// gets dom node based on the dom node
948var elDom1 = Ext.getDom(elDom);
949
950// If we don&#39;t know if we are working with an
951// Ext.Element or a dom node use Ext.getDom
952function(el){
953    var dom = Ext.getDom(el);
954    // do something with the dom node
955}
956         * </code></pre>
957         * <b>Note</b>: the dom node to be found actually needs to exist (be rendered, etc)
958         * when this method is called to be successful.
959         * @param {Mixed} el
960         * @return HTMLElement
961         */
962        getDom : function(el, strict){
963            if(!el || !DOC){
964                return null;
965            }
966            if (el.dom){
967                return el.dom;
968            } else {
969                if (typeof el == 'string') {
970                    var e = DOC.getElementById(el);
971                    // IE returns elements with the 'name' and 'id' attribute.
972                    // we do a strict check to return the element with only the id attribute
973                    if (e && isIE && strict) {
974                        if (el == e.getAttribute('id')) {
975                            return e;
976                        } else {
977                            return null;
978                        }
979                    }
980                    return e;
981                } else {
982                    return el;
983                }
984            }
985        },
986
987        /**
988         * Returns the current document body as an {@link Ext.Element}.
989         * @return Ext.Element The document body
990         */
991        getBody : function(){
992            return Ext.get(DOC.body || DOC.documentElement);
993        },
994
995        /**
996         * Returns the current document body as an {@link Ext.Element}.
997         * @return Ext.Element The document body
998         * @method
999         */
1000        getHead : function() {
1001            var head;
1002
1003            return function() {
1004                if (head == undefined) {
1005                    head = Ext.get(DOC.getElementsByTagName("head")[0]);
1006                }
1007
1008                return head;
1009            };
1010        }(),
1011
1012        /**
1013         * <p>Removes this element from the document, removes all DOM event listeners, and deletes the cache reference.
1014         * All DOM event listeners are removed from this element. If {@link Ext#enableNestedListenerRemoval} is
1015         * <code>true</code>, then DOM event listeners are also removed from all child nodes. The body node
1016         * will be ignored if passed in.</p>
1017         * @param {HTMLElement} node The node to remove
1018         * @method
1019         */
1020        removeNode : isIE && !isIE8 ? function(){
1021            var d;
1022            return function(n){
1023                if(n && n.tagName != 'BODY'){
1024                    (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
1025                    d = d || DOC.createElement('div');
1026                    d.appendChild(n);
1027                    d.innerHTML = '';
1028                    delete Ext.elCache[n.id];
1029                }
1030            };
1031        }() : function(n){
1032            if(n && n.parentNode && n.tagName != 'BODY'){
1033                (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
1034                n.parentNode.removeChild(n);
1035                delete Ext.elCache[n.id];
1036            }
1037        },
1038
1039        /**
1040         * <p>Returns true if the passed value is empty.</p>
1041         * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
1042         * <li>null</li>
1043         * <li>undefined</li>
1044         * <li>an empty array</li>
1045         * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
1046         * </ul></div>
1047         * @param {Mixed} value The value to test
1048         * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
1049         * @return {Boolean}
1050         */
1051        isEmpty : function(v, allowBlank){
1052            return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
1053        },
1054
1055        /**
1056         * Returns true if the passed value is a JavaScript array, otherwise false.
1057         * @param {Mixed} value The value to test
1058         * @return {Boolean}
1059         */
1060        isArray : function(v){
1061            return toString.apply(v) === '[object Array]';
1062        },
1063
1064        /**
1065         * Returns true if the passed object is a JavaScript date object, otherwise false.
1066         * @param {Object} object The object to test
1067         * @return {Boolean}
1068         */
1069        isDate : function(v){
1070            return toString.apply(v) === '[object Date]';
1071        },
1072
1073        /**
1074         * Returns true if the passed value is a JavaScript Object, otherwise false.
1075         * @param {Mixed} value The value to test
1076         * @return {Boolean}
1077         */
1078        isObject : function(v){
1079            return !!v && Object.prototype.toString.call(v) === '[object Object]';
1080        },
1081
1082        /**
1083         * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
1084         * @param {Mixed} value The value to test
1085         * @return {Boolean}
1086         */
1087        isPrimitive : function(v){
1088            return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
1089        },
1090
1091        /**
1092         * Returns true if the passed value is a JavaScript Function, otherwise false.
1093         * @param {Mixed} value The value to test
1094         * @return {Boolean}
1095         */
1096        isFunction : function(v){
1097            return toString.apply(v) === '[object Function]';
1098        },
1099
1100        /**
1101         * Returns true if the passed value is a number. Returns false for non-finite numbers.
1102         * @param {Mixed} value The value to test
1103         * @return {Boolean}
1104         */
1105        isNumber : function(v){
1106            return typeof v === 'number' && isFinite(v);
1107        },
1108
1109        /**
1110         * Returns true if the passed value is a string.
1111         * @param {Mixed} value The value to test
1112         * @return {Boolean}
1113         */
1114        isString : function(v){
1115            return typeof v === 'string';
1116        },
1117
1118        /**
1119         * Returns true if the passed value is a boolean.
1120         * @param {Mixed} value The value to test
1121         * @return {Boolean}
1122         */
1123        isBoolean : function(v){
1124            return typeof v === 'boolean';
1125        },
1126
1127        /**
1128         * Returns true if the passed value is an HTMLElement
1129         * @param {Mixed} value The value to test
1130         * @return {Boolean}
1131         */
1132        isElement : function(v) {
1133            return v ? !!v.tagName : false;
1134        },
1135
1136        /**
1137         * Returns true if the passed value is not undefined.
1138         * @param {Mixed} value The value to test
1139         * @return {Boolean}
1140         */
1141        isDefined : function(v){
1142            return typeof v !== 'undefined';
1143        },
1144
1145        /**
1146         * True if the detected browser is Opera.
1147         * @type Boolean
1148         */
1149        isOpera : isOpera,
1150        /**
1151         * True if the detected browser uses WebKit.
1152         * @type Boolean
1153         */
1154        isWebKit : isWebKit,
1155        /**
1156         * True if the detected browser is Chrome.
1157         * @type Boolean
1158         */
1159        isChrome : isChrome,
1160        /**
1161         * True if the detected browser is Safari.
1162         * @type Boolean
1163         */
1164        isSafari : isSafari,
1165        /**
1166         * True if the detected browser is Safari 3.x.
1167         * @type Boolean
1168         */
1169        isSafari3 : isSafari3,
1170        /**
1171         * True if the detected browser is Safari 4.x.
1172         * @type Boolean
1173         */
1174        isSafari4 : isSafari4,
1175        /**
1176         * True if the detected browser is Safari 2.x.
1177         * @type Boolean
1178         */
1179        isSafari2 : isSafari2,
1180        /**
1181         * True if the detected browser is Internet Explorer.
1182         * @type Boolean
1183         */
1184        isIE : isIE,
1185        /**
1186         * True if the detected browser is Internet Explorer 6.x.
1187         * @type Boolean
1188         */
1189        isIE6 : isIE6,
1190        /**
1191         * True if the detected browser is Internet Explorer 7.x.
1192         * @type Boolean
1193         */
1194        isIE7 : isIE7,
1195        /**
1196         * True if the detected browser is Internet Explorer 8.x.
1197         * @type Boolean
1198         */
1199        isIE8 : isIE8,
1200        /**
1201         * True if the detected browser is Internet Explorer 9.x.
1202         * @type Boolean
1203         */
1204        isIE9 : isIE9,
1205       
1206        /**
1207         * True if the detected browser is Internet Explorer 10.x
1208         * @type Boolean
1209         */
1210        isIE10 : isIE10,
1211       
1212        /**
1213         * True if the detected browser is Internet Explorer 9.x or lower
1214         * @type Boolean
1215         */
1216        isIE9m : isIE9m,
1217       
1218        /**
1219         * True if the detected browser is Internet Explorer 10.x or higher
1220         * @type Boolean
1221         */
1222        isIE10p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9),
1223       
1224        // IE10 quirks behaves like Gecko/WebKit quirks, so don't include it here
1225        // Used internally
1226        isIEQuirks: isIE && (!isStrict && (isIE6 || isIE7 || isIE8 || isIE9)),
1227               
1228        /**
1229         * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
1230         * @type Boolean
1231         */
1232        isGecko : isGecko,
1233        /**
1234         * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
1235         * @type Boolean
1236         */
1237        isGecko2 : isGecko2,
1238        /**
1239         * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
1240         * @type Boolean
1241         */
1242        isGecko3 : isGecko3,
1243        /**
1244         * True if the detected browser is Internet Explorer running in non-strict mode.
1245         * @type Boolean
1246         */
1247        isBorderBox : isBorderBox,
1248        /**
1249         * True if the detected platform is Linux.
1250         * @type Boolean
1251         */
1252        isLinux : isLinux,
1253        /**
1254         * True if the detected platform is Windows.
1255         * @type Boolean
1256         */
1257        isWindows : isWindows,
1258        /**
1259         * True if the detected platform is Mac OS.
1260         * @type Boolean
1261         */
1262        isMac : isMac,
1263        /**
1264         * True if the detected platform is Adobe Air.
1265         * @type Boolean
1266         */
1267        isAir : isAir
1268    });
1269
1270    /**
1271     * Creates namespaces to be used for scoping variables and classes so that they are not global.
1272     * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
1273     * <pre><code>
1274Ext.namespace('Company', 'Company.data');
1275Ext.namespace('Company.data'); // equivalent and preferable to above syntax
1276Company.Widget = function() { ... }
1277Company.data.CustomStore = function(config) { ... }
1278</code></pre>
1279     * @param {String} namespace1
1280     * @param {String} namespace2
1281     * @param {String} etc
1282     * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
1283     * @method ns
1284     */
1285    Ext.ns = Ext.namespace;
1286})();
1287
1288Ext.ns('Ext.util', 'Ext.lib', 'Ext.data', 'Ext.supports');
1289
1290Ext.elCache = {};
1291
1292/**
1293 * @class Function
1294 * These functions are available on every Function object (any JavaScript function).
1295 */
1296Ext.apply(Function.prototype, {
1297     /**
1298     * Creates an interceptor function. The passed function is called before the original one. If it returns false,
1299     * the original one is not called. The resulting function returns the results of the original function.
1300     * The passed function is called with the parameters of the original function. Example usage:
1301     * <pre><code>
1302var sayHi = function(name){
1303    alert('Hi, ' + name);
1304}
1305
1306sayHi('Fred'); // alerts "Hi, Fred"
1307
1308// create a new function that validates input without
1309// directly modifying the original function:
1310var sayHiToFriend = sayHi.createInterceptor(function(name){
1311    return name == 'Brian';
1312});
1313
1314sayHiToFriend('Fred');  // no alert
1315sayHiToFriend('Brian'); // alerts "Hi, Brian"
1316</code></pre>
1317     * @param {Function} fcn The function to call before the original
1318     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
1319     * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
1320     * @return {Function} The new function
1321     */
1322    createInterceptor : function(fcn, scope){
1323        var method = this;
1324        return !Ext.isFunction(fcn) ?
1325                this :
1326                function() {
1327                    var me = this,
1328                        args = arguments;
1329                    fcn.target = me;
1330                    fcn.method = method;
1331                    return (fcn.apply(scope || me || window, args) !== false) ?
1332                            method.apply(me || window, args) :
1333                            null;
1334                };
1335    },
1336
1337     /**
1338     * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
1339     * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code>
1340     * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the
1341     * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always
1342     * executes in the window scope.
1343     * <p>This method is required when you want to pass arguments to a callback function.  If no arguments
1344     * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn).
1345     * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function
1346     * would simply execute immediately when the code is parsed. Example usage:
1347     * <pre><code>
1348var sayHi = function(name){
1349    alert('Hi, ' + name);
1350}
1351
1352// clicking the button alerts "Hi, Fred"
1353new Ext.Button({
1354    text: 'Say Hi',
1355    renderTo: Ext.getBody(),
1356    handler: sayHi.createCallback('Fred')
1357});
1358</code></pre>
1359     * @return {Function} The new function
1360    */
1361    createCallback : function(/*args...*/){
1362        // make args available, in function below
1363        var args = arguments,
1364            method = this;
1365        return function() {
1366            return method.apply(window, args);
1367        };
1368    },
1369
1370    /**
1371     * Creates a delegate (callback) that sets the scope to obj.
1372     * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code>
1373     * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
1374     * callback points to obj. Example usage:
1375     * <pre><code>
1376var sayHi = function(name){
1377    // Note this use of "this.text" here.  This function expects to
1378    // execute within a scope that contains a text property.  In this
1379    // example, the "this" variable is pointing to the btn object that
1380    // was passed in createDelegate below.
1381    alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
1382}
1383
1384var btn = new Ext.Button({
1385    text: 'Say Hi',
1386    renderTo: Ext.getBody()
1387});
1388
1389// This callback will execute in the scope of the
1390// button instance. Clicking the button alerts
1391// "Hi, Fred. You clicked the "Say Hi" button."
1392btn.on('click', sayHi.createDelegate(btn, ['Fred']));
1393</code></pre>
1394     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
1395     * <b>If omitted, defaults to the browser window.</b>
1396     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
1397     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
1398     * if a number the args are inserted at the specified position
1399     * @return {Function} The new function
1400     */
1401    createDelegate : function(obj, args, appendArgs){
1402        var method = this;
1403        return function() {
1404            var callArgs = args || arguments;
1405            if (appendArgs === true){
1406                callArgs = Array.prototype.slice.call(arguments, 0);
1407                callArgs = callArgs.concat(args);
1408            }else if (Ext.isNumber(appendArgs)){
1409                callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
1410                var applyArgs = [appendArgs, 0].concat(args); // create method call params
1411                Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
1412            }
1413            return method.apply(obj || window, callArgs);
1414        };
1415    },
1416
1417    /**
1418     * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
1419     * <pre><code>
1420var sayHi = function(name){
1421    alert('Hi, ' + name);
1422}
1423
1424// executes immediately:
1425sayHi('Fred');
1426
1427// executes after 2 seconds:
1428sayHi.defer(2000, this, ['Fred']);
1429
1430// this syntax is sometimes useful for deferring
1431// execution of an anonymous function:
1432(function(){
1433    alert('Anonymous');
1434}).defer(100);
1435</code></pre>
1436     * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
1437     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
1438     * <b>If omitted, defaults to the browser window.</b>
1439     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
1440     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
1441     * if a number the args are inserted at the specified position
1442     * @return {Number} The timeout id that can be used with clearTimeout
1443     */
1444    defer : function(millis, obj, args, appendArgs){
1445        var fn = this.createDelegate(obj, args, appendArgs);
1446        if(millis > 0){
1447            return setTimeout(fn, millis);
1448        }
1449        fn();
1450        return 0;
1451    }
1452});
1453
1454/**
1455 * @class String
1456 * These functions are available on every String object.
1457 */
1458Ext.applyIf(String, {
1459    /**
1460     * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
1461     * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
1462     * <pre><code>
1463var cls = 'my-class', text = 'Some text';
1464var s = String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
1465// s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
1466     * </code></pre>
1467     * @param {String} string The tokenized string to be formatted
1468     * @param {String} value1 The value to replace token {0}
1469     * @param {String} value2 Etc...
1470     * @return {String} The formatted string
1471     * @static
1472     */
1473    format : function(format){
1474        var args = Ext.toArray(arguments, 1);
1475        return format.replace(/\{(\d+)\}/g, function(m, i){
1476            return args[i];
1477        });
1478    }
1479});
1480
1481/**
1482 * @class Array
1483 */
1484Ext.applyIf(Array.prototype, {
1485    /**
1486     * Checks whether or not the specified object exists in the array.
1487     * @param {Object} o The object to check for
1488     * @param {Number} from (Optional) The index at which to begin the search
1489     * @return {Number} The index of o in the array (or -1 if it is not found)
1490     */
1491    indexOf : function(o, from){
1492        var len = this.length;
1493        from = from || 0;
1494        from += (from < 0) ? len : 0;
1495        for (; from < len; ++from){
1496            if(this[from] === o){
1497                return from;
1498            }
1499        }
1500        return -1;
1501    },
1502
1503    /**
1504     * Removes the specified object from the array.  If the object is not found nothing happens.
1505     * @param {Object} o The object to remove
1506     * @return {Array} this array
1507     */
1508    remove : function(o){
1509        var index = this.indexOf(o);
1510        if(index != -1){
1511            this.splice(index, 1);
1512        }
1513        return this;
1514    }
1515});
1516/**
1517 * @class Ext.util.TaskRunner
1518 * Provides the ability to execute one or more arbitrary tasks in a multithreaded
1519 * manner.  Generally, you can use the singleton {@link Ext.TaskMgr} instead, but
1520 * if needed, you can create separate instances of TaskRunner.  Any number of
1521 * separate tasks can be started at any time and will run independently of each
1522 * other. Example usage:
1523 * <pre><code>
1524// Start a simple clock task that updates a div once per second
1525var updateClock = function(){
1526    Ext.fly('clock').update(new Date().format('g:i:s A'));
1527}
1528var task = {
1529    run: updateClock,
1530    interval: 1000 //1 second
1531}
1532var runner = new Ext.util.TaskRunner();
1533runner.start(task);
1534
1535// equivalent using TaskMgr
1536Ext.TaskMgr.start({
1537    run: updateClock,
1538    interval: 1000
1539});
1540
1541 * </code></pre>
1542 * <p>See the {@link #start} method for details about how to configure a task object.</p>
1543 * Also see {@link Ext.util.DelayedTask}.
1544 *
1545 * @constructor
1546 * @param {Number} interval (optional) The minimum precision in milliseconds supported by this TaskRunner instance
1547 * (defaults to 10)
1548 */
1549Ext.util.TaskRunner = function(interval){
1550    interval = interval || 10;
1551    var tasks = [],
1552        removeQueue = [],
1553        id = 0,
1554        running = false,
1555
1556        // private
1557        stopThread = function(){
1558                running = false;
1559                clearInterval(id);
1560                id = 0;
1561            },
1562
1563        // private
1564        startThread = function(){
1565                if(!running){
1566                    running = true;
1567                    id = setInterval(runTasks, interval);
1568                }
1569            },
1570
1571        // private
1572        removeTask = function(t){
1573                removeQueue.push(t);
1574                if(t.onStop){
1575                    t.onStop.apply(t.scope || t);
1576                }
1577            },
1578           
1579        // private
1580        runTasks = function(){
1581                var rqLen = removeQueue.length,
1582                        now = new Date().getTime();                                             
1583           
1584                if(rqLen > 0){
1585                    for(var i = 0; i < rqLen; i++){
1586                        tasks.remove(removeQueue[i]);
1587                    }
1588                    removeQueue = [];
1589                    if(tasks.length < 1){
1590                        stopThread();
1591                        return;
1592                    }
1593                }               
1594                for(var i = 0, t, itime, rt, len = tasks.length; i < len; ++i){
1595                    t = tasks[i];
1596                    itime = now - t.taskRunTime;
1597                    if(t.interval <= itime){
1598                        rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
1599                        t.taskRunTime = now;
1600                        if(rt === false || t.taskRunCount === t.repeat){
1601                            removeTask(t);
1602                            return;
1603                        }
1604                    }
1605                    if(t.duration && t.duration <= (now - t.taskStartTime)){
1606                        removeTask(t);
1607                    }
1608                }
1609            };
1610
1611    /**
1612     * Starts a new task.
1613     * @method start
1614     * @param {Object} task <p>A config object that supports the following properties:<ul>
1615     * <li><code>run</code> : Function<div class="sub-desc"><p>The function to execute each time the task is invoked. The
1616     * function will be called at each interval and passed the <code>args</code> argument if specified, and the
1617     * current invocation count if not.</p>
1618     * <p>If a particular scope (<code>this</code> reference) is required, be sure to specify it using the <code>scope</code> argument.</p>
1619     * <p>Return <code>false</code> from this function to terminate the task.</p></div></li>
1620     * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
1621     * should be invoked.</div></li>
1622     * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
1623     * specified by <code>run</code>. If not specified, the current invocation count is passed.</div></li>
1624     * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
1625     * <code>run</code> function. Defaults to the task config object.</div></li>
1626     * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to invoke
1627     * the task before stopping automatically (defaults to indefinite).</div></li>
1628     * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to invoke the task before
1629     * stopping automatically (defaults to indefinite).</div></li>
1630     * </ul></p>
1631     * <p>Before each invocation, Ext injects the property <code>taskRunCount</code> into the task object so
1632     * that calculations based on the repeat count can be performed.</p>
1633     * @return {Object} The task
1634     */
1635    this.start = function(task){
1636        tasks.push(task);
1637        task.taskStartTime = new Date().getTime();
1638        task.taskRunTime = 0;
1639        task.taskRunCount = 0;
1640        startThread();
1641        return task;
1642    };
1643
1644    /**
1645     * Stops an existing running task.
1646     * @method stop
1647     * @param {Object} task The task to stop
1648     * @return {Object} The task
1649     */
1650    this.stop = function(task){
1651        removeTask(task);
1652        return task;
1653    };
1654
1655    /**
1656     * Stops all tasks that are currently running.
1657     * @method stopAll
1658     */
1659    this.stopAll = function(){
1660        stopThread();
1661        for(var i = 0, len = tasks.length; i < len; i++){
1662            if(tasks[i].onStop){
1663                tasks[i].onStop();
1664            }
1665        }
1666        tasks = [];
1667        removeQueue = [];
1668    };
1669};
1670
1671/**
1672 * @class Ext.TaskMgr
1673 * @extends Ext.util.TaskRunner
1674 * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
1675 * {@link Ext.util.TaskRunner} for supported methods and task config properties.
1676 * <pre><code>
1677// Start a simple clock task that updates a div once per second
1678var task = {
1679    run: function(){
1680        Ext.fly('clock').update(new Date().format('g:i:s A'));
1681    },
1682    interval: 1000 //1 second
1683}
1684Ext.TaskMgr.start(task);
1685</code></pre>
1686 * <p>See the {@link #start} method for details about how to configure a task object.</p>
1687 * @singleton
1688 */
1689Ext.TaskMgr = new Ext.util.TaskRunner();if(typeof jQuery == "undefined"){
1690    throw "Unable to load Ext, jQuery not found.";
1691}
1692
1693(function(){
1694var libFlyweight;
1695
1696Ext.lib.Dom = {
1697    getViewWidth : function(full){
1698        // jQuery doesn't report full window size on document query, so max both
1699        return full ? Math.max(jQuery(document).width(),jQuery(window).width()) : jQuery(window).width();
1700    },
1701
1702    getViewHeight : function(full){
1703        // jQuery doesn't report full window size on document query, so max both
1704        return full ? Math.max(jQuery(document).height(),jQuery(window).height()) : jQuery(window).height();
1705    },
1706
1707    isAncestor : function(p, c){
1708        var ret = false;
1709
1710        p = Ext.getDom(p);
1711        c = Ext.getDom(c);
1712        if (p && c) {
1713            if (p.contains) {
1714                return p.contains(c);
1715            } else if (p.compareDocumentPosition) {
1716                return !!(p.compareDocumentPosition(c) & 16);
1717            } else {
1718                while (c = c.parentNode) {
1719                    ret = c == p || ret;
1720                }
1721            }
1722        }
1723        return ret;
1724    },
1725
1726    getRegion : function(el){
1727        return Ext.lib.Region.getRegion(el);
1728    },
1729
1730    //////////////////////////////////////////////////////////////////////////////////////
1731    // Use of jQuery.offset() removed to promote consistent behavior across libs.
1732    // JVS 05/23/07
1733    //////////////////////////////////////////////////////////////////////////////////////
1734
1735    getY : function(el){
1736        return this.getXY(el)[1];
1737    },
1738
1739    getX : function(el){
1740        return this.getXY(el)[0];
1741    },
1742
1743    getXY : function(el) {
1744        var p, pe, b, scroll, bd = (document.body || document.documentElement);
1745        el = Ext.getDom(el);
1746
1747        if(el == bd){
1748            return [0, 0];
1749        }
1750
1751        if (el.getBoundingClientRect) {
1752            b = el.getBoundingClientRect();
1753            scroll = fly(document).getScroll();
1754            return [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
1755        }
1756        var x = 0, y = 0;
1757
1758        p = el;
1759
1760        var hasAbsolute = fly(el).getStyle("position") == "absolute";
1761
1762        while (p) {
1763
1764            x += p.offsetLeft;
1765            y += p.offsetTop;
1766
1767            if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1768                hasAbsolute = true;
1769            }
1770
1771            if (Ext.isGecko) {
1772                pe = fly(p);
1773
1774                var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1775                var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1776
1777
1778                x += bl;
1779                y += bt;
1780
1781
1782                if (p != el && pe.getStyle('overflow') != 'visible') {
1783                    x += bl;
1784                    y += bt;
1785                }
1786            }
1787            p = p.offsetParent;
1788        }
1789
1790        if (Ext.isSafari && hasAbsolute) {
1791            x -= bd.offsetLeft;
1792            y -= bd.offsetTop;
1793        }
1794
1795        if (Ext.isGecko && !hasAbsolute) {
1796            var dbd = fly(bd);
1797            x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1798            y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1799        }
1800
1801        p = el.parentNode;
1802        while (p && p != bd) {
1803            if (!Ext.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1804                x -= p.scrollLeft;
1805                y -= p.scrollTop;
1806            }
1807            p = p.parentNode;
1808        }
1809        return [x, y];
1810    },
1811
1812    setXY : function(el, xy){
1813        el = Ext.fly(el, '_setXY');
1814        el.position();
1815        var pts = el.translatePoints(xy);
1816        if(xy[0] !== false){
1817            el.dom.style.left = pts.left + "px";
1818        }
1819        if(xy[1] !== false){
1820            el.dom.style.top = pts.top + "px";
1821        }
1822    },
1823
1824    setX : function(el, x){
1825        this.setXY(el, [x, false]);
1826    },
1827
1828    setY : function(el, y){
1829        this.setXY(el, [false, y]);
1830    }
1831};
1832
1833// all lib flyweight calls use their own flyweight to prevent collisions with developer flyweights
1834function fly(el){
1835    if(!libFlyweight){
1836        libFlyweight = new Ext.Element.Flyweight();
1837    }
1838    libFlyweight.dom = el;
1839    return libFlyweight;
1840}
1841Ext.lib.Event = {
1842    getPageX : function(e){
1843        e = e.browserEvent || e;
1844        return e.pageX;
1845    },
1846
1847    getPageY : function(e){
1848        e = e.browserEvent || e;
1849        return e.pageY;
1850    },
1851
1852    getXY : function(e){
1853        e = e.browserEvent || e;
1854        return [e.pageX, e.pageY];
1855    },
1856
1857    getTarget : function(e){
1858        return e.target;
1859    },
1860
1861    // all Ext events will go through event manager which provides scoping
1862    on : function(el, eventName, fn, scope, override){
1863        jQuery(el).bind(eventName, fn);
1864    },
1865
1866    un : function(el, eventName, fn){
1867        jQuery(el).unbind(eventName, fn);
1868    },
1869
1870    purgeElement : function(el){
1871        jQuery(el).unbind();
1872    },
1873
1874    preventDefault : function(e){
1875        e = e.browserEvent || e;
1876        if(e.preventDefault){
1877            e.preventDefault();
1878        }else{
1879            e.returnValue = false;
1880        }
1881    },
1882
1883    stopPropagation : function(e){
1884        e = e.browserEvent || e;
1885        if(e.stopPropagation){
1886            e.stopPropagation();
1887        }else{
1888            e.cancelBubble = true;
1889        }
1890    },
1891
1892    stopEvent : function(e){
1893        this.preventDefault(e);
1894        this.stopPropagation(e);
1895    },
1896
1897    onAvailable : function(id, fn, scope){
1898        var start = new Date();
1899        var f = function(){
1900            if(start.getElapsed() > 10000){
1901                clearInterval(iid);
1902            }
1903            var el = document.getElementById(id);
1904            if(el){
1905                clearInterval(iid);
1906                fn.call(scope||window, el);
1907            }
1908        };
1909        var iid = setInterval(f, 50);
1910    },
1911
1912    resolveTextNode: Ext.isGecko ? function(node){
1913        if(!node){
1914            return;
1915        }
1916        var s = HTMLElement.prototype.toString.call(node);
1917        if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
1918            return;
1919        }
1920        return node.nodeType == 3 ? node.parentNode : node;
1921    } : function(node){
1922        return node && node.nodeType == 3 ? node.parentNode : node;
1923    },
1924
1925    getRelatedTarget: function(ev) {
1926        ev = ev.browserEvent || ev;
1927        var t = ev.relatedTarget;
1928        if (!t) {
1929            if (ev.type == "mouseout") {
1930                t = ev.toElement;
1931            } else if (ev.type == "mouseover") {
1932                t = ev.fromElement;
1933            }
1934        }
1935
1936        return this.resolveTextNode(t);
1937    }
1938};
1939
1940Ext.lib.Ajax = function(){
1941    var createComplete = function(cb){
1942         return function(xhr, status){
1943            if((status == 'error' || status == 'timeout') && cb.failure){
1944                cb.failure.call(cb.scope||window, createResponse(cb, xhr));
1945            }else if(cb.success){
1946                cb.success.call(cb.scope||window, createResponse(cb, xhr));
1947            }
1948         };
1949    };
1950
1951    var createResponse = function(cb, xhr){
1952        var headerObj = {},
1953            headerStr,
1954            t,
1955            s;
1956
1957        try {
1958            headerStr = xhr.getAllResponseHeaders();
1959            Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'), function(v){
1960                t = v.indexOf(':');
1961                if(t >= 0){
1962                    s = v.substr(0, t).toLowerCase();
1963                    if(v.charAt(t + 1) == ' '){
1964                        ++t;
1965                    }
1966                    headerObj[s] = v.substr(t + 1);
1967                }
1968            });
1969        } catch(e) {}
1970
1971        return {
1972            responseText: xhr.responseText,
1973            responseXML : xhr.responseXML,
1974            argument: cb.argument,
1975            status: xhr.status,
1976            statusText: xhr.statusText,
1977            getResponseHeader : function(header){
1978                return headerObj[header.toLowerCase()];
1979            },
1980            getAllResponseHeaders : function(){
1981                return headerStr;
1982            }
1983        };
1984    };
1985    return {
1986        request : function(method, uri, cb, data, options){
1987            var o = {
1988                type: method,
1989                url: uri,
1990                data: data,
1991                timeout: cb.timeout,
1992                complete: createComplete(cb)
1993            };
1994
1995            if(options){
1996                var hs = options.headers;
1997                if(options.xmlData){
1998                    o.data = options.xmlData;
1999                    o.processData = false;
2000                    o.type = (method ? method : (options.method ? options.method : 'POST'));
2001                    if (!hs || !hs['Content-Type']){
2002                        o.contentType = 'text/xml';
2003                    }
2004                }else if(options.jsonData){
2005                    o.data = typeof options.jsonData == 'object' ? Ext.encode(options.jsonData) : options.jsonData;
2006                    o.processData = false;
2007                    o.type = (method ? method : (options.method ? options.method : 'POST'));
2008                    if (!hs || !hs['Content-Type']){
2009                        o.contentType = 'application/json';
2010                    }
2011                }
2012                if(hs){
2013                    o.beforeSend = function(xhr){
2014                        for (var h in hs) {
2015                            if (hs.hasOwnProperty(h)) {
2016                                xhr.setRequestHeader(h, hs[h]);
2017                            }
2018                        }
2019                    };
2020                }
2021            }
2022            jQuery.ajax(o);
2023        },
2024
2025        formRequest : function(form, uri, cb, data, isUpload, sslUri){
2026            jQuery.ajax({
2027                type: Ext.getDom(form).method ||'POST',
2028                url: uri,
2029                data: jQuery(form).serialize()+(data?'&'+data:''),
2030                timeout: cb.timeout,
2031                complete: createComplete(cb)
2032            });
2033        },
2034
2035        isCallInProgress : function(trans){
2036            return false;
2037        },
2038
2039        abort : function(trans){
2040            return false;
2041        },
2042
2043        serializeForm : function(form){
2044            return jQuery(form.dom||form).serialize();
2045        }
2046    };
2047}();
2048
2049Ext.lib.Anim = function(){
2050    var createAnim = function(cb, scope){
2051        var animated = true;
2052        return {
2053            stop : function(skipToLast){
2054                // do nothing
2055            },
2056
2057            isAnimated : function(){
2058                return animated;
2059            },
2060
2061            proxyCallback : function(){
2062                animated = false;
2063                Ext.callback(cb, scope);
2064            }
2065        };
2066    };
2067    return {
2068        scroll : function(el, args, duration, easing, cb, scope){
2069            // scroll anim not supported so just scroll immediately
2070            var anim = createAnim(cb, scope);
2071            el = Ext.getDom(el);
2072            if(typeof args.scroll.to[0] == 'number'){
2073                el.scrollLeft = args.scroll.to[0];
2074            }
2075            if(typeof args.scroll.to[1] == 'number'){
2076                el.scrollTop = args.scroll.to[1];
2077            }
2078            anim.proxyCallback();
2079            return anim;
2080        },
2081
2082        motion : function(el, args, duration, easing, cb, scope){
2083            return this.run(el, args, duration, easing, cb, scope);
2084        },
2085
2086        color : function(el, args, duration, easing, cb, scope){
2087            // color anim not supported, so execute callback immediately
2088            var anim = createAnim(cb, scope);
2089            anim.proxyCallback();
2090            return anim;
2091        },
2092
2093        run : function(el, args, duration, easing, cb, scope, type){
2094            var anim = createAnim(cb, scope), e = Ext.fly(el, '_animrun');
2095            var o = {};
2096            for(var k in args){
2097                switch(k){   // jquery doesn't support, so convert
2098                    case 'points':
2099                        var by, pts;
2100                        e.position();
2101                        if(by = args.points.by){
2102                            var xy = e.getXY();
2103                            pts = e.translatePoints([xy[0]+by[0], xy[1]+by[1]]);
2104                        }else{
2105                            pts = e.translatePoints(args.points.to);
2106                        }
2107                        o.left = pts.left;
2108                        o.top = pts.top;
2109                        if(!parseInt(e.getStyle('left'), 10)){ // auto bug
2110                            e.setLeft(0);
2111                        }
2112                        if(!parseInt(e.getStyle('top'), 10)){
2113                            e.setTop(0);
2114                        }
2115                        if(args.points.from){
2116                            e.setXY(args.points.from);
2117                        }
2118                    break;
2119                    case 'width':
2120                        o.width = args.width.to;
2121                        if (args.width.from)
2122                            e.setWidth(args.width.from);
2123                    break;
2124                    case 'height':
2125                        o.height = args.height.to;
2126                        if (args.height.from)
2127                            e.setHeight(args.height.from);
2128                    break;
2129                    case 'opacity':
2130                        o.opacity = args.opacity.to;
2131                        if (args.opacity.from)
2132                            e.setOpacity(args.opacity.from);
2133                    break;
2134                    case 'left':
2135                        o.left = args.left.to;
2136                        if (args.left.from)
2137                            e.setLeft(args.left.from);
2138                    break;
2139                    case 'top':
2140                        o.top = args.top.to;
2141                        if (args.top.from)
2142                            e.setTop(args.top.from);
2143                    break;
2144                        // jQuery can't handle callback, scope, and xy arguments, so break here
2145                    case 'callback':
2146                    case 'scope':
2147                    case 'xy':
2148                    break;
2149
2150                    default:
2151                        o[k] = args[k].to;
2152                        if (args[k].from)
2153                            e.setStyle(k, args[k].from);
2154                    break;
2155                }
2156            }
2157            // TODO: find out about easing plug in?
2158            jQuery(el).animate(o, duration*1000, undefined, anim.proxyCallback);
2159            return anim;
2160        }
2161    };
2162}();
2163
2164
2165Ext.lib.Region = function(t, r, b, l) {
2166    this.top = t;
2167    this[1] = t;
2168    this.right = r;
2169    this.bottom = b;
2170    this.left = l;
2171    this[0] = l;
2172};
2173
2174Ext.lib.Region.prototype = {
2175    contains : function(region) {
2176        return ( region.left   >= this.left   &&
2177                 region.right  <= this.right  &&
2178                 region.top    >= this.top    &&
2179                 region.bottom <= this.bottom    );
2180
2181    },
2182
2183    getArea : function() {
2184        return ( (this.bottom - this.top) * (this.right - this.left) );
2185    },
2186
2187    intersect : function(region) {
2188        var t = Math.max( this.top,    region.top    );
2189        var r = Math.min( this.right,  region.right  );
2190        var b = Math.min( this.bottom, region.bottom );
2191        var l = Math.max( this.left,   region.left   );
2192
2193        if (b >= t && r >= l) {
2194            return new Ext.lib.Region(t, r, b, l);
2195        } else {
2196            return null;
2197        }
2198    },
2199    union : function(region) {
2200        var t = Math.min( this.top,    region.top    );
2201        var r = Math.max( this.right,  region.right  );
2202        var b = Math.max( this.bottom, region.bottom );
2203        var l = Math.min( this.left,   region.left   );
2204
2205        return new Ext.lib.Region(t, r, b, l);
2206    },
2207
2208    constrainTo : function(r) {
2209            this.top = this.top.constrain(r.top, r.bottom);
2210            this.bottom = this.bottom.constrain(r.top, r.bottom);
2211            this.left = this.left.constrain(r.left, r.right);
2212            this.right = this.right.constrain(r.left, r.right);
2213            return this;
2214    },
2215
2216    adjust : function(t, l, b, r){
2217        this.top += t;
2218        this.left += l;
2219        this.right += r;
2220        this.bottom += b;
2221        return this;
2222    }
2223};
2224
2225Ext.lib.Region.getRegion = function(el) {
2226    var p = Ext.lib.Dom.getXY(el);
2227
2228    var t = p[1];
2229    var r = p[0] + el.offsetWidth;
2230    var b = p[1] + el.offsetHeight;
2231    var l = p[0];
2232
2233    return new Ext.lib.Region(t, r, b, l);
2234};
2235
2236Ext.lib.Point = function(x, y) {
2237   if (Ext.isArray(x)) {
2238      y = x[1];
2239      x = x[0];
2240   }
2241    this.x = this.right = this.left = this[0] = x;
2242    this.y = this.top = this.bottom = this[1] = y;
2243};
2244
2245Ext.lib.Point.prototype = new Ext.lib.Region();
2246
2247// prevent IE leaks
2248if(Ext.isIE) {
2249    function fnCleanUp() {
2250        var p = Function.prototype;
2251        delete p.createSequence;
2252        delete p.defer;
2253        delete p.createDelegate;
2254        delete p.createCallback;
2255        delete p.createInterceptor;
2256
2257        window.detachEvent("onunload", fnCleanUp);
2258    }
2259    window.attachEvent("onunload", fnCleanUp);
2260}
2261})();
Note: See TracBrowser for help on using the repository browser.