source: trunk/web/addons/job_monarch/lib/extjs-30/adapter/jquery/ext-jquery-adapter-debug.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

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