source: ext/3.4.1/adapter/yui/ext-yui-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: 71.1 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 YAHOO == "undefined"){
1690    throw "Unable to load Ext, core YUI utilities (yahoo, dom, event) not found.";
1691}
1692
1693(function(){
1694    var E = YAHOO.util.Event,
1695        D = YAHOO.util.Dom,
1696        CN = YAHOO.util.Connect,
1697        ES = YAHOO.util.Easing,
1698        A = YAHOO.util.Anim,
1699        libFlyweight,
1700        version = YAHOO.env.getVersion('yahoo').version.split('.'),
1701        mouseEnterSupported = parseInt(version[0], 10) >= 3,
1702        mouseCache = {},
1703        elContains = function(parent, child){
1704            if(parent && parent.firstChild){
1705                while(child){
1706                    if(child === parent){
1707                        return true;
1708                    }
1709                    child = child.parentNode;
1710                    if(child && (child.nodeType != 1)){
1711                        child = null;
1712                    }
1713                }
1714            }
1715            return false;
1716        }, checkRelatedTarget = function(e){
1717            return !elContains(e.currentTarget, Ext.lib.Event.getRelatedTarget(e));
1718        };
1719
1720Ext.lib.Dom = {
1721    getViewWidth : function(full){
1722        return full ? D.getDocumentWidth() : D.getViewportWidth();
1723    },
1724
1725    getViewHeight : function(full){
1726        return full ? D.getDocumentHeight() : D.getViewportHeight();
1727    },
1728
1729    isAncestor : function(haystack, needle){
1730        return D.isAncestor(haystack, needle);
1731    },
1732
1733    getRegion : function(el){
1734        return D.getRegion(el);
1735    },
1736
1737    getY : function(el){
1738        return this.getXY(el)[1];
1739    },
1740
1741    getX : function(el){
1742        return this.getXY(el)[0];
1743    },
1744
1745    // original version based on YahooUI getXY
1746    // this version fixes several issues in Safari and FF
1747    // and boosts performance by removing the batch overhead, repetitive dom lookups and array index calls
1748    getXY : function(el){
1749        var p, pe, b, scroll, bd = (document.body || document.documentElement);
1750        el = Ext.getDom(el);
1751
1752        if(el == bd){
1753            return [0, 0];
1754        }
1755
1756        if (el.getBoundingClientRect) {
1757            b = el.getBoundingClientRect();
1758            scroll = fly(document).getScroll();
1759            return [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
1760        }
1761        var x = 0, y = 0;
1762
1763        p = el;
1764
1765        var hasAbsolute = fly(el).getStyle("position") == "absolute";
1766
1767        while (p) {
1768
1769            x += p.offsetLeft;
1770            y += p.offsetTop;
1771
1772            if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1773                hasAbsolute = true;
1774            }
1775
1776            if (Ext.isGecko) {
1777                pe = fly(p);
1778
1779                var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1780                var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1781
1782
1783                x += bl;
1784                y += bt;
1785
1786
1787                if (p != el && pe.getStyle('overflow') != 'visible') {
1788                    x += bl;
1789                    y += bt;
1790                }
1791            }
1792            p = p.offsetParent;
1793        }
1794
1795        if (Ext.isSafari && hasAbsolute) {
1796            x -= bd.offsetLeft;
1797            y -= bd.offsetTop;
1798        }
1799
1800        if (Ext.isGecko && !hasAbsolute) {
1801            var dbd = fly(bd);
1802            x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1803            y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1804        }
1805
1806        p = el.parentNode;
1807        while (p && p != bd) {
1808            if (!Ext.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1809                x -= p.scrollLeft;
1810                y -= p.scrollTop;
1811            }
1812            p = p.parentNode;
1813        }
1814        return [x, y];
1815    },
1816
1817    setXY : function(el, xy){
1818        el = Ext.fly(el, '_setXY');
1819        el.position();
1820        var pts = el.translatePoints(xy);
1821        if(xy[0] !== false){
1822            el.dom.style.left = pts.left + "px";
1823        }
1824        if(xy[1] !== false){
1825            el.dom.style.top = pts.top + "px";
1826        }
1827    },
1828
1829    setX : function(el, x){
1830        this.setXY(el, [x, false]);
1831    },
1832
1833    setY : function(el, y){
1834        this.setXY(el, [false, y]);
1835    }
1836};
1837
1838Ext.lib.Event = {
1839    getPageX : function(e){
1840        return E.getPageX(e.browserEvent || e);
1841    },
1842
1843    getPageY : function(e){
1844        return E.getPageY(e.browserEvent || e);
1845    },
1846
1847    getXY : function(e){
1848        return E.getXY(e.browserEvent || e);
1849    },
1850
1851    getTarget : function(e){
1852        return E.getTarget(e.browserEvent || e);
1853    },
1854
1855    getRelatedTarget : function(e){
1856        return E.getRelatedTarget(e.browserEvent || e);
1857    },
1858
1859    on : function(el, eventName, fn, scope, override){
1860        if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
1861            var item = mouseCache[el.id] || (mouseCache[el.id] = {});
1862            item[eventName] = fn;
1863            fn = fn.createInterceptor(checkRelatedTarget);
1864            eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
1865        }
1866        E.on(el, eventName, fn, scope, override);
1867    },
1868
1869    un : function(el, eventName, fn){
1870        if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
1871            var item = mouseCache[el.id],
1872                ev = item && item[eventName];
1873
1874            if(ev){
1875                fn = ev.fn;
1876                delete item[eventName];
1877                eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
1878            }
1879        }
1880        E.removeListener(el, eventName, fn);;
1881    },
1882
1883    purgeElement : function(el){
1884        E.purgeElement(el);
1885    },
1886
1887    preventDefault : function(e){
1888        E.preventDefault(e.browserEvent || e);
1889    },
1890
1891    stopPropagation : function(e){
1892        E.stopPropagation(e.browserEvent || e);
1893    },
1894
1895    stopEvent : function(e){
1896        E.stopEvent(e.browserEvent || e);
1897    },
1898
1899    onAvailable : function(el, fn, scope, override){
1900        return E.onAvailable(el, fn, scope, override);
1901    }
1902};
1903
1904Ext.lib.Ajax = {
1905    request : function(method, uri, cb, data, options){
1906        if(options){
1907            var hs = options.headers;
1908            if(hs){
1909                for(var h in hs){
1910                    if(hs.hasOwnProperty(h)){
1911                        CN.initHeader(h, hs[h], false);
1912                    }
1913                }
1914            }
1915            if(options.xmlData){
1916                if (!hs || !hs['Content-Type']){
1917                    CN.initHeader('Content-Type', 'text/xml', false);
1918                }
1919                method = (method ? method : (options.method ? options.method : 'POST'));
1920                data = options.xmlData;
1921            }else if(options.jsonData){
1922                if (!hs || !hs['Content-Type']){
1923                    CN.initHeader('Content-Type', 'application/json', false);
1924                }
1925                method = (method ? method : (options.method ? options.method : 'POST'));
1926                data = typeof options.jsonData == 'object' ? Ext.encode(options.jsonData) : options.jsonData;
1927            }
1928        }
1929        return CN.asyncRequest(method, uri, cb, data);
1930    },
1931
1932    formRequest : function(form, uri, cb, data, isUpload, sslUri){
1933        CN.setForm(form, isUpload, sslUri);
1934        return CN.asyncRequest(Ext.getDom(form).method ||'POST', uri, cb, data);
1935    },
1936
1937    isCallInProgress : function(trans){
1938        return CN.isCallInProgress(trans);
1939    },
1940
1941    abort : function(trans){
1942        return CN.abort(trans);
1943    },
1944
1945    serializeForm : function(form){
1946        var d = CN.setForm(form.dom || form);
1947        CN.resetFormState();
1948        return d;
1949    }
1950};
1951
1952Ext.lib.Region = YAHOO.util.Region;
1953Ext.lib.Point = YAHOO.util.Point;
1954
1955
1956Ext.lib.Anim = {
1957    scroll : function(el, args, duration, easing, cb, scope){
1958        this.run(el, args, duration, easing, cb, scope, YAHOO.util.Scroll);
1959    },
1960
1961    motion : function(el, args, duration, easing, cb, scope){
1962        this.run(el, args, duration, easing, cb, scope, YAHOO.util.Motion);
1963    },
1964
1965    color : function(el, args, duration, easing, cb, scope){
1966        this.run(el, args, duration, easing, cb, scope, YAHOO.util.ColorAnim);
1967    },
1968
1969    run : function(el, args, duration, easing, cb, scope, type){
1970        type = type || YAHOO.util.Anim;
1971        if(typeof easing == "string"){
1972            easing = YAHOO.util.Easing[easing];
1973        }
1974        var anim = new type(el, args, duration, easing);
1975        anim.animateX(function(){
1976            Ext.callback(cb, scope);
1977        });
1978        return anim;
1979    }
1980};
1981
1982// all lib flyweight calls use their own flyweight to prevent collisions with developer flyweights
1983function fly(el){
1984    if(!libFlyweight){
1985        libFlyweight = new Ext.Element.Flyweight();
1986    }
1987    libFlyweight.dom = el;
1988    return libFlyweight;
1989}
1990
1991// prevent IE leaks
1992if(Ext.isIE) {
1993    function fnCleanUp() {
1994        var p = Function.prototype;
1995        delete p.createSequence;
1996        delete p.defer;
1997        delete p.createDelegate;
1998        delete p.createCallback;
1999        delete p.createInterceptor;
2000
2001        window.detachEvent("onunload", fnCleanUp);
2002    }
2003    window.attachEvent("onunload", fnCleanUp);
2004}
2005// various overrides
2006
2007// add ability for callbacks with animations
2008if(YAHOO.util.Anim){
2009    YAHOO.util.Anim.prototype.animateX = function(callback, scope){
2010        var f = function(){
2011            this.onComplete.unsubscribe(f);
2012            if(typeof callback == "function"){
2013                callback.call(scope || this, this);
2014            }
2015        };
2016        this.onComplete.subscribe(f, this, true);
2017        this.animate();
2018    };
2019}
2020
2021if(YAHOO.util.DragDrop && Ext.dd.DragDrop){
2022    YAHOO.util.DragDrop.defaultPadding = Ext.dd.DragDrop.defaultPadding;
2023    YAHOO.util.DragDrop.constrainTo = Ext.dd.DragDrop.constrainTo;
2024}
2025
2026YAHOO.util.Dom.getXY = function(el) {
2027    var f = function(el) {
2028        return Ext.lib.Dom.getXY(el);
2029    };
2030    return YAHOO.util.Dom.batch(el, f, YAHOO.util.Dom, true);
2031};
2032
2033
2034// workaround for Safari anim duration speed problems
2035if(YAHOO.util.AnimMgr){
2036    YAHOO.util.AnimMgr.fps = 1000;
2037}
2038
2039YAHOO.util.Region.prototype.adjust = function(t, l, b, r){
2040    this.top += t;
2041    this.left += l;
2042    this.right += r;
2043    this.bottom += b;
2044    return this;
2045};
2046   
2047YAHOO.util.Region.prototype.constrainTo = function(r) {
2048    this.top = this.top.constrain(r.top, r.bottom);
2049    this.bottom = this.bottom.constrain(r.top, r.bottom);
2050    this.left = this.left.constrain(r.left, r.right);
2051    this.right = this.right.constrain(r.left, r.right);
2052    return this;
2053};
2054
2055
2056})();
Note: See TracBrowser for help on using the repository browser.