Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / adapter / ext / ext-base-debug-w-comments.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();(function(){\r
1849         var libFlyweight;\r
1850         \r
1851         function fly(el) {\r
1852         if (!libFlyweight) {\r
1853             libFlyweight = new Ext.Element.Flyweight();\r
1854         }\r
1855         libFlyweight.dom = el;\r
1856         return libFlyweight;\r
1857     }\r
1858     \r
1859     (function(){\r
1860         var doc = document,\r
1861                 isCSS1 = doc.compatMode == "CSS1Compat",\r
1862                 MAX = Math.max,         \r
1863         ROUND = Math.round,\r
1864                 PARSEINT = parseInt;\r
1865                 \r
1866         Ext.lib.Dom = {\r
1867             isAncestor : function(p, c) {\r
1868                     var ret = false;\r
1869                         \r
1870                         p = Ext.getDom(p);\r
1871                         c = Ext.getDom(c);\r
1872                         if (p && c) {\r
1873                                 if (p.contains) {\r
1874                                         return p.contains(c);\r
1875                                 } else if (p.compareDocumentPosition) {\r
1876                                         return !!(p.compareDocumentPosition(c) & 16);\r
1877                                 } else {\r
1878                                         while (c = c.parentNode) {\r
1879                                                 ret = c == p || ret;                                    \r
1880                                         }\r
1881                                 }                   \r
1882                         }       \r
1883                         return ret;\r
1884                 },\r
1885                 \r
1886         getViewWidth : function(full) {\r
1887             return full ? this.getDocumentWidth() : this.getViewportWidth();\r
1888         },\r
1889 \r
1890         getViewHeight : function(full) {\r
1891             return full ? this.getDocumentHeight() : this.getViewportHeight();\r
1892         },\r
1893 \r
1894         getDocumentHeight: function() {            \r
1895             return MAX(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, this.getViewportHeight());\r
1896         },\r
1897 \r
1898         getDocumentWidth: function() {            \r
1899             return MAX(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, this.getViewportWidth());\r
1900         },\r
1901 \r
1902         getViewportHeight: function(){\r
1903                 return Ext.isIE ? \r
1904                            (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :\r
1905                            self.innerHeight;\r
1906         },\r
1907 \r
1908         getViewportWidth : function() {\r
1909                 return !Ext.isStrict && !Ext.isOpera ? doc.body.clientWidth :\r
1910                            Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;\r
1911         },\r
1912         \r
1913         getY : function(el) {\r
1914             return this.getXY(el)[1];\r
1915         },\r
1916 \r
1917         getX : function(el) {\r
1918             return this.getXY(el)[0];\r
1919         },\r
1920 \r
1921         getXY : function(el) {\r
1922             var p, \r
1923                 pe, \r
1924                 b,\r
1925                 bt, \r
1926                 bl,     \r
1927                 dbd,            \r
1928                 x = 0,\r
1929                 y = 0, \r
1930                 scroll,\r
1931                 hasAbsolute, \r
1932                 bd = (doc.body || doc.documentElement),\r
1933                 ret = [0,0];\r
1934                 \r
1935             el = Ext.getDom(el);\r
1936 \r
1937             if(el != bd){\r
1938                     if (el.getBoundingClientRect) {\r
1939                         b = el.getBoundingClientRect();\r
1940                         scroll = fly(document).getScroll();\r
1941                         ret = [ROUND(b.left + scroll.left), ROUND(b.top + scroll.top)];\r
1942                     } else {  \r
1943                             p = el;             \r
1944                             hasAbsolute = fly(el).isStyle("position", "absolute");\r
1945                 \r
1946                             while (p) {\r
1947                                     pe = fly(p);                \r
1948                                 x += p.offsetLeft;\r
1949                                 y += p.offsetTop;\r
1950                 \r
1951                                 hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");\r
1952                                                 \r
1953                                 if (Ext.isGecko) {                                  \r
1954                                     y += bt = PARSEINT(pe.getStyle("borderTopWidth"), 10) || 0;\r
1955                                     x += bl = PARSEINT(pe.getStyle("borderLeftWidth"), 10) || 0;        \r
1956                 \r
1957                                     if (p != el && !pe.isStyle('overflow','visible')) {\r
1958                                         x += bl;\r
1959                                         y += bt;\r
1960                                     }\r
1961                                 }\r
1962                                 p = p.offsetParent;\r
1963                             }\r
1964                 \r
1965                             if (Ext.isSafari && hasAbsolute) {\r
1966                                 x -= bd.offsetLeft;\r
1967                                 y -= bd.offsetTop;\r
1968                             }\r
1969                 \r
1970                             if (Ext.isGecko && !hasAbsolute) {\r
1971                                 dbd = fly(bd);\r
1972                                 x += PARSEINT(dbd.getStyle("borderLeftWidth"), 10) || 0;\r
1973                                 y += PARSEINT(dbd.getStyle("borderTopWidth"), 10) || 0;\r
1974                             }\r
1975                 \r
1976                             p = el.parentNode;\r
1977                             while (p && p != bd) {\r
1978                                 if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {\r
1979                                     x -= p.scrollLeft;\r
1980                                     y -= p.scrollTop;\r
1981                                 }\r
1982                                 p = p.parentNode;\r
1983                             }\r
1984                             ret = [x,y];\r
1985                     }\r
1986                 }\r
1987             return ret\r
1988         },\r
1989 \r
1990         setXY : function(el, xy) {\r
1991             (el = Ext.fly(el, '_setXY')).position();\r
1992             \r
1993             var pts = el.translatePoints(xy),\r
1994                 style = el.dom.style,\r
1995                 pos;                    \r
1996             \r
1997             for (pos in pts) {              \r
1998                     if(!isNaN(pts[pos])) style[pos] = pts[pos] + "px"\r
1999             }\r
2000         },\r
2001 \r
2002         setX : function(el, x) {\r
2003             this.setXY(el, [x, false]);\r
2004         },\r
2005 \r
2006         setY : function(el, y) {\r
2007             this.setXY(el, [false, y]);\r
2008         }\r
2009     };\r
2010 })();Ext.lib.Dom.getRegion = function(el) {\r
2011     return Ext.lib.Region.getRegion(el);\r
2012 };Ext.lib.Event = function() {
2013     var loadComplete = false,
2014         unloadListeners = {},
2015         retryCount = 0,
2016         onAvailStack = [],
2017         _interval,
2018         locked = false,
2019         win = window,
2020         doc = document,
2021
2022         // constants
2023         POLL_RETRYS = 200,
2024         POLL_INTERVAL = 20,
2025         EL = 0,
2026         TYPE = 0,
2027         FN = 1,
2028         WFN = 2,
2029         OBJ = 2,
2030         ADJ_SCOPE = 3,
2031         SCROLLLEFT = 'scrollLeft',
2032         SCROLLTOP = 'scrollTop',
2033         UNLOAD = 'unload',
2034         MOUSEOVER = 'mouseover',
2035         MOUSEOUT = 'mouseout',
2036         // private
2037         doAdd = function() {
2038             var ret;
2039             if (win.addEventListener) {
2040                 ret = function(el, eventName, fn, capture) {
2041                     if (eventName == 'mouseenter') {
2042                         fn = fn.createInterceptor(checkRelatedTarget);
2043                         el.addEventListener(MOUSEOVER, fn, (capture));
2044                     } else if (eventName == 'mouseleave') {
2045                         fn = fn.createInterceptor(checkRelatedTarget);
2046                         el.addEventListener(MOUSEOUT, fn, (capture));
2047                     } else {
2048                         el.addEventListener(eventName, fn, (capture));
2049                     }
2050                     return fn;
2051                 };
2052             } else if (win.attachEvent) {
2053                 ret = function(el, eventName, fn, capture) {
2054                     el.attachEvent("on" + eventName, fn);
2055                     return fn;
2056                 };
2057             } else {
2058                 ret = function(){};
2059             }
2060             return ret;
2061         }(),
2062         // private
2063         doRemove = function(){
2064             var ret;
2065             if (win.removeEventListener) {
2066                 ret = function (el, eventName, fn, capture) {
2067                     if (eventName == 'mouseenter') {
2068                         eventName = MOUSEOVER;
2069                     } else if (eventName == 'mouseleave') {
2070                         eventName = MOUSEOUT;
2071                     }
2072                     el.removeEventListener(eventName, fn, (capture));
2073                 };
2074             } else if (win.detachEvent) {
2075                 ret = function (el, eventName, fn) {
2076                     el.detachEvent("on" + eventName, fn);
2077                 };
2078             } else {
2079                 ret = function(){};
2080             }
2081             return ret;
2082         }();
2083
2084     function checkRelatedTarget(e) {
2085         return !elContains(e.currentTarget, pub.getRelatedTarget(e));
2086     }
2087
2088     function elContains(parent, child) {
2089        if(parent && parent.firstChild){
2090          while(child) {
2091             if(child === parent) {
2092                 return true;
2093             }
2094             child = child.parentNode;
2095             if(child && (child.nodeType != 1)) {
2096                 child = null;
2097             }
2098           }
2099         }
2100         return false;
2101     }
2102
2103     // private
2104     function _tryPreloadAttach() {
2105         var ret = false,
2106             notAvail = [],
2107             element, i, len, v,
2108             tryAgain = !loadComplete || (retryCount > 0);
2109
2110         if (!locked) {
2111             locked = true;
2112
2113             for (i = 0, len = onAvailStack.length; i < len; i++) {
2114                 v = onAvailStack[i];
2115                 if(v && (element = doc.getElementById(v.id))){
2116                     if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
2117                         element = v.override ? (v.override === true ? v.obj : v.override) : element;
2118                         v.fn.call(element, v.obj);
2119                         v = null;
2120                     } else {
2121                         notAvail.push(v);
2122                     }
2123                 }
2124             }
2125
2126             retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2127
2128             if (tryAgain) {
2129                 startInterval();
2130             } else {
2131                 clearInterval(_interval);
2132                 _interval = null;
2133             }
2134
2135             ret = !(locked = false);
2136         }
2137         return ret;
2138     }
2139
2140     // private
2141     function startInterval() {
2142         if(!_interval){
2143             var callback = function() {
2144                 _tryPreloadAttach();
2145             };
2146             _interval = setInterval(callback, POLL_INTERVAL);
2147         }
2148     }
2149
2150     // private
2151     function getScroll() {
2152         var dd = doc.documentElement,
2153             db = doc.body;
2154         if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
2155             return [dd[SCROLLLEFT], dd[SCROLLTOP]];
2156         }else if(db){
2157             return [db[SCROLLLEFT], db[SCROLLTOP]];
2158         }else{
2159             return [0, 0];
2160         }
2161     }
2162
2163     // private
2164     function getPageCoord (ev, xy) {
2165         ev = ev.browserEvent || ev;
2166         var coord  = ev['page' + xy];
2167         if (!coord && coord !== 0) {
2168             coord = ev['client' + xy] || 0;
2169
2170             if (Ext.isIE) {
2171                 coord += getScroll()[xy == "X" ? 0 : 1];
2172             }
2173         }
2174
2175         return coord;
2176     }
2177
2178     var pub =  {
2179         extAdapter: true,
2180         onAvailable : function(p_id, p_fn, p_obj, p_override) {
2181             onAvailStack.push({
2182                 id:         p_id,
2183                 fn:         p_fn,
2184                 obj:        p_obj,
2185                 override:   p_override,
2186                 checkReady: false });
2187
2188             retryCount = POLL_RETRYS;
2189             startInterval();
2190         },
2191
2192         // This function should ALWAYS be called from Ext.EventManager
2193         addListener: function(el, eventName, fn) {
2194             el = Ext.getDom(el);
2195             if (el && fn) {
2196                 if (eventName == UNLOAD) {
2197                     if (unloadListeners[el.id] === undefined) {
2198                         unloadListeners[el.id] = [];
2199                     }
2200                     unloadListeners[el.id].push([eventName, fn]);
2201                     return fn;
2202                 }
2203                 return doAdd(el, eventName, fn, false);
2204             }
2205             return false;
2206         },
2207
2208         // This function should ALWAYS be called from Ext.EventManager
2209         removeListener: function(el, eventName, fn) {
2210             el = Ext.getDom(el);
2211             var i, len, li;
2212             if (el && fn) {
2213                 if (eventName == UNLOAD) {
2214                     if (unloadListeners[id] !== undefined) {
2215                         for (i = 0, len = unloadListeners[id].length; i < len; i++) {
2216                             li = unloadListeners[id][i];
2217                             if (li && li[TYPE] == eventName && li[FN] == fn) {
2218                                 unloadListeners[id].splice(i, 1);
2219                             }
2220                         }
2221                     }
2222                     return;
2223                 }
2224                 doRemove(el, eventName, fn, false);
2225             }
2226         },
2227
2228         getTarget : function(ev) {
2229             ev = ev.browserEvent || ev;
2230             return this.resolveTextNode(ev.target || ev.srcElement);
2231         },
2232
2233         resolveTextNode : Ext.isGecko ? function(node){
2234             if(!node){
2235                 return;
2236             }
2237             // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
2238             var s = HTMLElement.prototype.toString.call(node);
2239             if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
2240                 return;
2241             }
2242             return node.nodeType == 3 ? node.parentNode : node;
2243         } : function(node){
2244             return node && node.nodeType == 3 ? node.parentNode : node;
2245         },
2246
2247         getRelatedTarget : function(ev) {
2248             ev = ev.browserEvent || ev;
2249             return this.resolveTextNode(ev.relatedTarget ||
2250                     (ev.type == MOUSEOUT ? ev.toElement :
2251                      ev.type == MOUSEOVER ? ev.fromElement : null));
2252         },
2253
2254         getPageX : function(ev) {
2255             return getPageCoord(ev, "X");
2256         },
2257
2258         getPageY : function(ev) {
2259             return getPageCoord(ev, "Y");
2260         },
2261
2262
2263         getXY : function(ev) {
2264             return [this.getPageX(ev), this.getPageY(ev)];
2265         },
2266
2267         stopEvent : function(ev) {
2268             this.stopPropagation(ev);
2269             this.preventDefault(ev);
2270         },
2271
2272         stopPropagation : function(ev) {
2273             ev = ev.browserEvent || ev;
2274             if (ev.stopPropagation) {
2275                 ev.stopPropagation();
2276             } else {
2277                 ev.cancelBubble = true;
2278             }
2279         },
2280
2281         preventDefault : function(ev) {
2282             ev = ev.browserEvent || ev;
2283             if (ev.preventDefault) {
2284                 ev.preventDefault();
2285             } else {
2286                 ev.returnValue = false;
2287             }
2288         },
2289
2290         getEvent : function(e) {
2291             e = e || win.event;
2292             if (!e) {
2293                 var c = this.getEvent.caller;
2294                 while (c) {
2295                     e = c.arguments[0];
2296                     if (e && Event == e.constructor) {
2297                         break;
2298                     }
2299                     c = c.caller;
2300                 }
2301             }
2302             return e;
2303         },
2304
2305         getCharCode : function(ev) {
2306             ev = ev.browserEvent || ev;
2307             return ev.charCode || ev.keyCode || 0;
2308         },
2309
2310         //clearCache: function() {},
2311         // deprecated, call from EventManager
2312         getListeners : function(el, eventName) {
2313             Ext.EventManager.getListeners(el, eventName);
2314         },
2315
2316         // deprecated, call from EventManager
2317         purgeElement : function(el, recurse, eventName) {
2318             Ext.EventManager.purgeElement(el, recurse, eventName);
2319         },
2320
2321         _load : function(e) {
2322             loadComplete = true;
2323             var EU = Ext.lib.Event;
2324             if (Ext.isIE && e !== true) {
2325         // IE8 complains that _load is null or not an object
2326         // so lets remove self via arguments.callee
2327                 doRemove(win, "load", arguments.callee);
2328             }
2329         },
2330
2331         _unload : function(e) {
2332              var EU = Ext.lib.Event,
2333                 i, j, l, v, ul, id, len, index, scope;
2334
2335
2336             for (id in unloadListeners) {
2337                 ul = unloadListeners[id];
2338                 for (i = 0, len = ul.length; i < len; i++) {
2339                     v = ul[i];
2340                     if (v) {
2341                         try{
2342                             scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) :  win;
2343                             v[FN].call(scope, EU.getEvent(e), v[OBJ]);
2344                         }catch(ex){}
2345                     }
2346                 }
2347             };
2348
2349             unloadListeners = null;
2350             Ext.EventManager._unload();
2351
2352             doRemove(win, UNLOAD, EU._unload);
2353         }
2354     };
2355
2356     // Initialize stuff.
2357     pub.on = pub.addListener;
2358     pub.un = pub.removeListener;
2359     if (doc && doc.body) {
2360         pub._load(true);
2361     } else {
2362         doAdd(win, "load", pub._load);
2363     }
2364     doAdd(win, UNLOAD, pub._unload);
2365     _tryPreloadAttach();
2366
2367     return pub;
2368 }();
2369 /*\r
2370 * Portions of this file are based on pieces of Yahoo User Interface Library\r
2371 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.\r
2372 * YUI licensed under the BSD License:\r
2373 * http://developer.yahoo.net/yui/license.txt\r
2374 */\r
2375 Ext.lib.Ajax = function() {     \r
2376     var activeX = ['MSXML2.XMLHTTP.3.0',\r
2377                    'MSXML2.XMLHTTP',\r
2378                    'Microsoft.XMLHTTP'],\r
2379         CONTENTTYPE = 'Content-Type';\r
2380                    \r
2381     // private\r
2382     function setHeader(o) {\r
2383         var conn = o.conn,\r
2384             prop;\r
2385         \r
2386         function setTheHeaders(conn, headers){\r
2387             for (prop in headers) {\r
2388                 if (headers.hasOwnProperty(prop)) {\r
2389                     conn.setRequestHeader(prop, headers[prop]);\r
2390                 }\r
2391             }   \r
2392         }       \r
2393         \r
2394         if (pub.defaultHeaders) {\r
2395             setTheHeaders(conn, pub.defaultHeaders);\r
2396         }\r
2397 \r
2398         if (pub.headers) {\r
2399             setTheHeaders(conn, pub.headers);\r
2400             delete pub.headers;                \r
2401         }\r
2402     }    \r
2403     \r
2404     // private\r
2405     function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {          \r
2406         return {\r
2407             tId : tId,\r
2408             status : isAbort ? -1 : 0,\r
2409             statusText : isAbort ? 'transaction aborted' : 'communication failure',\r
2410             isAbort: isAbort,\r
2411             isTimeout: isTimeout,\r
2412             argument : callbackArg\r
2413         };\r
2414     }  \r
2415     \r
2416     // private \r
2417     function initHeader(label, value) {         \r
2418         (pub.headers = pub.headers || {})[label] = value;                       \r
2419     }\r
2420     \r
2421     // private\r
2422     function createResponseObject(o, callbackArg) {\r
2423         var headerObj = {},\r
2424             headerStr,              \r
2425             conn = o.conn,\r
2426             t,\r
2427             s;\r
2428 \r
2429         try {\r
2430             headerStr = o.conn.getAllResponseHeaders();   \r
2431             Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'), function(v){\r
2432                 t = v.indexOf(':');\r
2433                 if(t >= 0){\r
2434                     s = v.substr(0, t).toLowerCase();\r
2435                     if(v.charAt(t + 1) == ' '){\r
2436                         ++t;\r
2437                     }\r
2438                     headerObj[s] = v.substr(t + 1);\r
2439                 }\r
2440             });\r
2441         } catch(e) {}\r
2442                     \r
2443         return {\r
2444             tId : o.tId,\r
2445             status : conn.status,\r
2446             statusText : conn.statusText,\r
2447             getResponseHeader : function(header){return headerObj[header.toLowerCase()];},\r
2448             getAllResponseHeaders : function(){return headerStr},\r
2449             responseText : conn.responseText,\r
2450             responseXML : conn.responseXML,\r
2451             argument : callbackArg\r
2452         };\r
2453     }\r
2454     \r
2455     // private\r
2456     function releaseObject(o) {\r
2457         o.conn = null;\r
2458         o = null;\r
2459     }        \r
2460     \r
2461     // private\r
2462     function handleTransactionResponse(o, callback, isAbort, isTimeout) {\r
2463         if (!callback) {\r
2464             releaseObject(o);\r
2465             return;\r
2466         }\r
2467 \r
2468         var httpStatus, responseObject;\r
2469 \r
2470         try {\r
2471             if (o.conn.status !== undefined && o.conn.status != 0) {\r
2472                 httpStatus = o.conn.status;\r
2473             }\r
2474             else {\r
2475                 httpStatus = 13030;\r
2476             }\r
2477         }\r
2478         catch(e) {\r
2479             httpStatus = 13030;\r
2480         }\r
2481 \r
2482         if ((httpStatus >= 200 && httpStatus < 300) || (Ext.isIE && httpStatus == 1223)) {\r
2483             responseObject = createResponseObject(o, callback.argument);\r
2484             if (callback.success) {\r
2485                 if (!callback.scope) {\r
2486                     callback.success(responseObject);\r
2487                 }\r
2488                 else {\r
2489                     callback.success.apply(callback.scope, [responseObject]);\r
2490                 }\r
2491             }\r
2492         }\r
2493         else {\r
2494             switch (httpStatus) {\r
2495                 case 12002:\r
2496                 case 12029:\r
2497                 case 12030:\r
2498                 case 12031:\r
2499                 case 12152:\r
2500                 case 13030:\r
2501                     responseObject = createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false), isTimeout);\r
2502                     if (callback.failure) {\r
2503                         if (!callback.scope) {\r
2504                             callback.failure(responseObject);\r
2505                         }\r
2506                         else {\r
2507                             callback.failure.apply(callback.scope, [responseObject]);\r
2508                         }\r
2509                     }\r
2510                     break;\r
2511                 default:\r
2512                     responseObject = createResponseObject(o, callback.argument);\r
2513                     if (callback.failure) {\r
2514                         if (!callback.scope) {\r
2515                             callback.failure(responseObject);\r
2516                         }\r
2517                         else {\r
2518                             callback.failure.apply(callback.scope, [responseObject]);\r
2519                         }\r
2520                     }\r
2521             }\r
2522         }\r
2523 \r
2524         releaseObject(o);\r
2525         responseObject = null;\r
2526     }  \r
2527     \r
2528     // private\r
2529     function handleReadyState(o, callback){\r
2530     callback = callback || {};\r
2531         var conn = o.conn,\r
2532             tId = o.tId,\r
2533             poll = pub.poll,\r
2534             cbTimeout = callback.timeout || null;\r
2535 \r
2536         if (cbTimeout) {\r
2537             pub.timeout[tId] = setTimeout(function() {\r
2538                 pub.abort(o, callback, true);\r
2539             }, cbTimeout);\r
2540         }\r
2541 \r
2542         poll[tId] = setInterval(\r
2543             function() {\r
2544                 if (conn && conn.readyState == 4) {\r
2545                     clearInterval(poll[tId]);\r
2546                     poll[tId] = null;\r
2547 \r
2548                     if (cbTimeout) {\r
2549                         clearTimeout(pub.timeout[tId]);\r
2550                         pub.timeout[tId] = null;\r
2551                     }\r
2552 \r
2553                     handleTransactionResponse(o, callback);\r
2554                 }\r
2555             },\r
2556             pub.pollInterval);\r
2557     }\r
2558     \r
2559     // private\r
2560     function asyncRequest(method, uri, callback, postData) {\r
2561         var o = getConnectionObject() || null;\r
2562 \r
2563         if (o) {\r
2564             o.conn.open(method, uri, true);\r
2565 \r
2566             if (pub.useDefaultXhrHeader) {                    \r
2567                 initHeader('X-Requested-With', pub.defaultXhrHeader);\r
2568             }\r
2569 \r
2570             if(postData && pub.useDefaultHeader && (!pub.headers || !pub.headers[CONTENTTYPE])){\r
2571                 initHeader(CONTENTTYPE, pub.defaultPostHeader);\r
2572             }\r
2573 \r
2574             if (pub.defaultHeaders || pub.headers) {\r
2575                 setHeader(o);\r
2576             }\r
2577 \r
2578             handleReadyState(o, callback);\r
2579             o.conn.send(postData || null);\r
2580         }\r
2581         return o;\r
2582     }\r
2583     \r
2584     // private\r
2585     function getConnectionObject() {\r
2586         var o;          \r
2587 \r
2588         try {\r
2589             if (o = createXhrObject(pub.transactionId)) {\r
2590                 pub.transactionId++;\r
2591             }\r
2592         } catch(e) {\r
2593         } finally {\r
2594             return o;\r
2595         }\r
2596     }\r
2597        \r
2598     // private\r
2599     function createXhrObject(transactionId) {\r
2600         var http;\r
2601             \r
2602         try {\r
2603             http = new XMLHttpRequest();                \r
2604         } catch(e) {\r
2605             for (var i = 0; i < activeX.length; ++i) {              \r
2606                 try {\r
2607                     http = new ActiveXObject(activeX[i]);                        \r
2608                     break;\r
2609                 } catch(e) {}\r
2610             }\r
2611         } finally {\r
2612             return {conn : http, tId : transactionId};\r
2613         }\r
2614     }\r
2615          \r
2616     var pub = {\r
2617         request : function(method, uri, cb, data, options) {\r
2618             if(options){\r
2619                 var me = this,              \r
2620                     xmlData = options.xmlData,\r
2621                     jsonData = options.jsonData,\r
2622                     hs;\r
2623                     \r
2624                 Ext.applyIf(me, options);           \r
2625                 \r
2626                 if(xmlData || jsonData){\r
2627                     hs = me.headers;\r
2628                     if(!hs || !hs[CONTENTTYPE]){\r
2629                         initHeader(CONTENTTYPE, xmlData ? 'text/xml' : 'application/json');\r
2630                     }\r
2631                     data = xmlData || (!Ext.isPrimitive(jsonData) ? Ext.encode(jsonData) : jsonData);\r
2632                 }\r
2633             }                       \r
2634             return asyncRequest(method || options.method || "POST", uri, cb, data);\r
2635         },\r
2636 \r
2637         serializeForm : function(form) {\r
2638             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,\r
2639                 hasSubmit = false,\r
2640                 encoder = encodeURIComponent,\r
2641                 element,\r
2642                 options, \r
2643                 name, \r
2644                 val,                \r
2645                 data = '',\r
2646                 type;\r
2647                 \r
2648             Ext.each(fElements, function(element) {                 \r
2649                 name = element.name;                 \r
2650                 type = element.type;\r
2651                 \r
2652                 if (!element.disabled && name){\r
2653                     if(/select-(one|multiple)/i.test(type)) {\r
2654                         Ext.each(element.options, function(opt) {\r
2655                             if (opt.selected) {\r
2656                                 data += String.format("{0}={1}&", encoder(name), encoder((opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttribute('value') !== null) ? opt.value : opt.text));\r
2657                             }                               \r
2658                         });\r
2659                     } else if(!/file|undefined|reset|button/i.test(type)) {\r
2660                             if(!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)){\r
2661                                 \r
2662                                 data += encoder(name) + '=' + encoder(element.value) + '&';                     \r
2663                                 hasSubmit = /submit/i.test(type);    \r
2664                             }                       \r
2665                     } \r
2666                 }\r
2667             });            \r
2668             return data.substr(0, data.length - 1);\r
2669         },\r
2670         \r
2671         useDefaultHeader : true,\r
2672         defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',\r
2673         useDefaultXhrHeader : true,\r
2674         defaultXhrHeader : 'XMLHttpRequest',        \r
2675         poll : {},\r
2676         timeout : {},\r
2677         pollInterval : 50,\r
2678         transactionId : 0,\r
2679         \r
2680 //  This is never called - Is it worth exposing this?               \r
2681 //          setProgId : function(id) {\r
2682 //              activeX.unshift(id);\r
2683 //          },\r
2684 \r
2685 //  This is never called - Is it worth exposing this?   \r
2686 //          setDefaultPostHeader : function(b) {\r
2687 //              this.useDefaultHeader = b;\r
2688 //          },\r
2689         \r
2690 //  This is never called - Is it worth exposing this?   \r
2691 //          setDefaultXhrHeader : function(b) {\r
2692 //              this.useDefaultXhrHeader = b;\r
2693 //          },\r
2694 \r
2695 //  This is never called - Is it worth exposing this?           \r
2696 //          setPollingInterval : function(i) {\r
2697 //              if (typeof i == 'number' && isFinite(i)) {\r
2698 //                  this.pollInterval = i;\r
2699 //              }\r
2700 //          },\r
2701         \r
2702 //  This is never called - Is it worth exposing this?\r
2703 //          resetDefaultHeaders : function() {\r
2704 //              this.defaultHeaders = null;\r
2705 //          },\r
2706     \r
2707             abort : function(o, callback, isTimeout) {\r
2708                 var me = this,\r
2709                     tId = o.tId,\r
2710                     isAbort = false;\r
2711                 \r
2712                 if (me.isCallInProgress(o)) {\r
2713                     o.conn.abort();\r
2714                     clearInterval(me.poll[tId]);\r
2715                     me.poll[tId] = null;\r
2716                     clearTimeout(pub.timeout[tId]);\r
2717                     me.timeout[tId] = null;\r
2718                     \r
2719                     handleTransactionResponse(o, callback, (isAbort = true), isTimeout);                \r
2720                 }\r
2721                 return isAbort;\r
2722             },\r
2723     \r
2724             isCallInProgress : function(o) {\r
2725                 // if there is a connection and readyState is not 0 or 4\r
2726                 return o.conn && !{0:true,4:true}[o.conn.readyState];           \r
2727             }\r
2728         };\r
2729         return pub;\r
2730     }();        Ext.lib.Region = function(t, r, b, l) {\r
2731                 var me = this;\r
2732         me.top = t;\r
2733         me[1] = t;\r
2734         me.right = r;\r
2735         me.bottom = b;\r
2736         me.left = l;\r
2737         me[0] = l;\r
2738     };\r
2739 \r
2740     Ext.lib.Region.prototype = {\r
2741         contains : function(region) {\r
2742                 var me = this;\r
2743             return ( region.left >= me.left &&\r
2744                      region.right <= me.right &&\r
2745                      region.top >= me.top &&\r
2746                      region.bottom <= me.bottom );\r
2747 \r
2748         },\r
2749 \r
2750         getArea : function() {\r
2751                 var me = this;\r
2752             return ( (me.bottom - me.top) * (me.right - me.left) );\r
2753         },\r
2754 \r
2755         intersect : function(region) {\r
2756             var me = this,\r
2757                 t = Math.max(me.top, region.top),\r
2758                 r = Math.min(me.right, region.right),\r
2759                 b = Math.min(me.bottom, region.bottom),\r
2760                 l = Math.max(me.left, region.left);\r
2761 \r
2762             if (b >= t && r >= l) {\r
2763                 return new Ext.lib.Region(t, r, b, l);\r
2764             }\r
2765         },\r
2766         \r
2767         union : function(region) {\r
2768                 var me = this,\r
2769                 t = Math.min(me.top, region.top),\r
2770                 r = Math.max(me.right, region.right),\r
2771                 b = Math.max(me.bottom, region.bottom),\r
2772                 l = Math.min(me.left, region.left);\r
2773 \r
2774             return new Ext.lib.Region(t, r, b, l);\r
2775         },\r
2776 \r
2777         constrainTo : function(r) {\r
2778                 var me = this;\r
2779             me.top = me.top.constrain(r.top, r.bottom);\r
2780             me.bottom = me.bottom.constrain(r.top, r.bottom);\r
2781             me.left = me.left.constrain(r.left, r.right);\r
2782             me.right = me.right.constrain(r.left, r.right);\r
2783             return me;\r
2784         },\r
2785 \r
2786         adjust : function(t, l, b, r) {\r
2787                 var me = this;\r
2788             me.top += t;\r
2789             me.left += l;\r
2790             me.right += r;\r
2791             me.bottom += b;\r
2792             return me;\r
2793         }\r
2794     };\r
2795 \r
2796     Ext.lib.Region.getRegion = function(el) {\r
2797         var p = Ext.lib.Dom.getXY(el),\r
2798                 t = p[1],\r
2799                 r = p[0] + el.offsetWidth,\r
2800                 b = p[1] + el.offsetHeight,\r
2801                 l = p[0];\r
2802 \r
2803         return new Ext.lib.Region(t, r, b, l);\r
2804     };  Ext.lib.Point = function(x, y) {\r
2805         if (Ext.isArray(x)) {\r
2806             y = x[1];\r
2807             x = x[0];\r
2808         }\r
2809         var me = this;\r
2810         me.x = me.right = me.left = me[0] = x;\r
2811         me.y = me.top = me.bottom = me[1] = y;\r
2812     };\r
2813 \r
2814     Ext.lib.Point.prototype = new Ext.lib.Region();\r
2815 (function(){    \r
2816     var EXTLIB = Ext.lib,\r
2817         noNegatives = /width|height|opacity|padding/i,\r
2818         offsetAttribute = /^((width|height)|(top|left))$/,\r
2819         defaultUnit = /width|height|top$|bottom$|left$|right$/i,\r
2820         offsetUnit =  /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,\r
2821         isset = function(v){\r
2822             return typeof v !== 'undefined';\r
2823         },\r
2824         now = function(){\r
2825             return new Date();    \r
2826         };\r
2827         \r
2828     EXTLIB.Anim = {\r
2829         motion : function(el, args, duration, easing, cb, scope) {\r
2830             return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);\r
2831         },\r
2832 \r
2833         run : function(el, args, duration, easing, cb, scope, type) {\r
2834             type = type || Ext.lib.AnimBase;\r
2835             if (typeof easing == "string") {\r
2836                 easing = Ext.lib.Easing[easing];\r
2837             }\r
2838             var anim = new type(el, args, duration, easing);\r
2839             anim.animateX(function() {\r
2840                 if(Ext.isFunction(cb)){\r
2841                     cb.call(scope);\r
2842                 }\r
2843             });\r
2844             return anim;\r
2845         }\r
2846     };\r
2847     \r
2848     EXTLIB.AnimBase = function(el, attributes, duration, method) {\r
2849         if (el) {\r
2850             this.init(el, attributes, duration, method);\r
2851         }\r
2852     };\r
2853 \r
2854     EXTLIB.AnimBase.prototype = {\r
2855         doMethod: function(attr, start, end) {\r
2856             var me = this;\r
2857             return me.method(me.curFrame, start, end - start, me.totalFrames);\r
2858         },\r
2859 \r
2860 \r
2861         setAttr: function(attr, val, unit) {\r
2862             if (noNegatives.test(attr) && val < 0) {\r
2863                 val = 0;\r
2864             }\r
2865             Ext.fly(this.el, '_anim').setStyle(attr, val + unit);\r
2866         },\r
2867 \r
2868 \r
2869         getAttr: function(attr) {\r
2870             var el = Ext.fly(this.el),\r
2871                 val = el.getStyle(attr),\r
2872                 a = offsetAttribute.exec(attr) || []\r
2873 \r
2874             if (val !== 'auto' && !offsetUnit.test(val)) {\r
2875                 return parseFloat(val);\r
2876             }\r
2877 \r
2878             return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;\r
2879         },\r
2880 \r
2881 \r
2882         getDefaultUnit: function(attr) {\r
2883             return defaultUnit.test(attr) ? 'px' : '';\r
2884         },\r
2885 \r
2886         animateX : function(callback, scope) {\r
2887             var me = this,\r
2888                 f = function() {\r
2889                 me.onComplete.removeListener(f);\r
2890                 if (Ext.isFunction(callback)) {\r
2891                     callback.call(scope || me, me);\r
2892                 }\r
2893             };\r
2894             me.onComplete.addListener(f, me);\r
2895             me.animate();\r
2896         },\r
2897 \r
2898 \r
2899         setRunAttr: function(attr) {            \r
2900             var me = this,\r
2901                 a = this.attributes[attr],\r
2902                 to = a.to,\r
2903                 by = a.by,\r
2904                 from = a.from,\r
2905                 unit = a.unit,\r
2906                 ra = (this.runAttrs[attr] = {}),\r
2907                 end;\r
2908 \r
2909             if (!isset(to) && !isset(by)){\r
2910                 return false;\r
2911             }\r
2912 \r
2913             var start = isset(from) ? from : me.getAttr(attr);\r
2914             if (isset(to)) {\r
2915                 end = to;\r
2916             }else if(isset(by)) {\r
2917                 if (Ext.isArray(start)){\r
2918                     end = [];\r
2919                                         for(var i=0,len=start.length; i<len; i++) {\r
2920                                                 end[i] = start[i] + by[i];\r
2921                                         }\r
2922                 }else{\r
2923                     end = start + by;\r
2924                 }\r
2925             }\r
2926 \r
2927             Ext.apply(ra, {\r
2928                 start: start,\r
2929                 end: end,\r
2930                 unit: isset(unit) ? unit : me.getDefaultUnit(attr)\r
2931             });\r
2932         },\r
2933 \r
2934 \r
2935         init: function(el, attributes, duration, method) {\r
2936             var me = this,\r
2937                 actualFrames = 0,\r
2938                 mgr = EXTLIB.AnimMgr;\r
2939                 \r
2940             Ext.apply(me, {\r
2941                 isAnimated: false,\r
2942                 startTime: null,\r
2943                 el: Ext.getDom(el),\r
2944                 attributes: attributes || {},\r
2945                 duration: duration || 1,\r
2946                 method: method || EXTLIB.Easing.easeNone,\r
2947                 useSec: true,\r
2948                 curFrame: 0,\r
2949                 totalFrames: mgr.fps,\r
2950                 runAttrs: {},\r
2951                 animate: function(){\r
2952                     var me = this,\r
2953                         d = me.duration;\r
2954                     \r
2955                     if(me.isAnimated){\r
2956                         return false;\r
2957                     }\r
2958 \r
2959                     me.curFrame = 0;\r
2960                     me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;\r
2961                     mgr.registerElement(me); \r
2962                 },\r
2963                 \r
2964                 stop: function(finish){\r
2965                     var me = this;\r
2966                 \r
2967                     if(finish){\r
2968                         me.curFrame = me.totalFrames;\r
2969                         me._onTween.fire();\r
2970                     }\r
2971                     mgr.stop(me);\r
2972                 }\r
2973             });\r
2974 \r
2975             var onStart = function(){\r
2976                 var me = this,\r
2977                     attr;\r
2978                 \r
2979                 me.onStart.fire();\r
2980                 me.runAttrs = {};\r
2981                 for(attr in this.attributes){\r
2982                     this.setRunAttr(attr);\r
2983                 }\r
2984 \r
2985                 me.isAnimated = true;\r
2986                 me.startTime = now();\r
2987                 actualFrames = 0;\r
2988             };\r
2989 \r
2990 \r
2991             var onTween = function(){\r
2992                 var me = this;\r
2993 \r
2994                 me.onTween.fire({\r
2995                     duration: now() - me.startTime,\r
2996                     curFrame: me.curFrame\r
2997                 });\r
2998 \r
2999                 var ra = me.runAttrs;\r
3000                 for (var attr in ra) {\r
3001                     this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);\r
3002                 }\r
3003 \r
3004                 ++actualFrames;\r
3005             };\r
3006 \r
3007             var onComplete = function() {\r
3008                 var me = this,\r
3009                     actual = (now() - me.startTime) / 1000,\r
3010                     data = {\r
3011                         duration: actual,\r
3012                         frames: actualFrames,\r
3013                         fps: actualFrames / actual\r
3014                     };\r
3015 \r
3016                 me.isAnimated = false;\r
3017                 actualFrames = 0;\r
3018                 me.onComplete.fire(data);\r
3019             };\r
3020 \r
3021             me.onStart = new Ext.util.Event(me);\r
3022             me.onTween = new Ext.util.Event(me);            \r
3023             me.onComplete = new Ext.util.Event(me);\r
3024             (me._onStart = new Ext.util.Event(me)).addListener(onStart);\r
3025             (me._onTween = new Ext.util.Event(me)).addListener(onTween);\r
3026             (me._onComplete = new Ext.util.Event(me)).addListener(onComplete); \r
3027         }\r
3028     };\r
3029 \r
3030 \r
3031     Ext.lib.AnimMgr = new function() {\r
3032         var me = this,\r
3033             thread = null,\r
3034             queue = [],\r
3035             tweenCount = 0;\r
3036 \r
3037 \r
3038         Ext.apply(me, {\r
3039             fps: 1000,\r
3040             delay: 1,\r
3041             registerElement: function(tween){\r
3042                 queue.push(tween);\r
3043                 ++tweenCount;\r
3044                 tween._onStart.fire();\r
3045                 me.start();\r
3046             },\r
3047             \r
3048             unRegister: function(tween, index){\r
3049                 tween._onComplete.fire();\r
3050                 index = index || getIndex(tween);\r
3051                 if (index != -1) {\r
3052                     queue.splice(index, 1);\r
3053                 }\r
3054 \r
3055                 if (--tweenCount <= 0) {\r
3056                     me.stop();\r
3057                 }\r
3058             },\r
3059             \r
3060             start: function(){\r
3061                 if(thread === null){\r
3062                     thread = setInterval(me.run, me.delay);\r
3063                 }\r
3064             },\r
3065             \r
3066             stop: function(tween){\r
3067                 if(!tween){\r
3068                     clearInterval(thread);\r
3069                     for(var i = 0, len = queue.length; i < len; ++i){\r
3070                         if(queue[0].isAnimated){\r
3071                             me.unRegister(queue[0], 0);\r
3072                         }\r
3073                     }\r
3074 \r
3075                     queue = [];\r
3076                     thread = null;\r
3077                     tweenCount = 0;\r
3078                 }else{\r
3079                     me.unRegister(tween);\r
3080                 }\r
3081             },\r
3082             \r
3083             run: function(){\r
3084                 var tf, i, len, tween;\r
3085                 for(i = 0, len = queue.length; i<len; i++) {\r
3086                     tween = queue[i];\r
3087                     if(tween && tween.isAnimated){\r
3088                         tf = tween.totalFrames;\r
3089                         if(tween.curFrame < tf || tf === null){\r
3090                             ++tween.curFrame;\r
3091                             if(tween.useSec){\r
3092                                 correctFrame(tween);\r
3093                             }\r
3094                             tween._onTween.fire();\r
3095                         }else{\r
3096                             me.stop(tween);\r
3097                         }\r
3098                     }                   \r
3099                 }\r
3100             }\r
3101         });\r
3102 \r
3103         var getIndex = function(anim) {\r
3104             var i, len;\r
3105             for(i = 0, len = queue.length; i<len; i++) {\r
3106                 if(queue[i] === anim) {\r
3107                     return i;\r
3108                 }\r
3109             }\r
3110             return -1;\r
3111         };\r
3112 \r
3113         var correctFrame = function(tween) {\r
3114             var frames = tween.totalFrames,\r
3115                 frame = tween.curFrame,\r
3116                 duration = tween.duration,\r
3117                 expected = (frame * duration * 1000 / frames),\r
3118                 elapsed = (now() - tween.startTime),\r
3119                 tweak = 0;\r
3120 \r
3121             if(elapsed < duration * 1000){\r
3122                 tweak = Math.round((elapsed / expected - 1) * frame);\r
3123             }else{\r
3124                 tweak = frames - (frame + 1);\r
3125             }\r
3126             if(tweak > 0 && isFinite(tweak)){\r
3127                 if(tween.curFrame + tweak >= frames){\r
3128                     tweak = frames - (frame + 1);\r
3129                 }\r
3130                 tween.curFrame += tweak;\r
3131             }\r
3132         };\r
3133     };\r
3134 \r
3135     EXTLIB.Bezier = new function() {\r
3136 \r
3137         this.getPosition = function(points, t) {\r
3138             var n = points.length,\r
3139                 tmp = [],\r
3140                 c = 1 - t, \r
3141                 i,\r
3142                 j;\r
3143 \r
3144             for (i = 0; i < n; ++i) {\r
3145                 tmp[i] = [points[i][0], points[i][1]];\r
3146             }\r
3147 \r
3148             for (j = 1; j < n; ++j) {\r
3149                 for (i = 0; i < n - j; ++i) {\r
3150                     tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];\r
3151                     tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];\r
3152                 }\r
3153             }\r
3154 \r
3155             return [ tmp[0][0], tmp[0][1] ];\r
3156 \r
3157         };\r
3158     };\r
3159 \r
3160 \r
3161     EXTLIB.Easing = {\r
3162         easeNone: function (t, b, c, d) {\r
3163             return c * t / d + b;\r
3164         },\r
3165 \r
3166 \r
3167         easeIn: function (t, b, c, d) {\r
3168             return c * (t /= d) * t + b;\r
3169         },\r
3170 \r
3171 \r
3172         easeOut: function (t, b, c, d) {\r
3173             return -c * (t /= d) * (t - 2) + b;\r
3174         }\r
3175     };\r
3176 \r
3177     (function() {\r
3178         EXTLIB.Motion = function(el, attributes, duration, method) {\r
3179             if (el) {\r
3180                 EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);\r
3181             }\r
3182         };\r
3183 \r
3184         Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);\r
3185 \r
3186         var superclass = EXTLIB.Motion.superclass,\r
3187             proto = EXTLIB.Motion.prototype,\r
3188             pointsRe = /^points$/i;\r
3189 \r
3190         Ext.apply(EXTLIB.Motion.prototype, {\r
3191             setAttr: function(attr, val, unit){\r
3192                 var me = this,\r
3193                     setAttr = superclass.setAttr;\r
3194                     \r
3195                 if (pointsRe.test(attr)) {\r
3196                     unit = unit || 'px';\r
3197                     setAttr.call(me, 'left', val[0], unit);\r
3198                     setAttr.call(me, 'top', val[1], unit);\r
3199                 } else {\r
3200                     setAttr.call(me, attr, val, unit);\r
3201                 }\r
3202             },\r
3203             \r
3204             getAttr: function(attr){\r
3205                 var me = this,\r
3206                     getAttr = superclass.getAttr;\r
3207                     \r
3208                 return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);\r
3209             },\r
3210             \r
3211             doMethod: function(attr, start, end){\r
3212                 var me = this;\r
3213                 \r
3214                 return pointsRe.test(attr)\r
3215                         ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)\r
3216                         : superclass.doMethod.call(me, attr, start, end);\r
3217             },\r
3218             \r
3219             setRunAttr: function(attr){\r
3220                 if(pointsRe.test(attr)){\r
3221                     \r
3222                     var me = this,\r
3223                         el = this.el,\r
3224                         points = this.attributes.points,\r
3225                         control = points.control || [],\r
3226                         from = points.from,\r
3227                         to = points.to,\r
3228                         by = points.by,\r
3229                         DOM = EXTLIB.Dom,\r
3230                         start,\r
3231                         i,\r
3232                         end,\r
3233                         len,\r
3234                         ra;\r
3235                   \r
3236 \r
3237                     if(control.length > 0 && !Ext.isArray(control[0])){\r
3238                         control = [control];\r
3239                     }else{\r
3240                         /*\r
3241                         var tmp = [];\r
3242                         for (i = 0,len = control.length; i < len; ++i) {\r
3243                             tmp[i] = control[i];\r
3244                         }\r
3245                         control = tmp;\r
3246                         */\r
3247                     }\r
3248 \r
3249                     Ext.fly(el, '_anim').position();\r
3250                     DOM.setXY(el, isset(from) ? from : DOM.getXY(el));\r
3251                     start = me.getAttr('points');\r
3252 \r
3253 \r
3254                     if(isset(to)){\r
3255                         end = translateValues.call(me, to, start);\r
3256                         for (i = 0,len = control.length; i < len; ++i) {\r
3257                             control[i] = translateValues.call(me, control[i], start);\r
3258                         }\r
3259                     } else if (isset(by)) {\r
3260                         end = [start[0] + by[0], start[1] + by[1]];\r
3261 \r
3262                         for (i = 0,len = control.length; i < len; ++i) {\r
3263                             control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];\r
3264                         }\r
3265                     }\r
3266 \r
3267                     ra = this.runAttrs[attr] = [start];\r
3268                     if (control.length > 0) {\r
3269                         ra = ra.concat(control);\r
3270                     }\r
3271 \r
3272                     ra[ra.length] = end;\r
3273                 }else{\r
3274                     superclass.setRunAttr.call(this, attr);\r
3275                 }\r
3276             }\r
3277         });\r
3278 \r
3279         var translateValues = function(val, start) {\r
3280             var pageXY = EXTLIB.Dom.getXY(this.el);\r
3281             return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];\r
3282         };\r
3283     })();\r
3284 })();// Easing functions\r
3285 (function(){\r
3286         // shortcuts to aid compression\r
3287         var abs = Math.abs,\r
3288                 pi = Math.PI,\r
3289                 asin = Math.asin,\r
3290                 pow = Math.pow,\r
3291                 sin = Math.sin,\r
3292                 EXTLIB = Ext.lib;\r
3293                 \r
3294     Ext.apply(EXTLIB.Easing, {\r
3295         \r
3296         easeBoth: function (t, b, c, d) {\r
3297                 return ((t /= d / 2) < 1)  ?  c / 2 * t * t + b  :  -c / 2 * ((--t) * (t - 2) - 1) + b;               \r
3298         },\r
3299         \r
3300         easeInStrong: function (t, b, c, d) {\r
3301             return c * (t /= d) * t * t * t + b;\r
3302         },\r
3303 \r
3304         easeOutStrong: function (t, b, c, d) {\r
3305             return -c * ((t = t / d - 1) * t * t * t - 1) + b;\r
3306         },\r
3307 \r
3308         easeBothStrong: function (t, b, c, d) {\r
3309             return ((t /= d / 2) < 1)  ?  c / 2 * t * t * t * t + b  :  -c / 2 * ((t -= 2) * t * t * t - 2) + b;\r
3310         },\r
3311 \r
3312         elasticIn: function (t, b, c, d, a, p) {\r
3313                 if (t == 0 || (t /= d) == 1) {\r
3314                 return t == 0 ? b : b + c;\r
3315             }               \r
3316             p = p || (d * .3);              \r
3317 \r
3318                         var s;\r
3319                         if (a >= abs(c)) {\r
3320                                 s = p / (2 * pi) * asin(c / a);\r
3321                         } else {\r
3322                                 a = c;\r
3323                                 s = p / 4;\r
3324                         }\r
3325         \r
3326             return -(a * pow(2, 10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b;\r
3327                       \r
3328         },      \r
3329         \r
3330                 elasticOut: function (t, b, c, d, a, p) {\r
3331                 if (t == 0 || (t /= d) == 1) {\r
3332                 return t == 0 ? b : b + c;\r
3333             }               \r
3334             p = p || (d * .3);              \r
3335 \r
3336                         var s;\r
3337                         if (a >= abs(c)) {\r
3338                                 s = p / (2 * pi) * asin(c / a);\r
3339                         } else {\r
3340                                 a = c;\r
3341                                 s = p / 4;\r
3342                         }\r
3343         \r
3344             return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b;        \r
3345         },      \r
3346         \r
3347         elasticBoth: function (t, b, c, d, a, p) {\r
3348             if (t == 0 || (t /= d / 2) == 2) {\r
3349                 return t == 0 ? b : b + c;\r
3350             }                           \r
3351                     \r
3352             p = p || (d * (.3 * 1.5));              \r
3353 \r
3354             var s;\r
3355             if (a >= abs(c)) {\r
3356                     s = p / (2 * pi) * asin(c / a);\r
3357             } else {\r
3358                     a = c;\r
3359                 s = p / 4;\r
3360             }\r
3361 \r
3362             return t < 1 ?\r
3363                         -.5 * (a * pow(2, 10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b :\r
3364                     a * pow(2, -10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p) * .5 + c + b;\r
3365         },\r
3366 \r
3367         backIn: function (t, b, c, d, s) {\r
3368             s = s ||  1.70158;              \r
3369             return c * (t /= d) * t * ((s + 1) * t - s) + b;\r
3370         },\r
3371 \r
3372 \r
3373         backOut: function (t, b, c, d, s) {\r
3374             if (!s) {\r
3375                 s = 1.70158;\r
3376             }\r
3377             return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\r
3378         },\r
3379 \r
3380 \r
3381         backBoth: function (t, b, c, d, s) {\r
3382             s = s || 1.70158;               \r
3383 \r
3384             return ((t /= d / 2 ) < 1) ?\r
3385                     c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b :                  \r
3386                         c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\r
3387         },\r
3388 \r
3389 \r
3390         bounceIn: function (t, b, c, d) {\r
3391             return c - EXTLIB.Easing.bounceOut(d - t, 0, c, d) + b;\r
3392         },\r
3393 \r
3394 \r
3395         bounceOut: function (t, b, c, d) {\r
3396         if ((t /= d) < (1 / 2.75)) {\r
3397                 return c * (7.5625 * t * t) + b;\r
3398             } else if (t < (2 / 2.75)) {\r
3399                 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;\r
3400             } else if (t < (2.5 / 2.75)) {\r
3401                 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;\r
3402             }\r
3403             return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;\r
3404         },\r
3405 \r
3406 \r
3407         bounceBoth: function (t, b, c, d) {\r
3408             return (t < d / 2) ?\r
3409                    EXTLIB.Easing.bounceIn(t * 2, 0, c, d) * .5 + b : \r
3410                    EXTLIB.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;\r
3411         }\r
3412     });\r
3413 })();\r
3414 \r
3415 (function() {\r
3416     var EXTLIB = Ext.lib;\r
3417         // Color Animation\r
3418         EXTLIB.Anim.color = function(el, args, duration, easing, cb, scope) {\r
3419             return EXTLIB.Anim.run(el, args, duration, easing, cb, scope, EXTLIB.ColorAnim);\r
3420         }\r
3421         \r
3422     EXTLIB.ColorAnim = function(el, attributes, duration, method) {\r
3423         EXTLIB.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);\r
3424     };\r
3425 \r
3426     Ext.extend(EXTLIB.ColorAnim, EXTLIB.AnimBase);\r
3427 \r
3428     var superclass = EXTLIB.ColorAnim.superclass,\r
3429         colorRE = /color$/i,\r
3430         transparentRE = /^transparent|rgba\(0, 0, 0, 0\)$/,\r
3431         rgbRE = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,\r
3432         hexRE= /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,\r
3433         hex3RE = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,\r
3434         isset = function(v){\r
3435             return typeof v !== 'undefined';\r
3436         }\r
3437                 \r
3438         // private      \r
3439     function parseColor(s) {    \r
3440         var pi = parseInt,\r
3441             base,\r
3442             out = null,\r
3443             c;\r
3444         \r
3445             if (s.length == 3) {\r
3446             return s;\r
3447         }\r
3448                 \r
3449         Ext.each([hexRE, rgbRE, hex3RE], function(re, idx){\r
3450             base = (idx % 2 == 0) ? 16 : 10;\r
3451             c = re.exec(s);\r
3452             if(c && c.length == 4){\r
3453                 out = [pi(c[1], base), pi(c[2], base), pi(c[3], base)];\r
3454                 return false;\r
3455             }\r
3456         });\r
3457         return out;\r
3458     }   \r
3459 \r
3460     Ext.apply(EXTLIB.ColorAnim.prototype, {\r
3461         getAttr : function(attr) {\r
3462             var me = this,\r
3463                 el = me.el,\r
3464                 val;                \r
3465             if(colorRE.test(attr)){\r
3466                 while(el && transparentRE.test(val = Ext.fly(el).getStyle(attr))){\r
3467                     el = el.parentNode;\r
3468                     val = "fff";\r
3469                 }\r
3470             }else{\r
3471                 val = superclass.getAttr.call(me, attr);\r
3472             }\r
3473             return val;\r
3474         },\r
3475 \r
3476         doMethod : function(attr, start, end) {\r
3477             var me = this,\r
3478                 val,\r
3479                 floor = Math.floor,\r
3480                                 i, len = start.length, v;            \r
3481 \r
3482             if(colorRE.test(attr)){\r
3483                 val = [];\r
3484                                 \r
3485                                 for(i=0; i<len; i++) {\r
3486                                         v = start[i];\r
3487                                         val[i] = superclass.doMethod.call(me, attr, v, end[i]);\r
3488                                 }\r
3489                 val = 'rgb(' + floor(val[0]) + ',' + floor(val[1]) + ',' + floor(val[2]) + ')';\r
3490             }else{\r
3491                 val = superclass.doMethod.call(me, attr, start, end);\r
3492             }\r
3493             return val;\r
3494         },\r
3495 \r
3496         setRunAttr : function(attr) {\r
3497             var me = this,\r
3498                 a = me.attributes[attr],\r
3499                 to = a.to,\r
3500                 by = a.by,\r
3501                 ra;\r
3502                 \r
3503             superclass.setRunAttr.call(me, attr);\r
3504             ra = me.runAttrs[attr];\r
3505             if(colorRE.test(attr)){\r
3506                 var start = parseColor(ra.start),\r
3507                     end = parseColor(ra.end);\r
3508 \r
3509                 if(!isset(to) && isset(by)){\r
3510                     end = parseColor(by);\r
3511                                         for(var i=0,len=start.length; i<len; i++) {\r
3512                                                 end[i] = start[i] + end[i];\r
3513                                         }\r
3514                 }\r
3515                 ra.start = start;\r
3516                 ra.end = end;\r
3517             }\r
3518         }\r
3519         });\r
3520 })();   \r
3521 \r
3522         \r
3523 (function() {\r
3524             // Scroll Animation \r
3525     var EXTLIB = Ext.lib;\r
3526         EXTLIB.Anim.scroll = function(el, args, duration, easing, cb, scope) {          \r
3527             return EXTLIB.Anim.run(el, args, duration, easing, cb, scope, EXTLIB.Scroll);\r
3528         }\r
3529         \r
3530     EXTLIB.Scroll = function(el, attributes, duration, method) {\r
3531         if(el){\r
3532             EXTLIB.Scroll.superclass.constructor.call(this, el, attributes, duration, method);\r
3533         }\r
3534     };\r
3535 \r
3536     Ext.extend(EXTLIB.Scroll, EXTLIB.ColorAnim);\r
3537 \r
3538     var superclass = EXTLIB.Scroll.superclass,\r
3539         SCROLL = 'scroll';\r
3540 \r
3541     Ext.apply(EXTLIB.Scroll.prototype, {\r
3542 \r
3543         doMethod : function(attr, start, end) {\r
3544             var val,\r
3545                 me = this,\r
3546                 curFrame = me.curFrame,\r
3547                 totalFrames = me.totalFrames;\r
3548 \r
3549             if(attr == SCROLL){\r
3550                 val = [me.method(curFrame, start[0], end[0] - start[0], totalFrames),\r
3551                        me.method(curFrame, start[1], end[1] - start[1], totalFrames)];\r
3552             }else{\r
3553                 val = superclass.doMethod.call(me, attr, start, end);\r
3554             }\r
3555             return val;\r
3556         },\r
3557 \r
3558         getAttr : function(attr) {\r
3559             var me = this;\r
3560 \r
3561             if (attr == SCROLL) {\r
3562                 return [me.el.scrollLeft, me.el.scrollTop];\r
3563             }else{\r
3564                 return superclass.getAttr.call(me, attr);\r
3565             }\r
3566         },\r
3567 \r
3568         setAttr : function(attr, val, unit) {\r
3569             var me = this;\r
3570 \r
3571             if(attr == SCROLL){\r
3572                 me.el.scrollLeft = val[0];\r
3573                 me.el.scrollTop = val[1];\r
3574             }else{\r
3575                 superclass.setAttr.call(me, attr, val, unit);\r
3576             }\r
3577         }\r
3578     });\r
3579 })();   \r
3580         if(Ext.isIE) {\r
3581         function fnCleanUp() {\r
3582             var p = Function.prototype;\r
3583             delete p.createSequence;\r
3584             delete p.defer;\r
3585             delete p.createDelegate;\r
3586             delete p.createCallback;\r
3587             delete p.createInterceptor;\r
3588 \r
3589             window.detachEvent("onunload", fnCleanUp);\r
3590         }\r
3591         window.attachEvent("onunload", fnCleanUp);\r
3592     }\r
3593 })();