source: trunk/web/addons/job_monarch/lib/extjs-30/adapter/yui/ext-yui-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: 73.4 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 YAHOO == "undefined"){
1754    throw "Unable to load Ext, core YUI utilities (yahoo, dom, event) not found.";
1755}
1756
1757(function(){
1758    var E = YAHOO.util.Event,
1759        D = YAHOO.util.Dom,
1760        CN = YAHOO.util.Connect,
1761        ES = YAHOO.util.Easing,
1762        A = YAHOO.util.Anim,
1763        libFlyweight,
1764        version = YAHOO.env.getVersion('yahoo').version.split('.'),
1765        mouseEnterSupported = parseInt(version[0]) >= 3,
1766        mouseCache = {},
1767        isXUL = Ext.isGecko ? function(node){
1768            return Object.prototype.toString.call(node) == '[object XULElement]';
1769        } : function(){
1770        }, isTextNode = Ext.isGecko ? function(node){
1771            try{
1772                return node.nodeType == 3;
1773            }catch (e){
1774                return false;
1775            }
1776        } : function(node){
1777            return node.nodeType == 3;
1778        }, elContains = function(parent, child){
1779            if(parent && parent.firstChild){
1780                while(child){
1781                    if(child === parent){
1782                        return true;
1783                    }
1784                    try{
1785                        child = child.parentNode;
1786                    }catch (e){
1787                        return false;
1788                    }
1789                    if(child && (child.nodeType != 1)){
1790                        child = null;
1791                    }
1792                }
1793            }
1794            return false;
1795        }, checkRelatedTarget = function(e){
1796            var related = Ext.lib.Event.getRelatedTarget(e);
1797            return !(isXUL(related) || elContains(e.currentTarget, related));
1798        };
1799
1800Ext.lib.Dom = {
1801    getViewWidth : function(full){
1802        return full ? D.getDocumentWidth() : D.getViewportWidth();
1803    },
1804
1805    getViewHeight : function(full){
1806        return full ? D.getDocumentHeight() : D.getViewportHeight();
1807    },
1808
1809    isAncestor : function(haystack, needle){
1810        return D.isAncestor(haystack, needle);
1811    },
1812
1813    getRegion : function(el){
1814        return D.getRegion(el);
1815    },
1816
1817    getY : function(el){
1818        return this.getXY(el)[1];
1819    },
1820
1821    getX : function(el){
1822        return this.getXY(el)[0];
1823    },
1824
1825    // original version based on YahooUI getXY
1826    // this version fixes several issues in Safari and FF
1827    // and boosts performance by removing the batch overhead, repetitive dom lookups and array index calls
1828    getXY : function(el){
1829        var p, pe, b, scroll, bd = (document.body || document.documentElement);
1830        el = Ext.getDom(el);
1831
1832        if(el == bd){
1833            return [0, 0];
1834        }
1835
1836        if (el.getBoundingClientRect) {
1837            b = el.getBoundingClientRect();
1838            scroll = fly(document).getScroll();
1839            return [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
1840        }
1841        var x = 0, y = 0;
1842
1843        p = el;
1844
1845        var hasAbsolute = fly(el).getStyle("position") == "absolute";
1846
1847        while (p) {
1848
1849            x += p.offsetLeft;
1850            y += p.offsetTop;
1851
1852            if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1853                hasAbsolute = true;
1854            }
1855
1856            if (Ext.isGecko) {
1857                pe = fly(p);
1858
1859                var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1860                var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1861
1862
1863                x += bl;
1864                y += bt;
1865
1866
1867                if (p != el && pe.getStyle('overflow') != 'visible') {
1868                    x += bl;
1869                    y += bt;
1870                }
1871            }
1872            p = p.offsetParent;
1873        }
1874
1875        if (Ext.isSafari && hasAbsolute) {
1876            x -= bd.offsetLeft;
1877            y -= bd.offsetTop;
1878        }
1879
1880        if (Ext.isGecko && !hasAbsolute) {
1881            var dbd = fly(bd);
1882            x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1883            y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1884        }
1885
1886        p = el.parentNode;
1887        while (p && p != bd) {
1888            if (!Ext.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1889                x -= p.scrollLeft;
1890                y -= p.scrollTop;
1891            }
1892            p = p.parentNode;
1893        }
1894        return [x, y];
1895    },
1896
1897    setXY : function(el, xy){
1898        el = Ext.fly(el, '_setXY');
1899        el.position();
1900        var pts = el.translatePoints(xy);
1901        if(xy[0] !== false){
1902            el.dom.style.left = pts.left + "px";
1903        }
1904        if(xy[1] !== false){
1905            el.dom.style.top = pts.top + "px";
1906        }
1907    },
1908
1909    setX : function(el, x){
1910        this.setXY(el, [x, false]);
1911    },
1912
1913    setY : function(el, y){
1914        this.setXY(el, [false, y]);
1915    }
1916};
1917
1918Ext.lib.Event = {
1919    getPageX : function(e){
1920        return E.getPageX(e.browserEvent || e);
1921    },
1922
1923    getPageY : function(e){
1924        return E.getPageY(e.browserEvent || e);
1925    },
1926
1927    getXY : function(e){
1928        return E.getXY(e.browserEvent || e);
1929    },
1930
1931    getTarget : function(e){
1932        return E.getTarget(e.browserEvent || e);
1933    },
1934
1935    getRelatedTarget : function(e){
1936        return E.getRelatedTarget(e.browserEvent || e);
1937    },
1938
1939    on : function(el, eventName, fn, scope, override){
1940        if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
1941            var item = mouseCache[el.id] || (mouseCache[el.id] = {});
1942            item[eventName] = fn;
1943            fn = fn.createInterceptor(checkRelatedTarget);
1944            eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
1945        }
1946        E.on(el, eventName, fn, scope, override);
1947    },
1948
1949    un : function(el, eventName, fn){
1950        if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
1951            var item = mouseCache[el.id], 
1952                ev = item && item[eventName];
1953
1954            if(ev){
1955                fn = ev.fn;
1956                delete item[eventName];
1957                eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
1958            }
1959        }
1960        E.removeListener(el, eventName, fn);;
1961    },
1962
1963    purgeElement : function(el){
1964        E.purgeElement(el);
1965    },
1966
1967    preventDefault : function(e){
1968        E.preventDefault(e.browserEvent || e);
1969    },
1970
1971    stopPropagation : function(e){
1972        E.stopPropagation(e.browserEvent || e);
1973    },
1974
1975    stopEvent : function(e){
1976        E.stopEvent(e.browserEvent || e);
1977    },
1978
1979    onAvailable : function(el, fn, scope, override){
1980        return E.onAvailable(el, fn, scope, override);
1981    }
1982};
1983
1984Ext.lib.Ajax = {
1985    request : function(method, uri, cb, data, options){
1986        if(options){
1987            var hs = options.headers;
1988            if(hs){
1989                for(var h in hs){
1990                    if(hs.hasOwnProperty(h)){
1991                        CN.initHeader(h, hs[h], false);
1992                    }
1993                }
1994            }
1995            if(options.xmlData){
1996                if (!hs || !hs['Content-Type']){
1997                    CN.initHeader('Content-Type', 'text/xml', false);
1998                }
1999                method = (method ? method : (options.method ? options.method : 'POST'));
2000                data = options.xmlData;
2001            }else if(options.jsonData){
2002                if (!hs || !hs['Content-Type']){
2003                    CN.initHeader('Content-Type', 'application/json', false);
2004                }
2005                method = (method ? method : (options.method ? options.method : 'POST'));
2006                data = typeof options.jsonData == 'object' ? Ext.encode(options.jsonData) : options.jsonData;
2007            }
2008        }
2009        return CN.asyncRequest(method, uri, cb, data);
2010    },
2011
2012    formRequest : function(form, uri, cb, data, isUpload, sslUri){
2013        CN.setForm(form, isUpload, sslUri);
2014        return CN.asyncRequest(Ext.getDom(form).method ||'POST', uri, cb, data);
2015    },
2016
2017    isCallInProgress : function(trans){
2018        return CN.isCallInProgress(trans);
2019    },
2020
2021    abort : function(trans){
2022        return CN.abort(trans);
2023    },
2024
2025    serializeForm : function(form){
2026        var d = CN.setForm(form.dom || form);
2027        CN.resetFormState();
2028        return d;
2029    }
2030};
2031
2032Ext.lib.Region = YAHOO.util.Region;
2033Ext.lib.Point = YAHOO.util.Point;
2034
2035
2036Ext.lib.Anim = {
2037    scroll : function(el, args, duration, easing, cb, scope){
2038        this.run(el, args, duration, easing, cb, scope, YAHOO.util.Scroll);
2039    },
2040
2041    motion : function(el, args, duration, easing, cb, scope){
2042        this.run(el, args, duration, easing, cb, scope, YAHOO.util.Motion);
2043    },
2044
2045    color : function(el, args, duration, easing, cb, scope){
2046        this.run(el, args, duration, easing, cb, scope, YAHOO.util.ColorAnim);
2047    },
2048
2049    run : function(el, args, duration, easing, cb, scope, type){
2050        type = type || YAHOO.util.Anim;
2051        if(typeof easing == "string"){
2052            easing = YAHOO.util.Easing[easing];
2053        }
2054        var anim = new type(el, args, duration, easing);
2055        anim.animateX(function(){
2056            Ext.callback(cb, scope);
2057        });
2058        return anim;
2059    }
2060};
2061
2062// all lib flyweight calls use their own flyweight to prevent collisions with developer flyweights
2063function fly(el){
2064    if(!libFlyweight){
2065        libFlyweight = new Ext.Element.Flyweight();
2066    }
2067    libFlyweight.dom = el;
2068    return libFlyweight;
2069}
2070
2071// prevent IE leaks
2072if(Ext.isIE) {
2073    function fnCleanUp() {
2074        var p = Function.prototype;
2075        delete p.createSequence;
2076        delete p.defer;
2077        delete p.createDelegate;
2078        delete p.createCallback;
2079        delete p.createInterceptor;
2080
2081        window.detachEvent("onunload", fnCleanUp);
2082    }
2083    window.attachEvent("onunload", fnCleanUp);
2084}
2085// various overrides
2086
2087// add ability for callbacks with animations
2088if(YAHOO.util.Anim){
2089    YAHOO.util.Anim.prototype.animateX = function(callback, scope){
2090        var f = function(){
2091            this.onComplete.unsubscribe(f);
2092            if(typeof callback == "function"){
2093                callback.call(scope || this, this);
2094            }
2095        };
2096        this.onComplete.subscribe(f, this, true);
2097        this.animate();
2098    };
2099}
2100
2101if(YAHOO.util.DragDrop && Ext.dd.DragDrop){
2102    YAHOO.util.DragDrop.defaultPadding = Ext.dd.DragDrop.defaultPadding;
2103    YAHOO.util.DragDrop.constrainTo = Ext.dd.DragDrop.constrainTo;
2104}
2105
2106YAHOO.util.Dom.getXY = function(el) {
2107    var f = function(el) {
2108        return Ext.lib.Dom.getXY(el);
2109    };
2110    return YAHOO.util.Dom.batch(el, f, YAHOO.util.Dom, true);
2111};
2112
2113
2114// workaround for Safari anim duration speed problems
2115if(YAHOO.util.AnimMgr){
2116    YAHOO.util.AnimMgr.fps = 1000;
2117}
2118
2119YAHOO.util.Region.prototype.adjust = function(t, l, b, r){
2120    this.top += t;
2121    this.left += l;
2122    this.right += r;
2123    this.bottom += b;
2124    return this;
2125};
2126   
2127YAHOO.util.Region.prototype.constrainTo = function(r) {
2128    this.top = this.top.constrain(r.top, r.bottom);
2129    this.bottom = this.bottom.constrain(r.top, r.bottom);
2130    this.left = this.left.constrain(r.left, r.right);
2131    this.right = this.right.constrain(r.left, r.right);
2132    return this;
2133};
2134
2135
2136})();
Note: See TracBrowser for help on using the repository browser.