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