8d0a32a536d892350eed3b23a8bdfdf60a81a755
[extjs.git] / adapter / ext / ext-base-debug.js
1 /*!
2  * Ext JS Library 3.1.1
3  * Copyright(c) 2006-2010 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.1'
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(/\bchrome\b/),
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             el = Ext.getDom(el, true) || {};
165             if (!el.id) {
166                 el.id = (prefix || "ext-gen") + (++idSeed);
167             }
168             return el.id;
169         },
170
171         /**
172          * <p>Extends one class to create a subclass and optionally overrides members with the passed literal. This method
173          * also adds the function "override()" to the subclass that can be used to override members of the class.</p>
174          * For example, to create a subclass of Ext GridPanel:
175          * <pre><code>
176 MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
177     constructor: function(config) {
178
179 //      Create configuration for this Grid.
180         var store = new Ext.data.Store({...});
181         var colModel = new Ext.grid.ColumnModel({...});
182
183 //      Create a new config object containing our computed properties
184 //      *plus* whatever was in the config parameter.
185         config = Ext.apply({
186             store: store,
187             colModel: colModel
188         }, config);
189
190         MyGridPanel.superclass.constructor.call(this, config);
191
192 //      Your postprocessing here
193     },
194
195     yourMethod: function() {
196         // etc.
197     }
198 });
199 </code></pre>
200          *
201          * <p>This function also supports a 3-argument call in which the subclass's constructor is
202          * passed as an argument. In this form, the parameters are as follows:</p>
203          * <div class="mdetail-params"><ul>
204          * <li><code>subclass</code> : Function <div class="sub-desc">The subclass constructor.</div></li>
205          * <li><code>superclass</code> : Function <div class="sub-desc">The constructor of class being extended</div></li>
206          * <li><code>overrides</code> : Object <div class="sub-desc">A literal with members which are copied into the subclass's
207          * prototype, and are therefore shared among all instances of the new class.</div></li>
208          * </ul></div>
209          *
210          * @param {Function} superclass The constructor of class being extended.
211          * @param {Object} overrides <p>A literal with members which are copied into the subclass's
212          * prototype, and are therefore shared between all instances of the new class.</p>
213          * <p>This may contain a special member named <tt><b>constructor</b></tt>. This is used
214          * to define the constructor of the new class, and is returned. If this property is
215          * <i>not</i> specified, a constructor is generated and returned which just calls the
216          * superclass's constructor passing on its parameters.</p>
217          * <p><b>It is essential that you call the superclass constructor in any provided constructor. See example code.</b></p>
218          * @return {Function} The subclass constructor from the <code>overrides</code> parameter, or a generated one if not provided.
219          */
220         extend : function(){
221             // inline overrides
222             var io = function(o){
223                 for(var m in o){
224                     this[m] = o[m];
225                 }
226             };
227             var oc = Object.prototype.constructor;
228
229             return function(sb, sp, overrides){
230                 if(Ext.isObject(sp)){
231                     overrides = sp;
232                     sp = sb;
233                     sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
234                 }
235                 var F = function(){},
236                     sbp,
237                     spp = sp.prototype;
238
239                 F.prototype = spp;
240                 sbp = sb.prototype = new F();
241                 sbp.constructor=sb;
242                 sb.superclass=spp;
243                 if(spp.constructor == oc){
244                     spp.constructor=sp;
245                 }
246                 sb.override = function(o){
247                     Ext.override(sb, o);
248                 };
249                 sbp.superclass = sbp.supr = (function(){
250                     return spp;
251                 });
252                 sbp.override = io;
253                 Ext.override(sb, overrides);
254                 sb.extend = function(o){return Ext.extend(sb, o);};
255                 return sb;
256             };
257         }(),
258
259         /**
260          * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
261          * Usage:<pre><code>
262 Ext.override(MyClass, {
263     newMethod1: function(){
264         // etc.
265     },
266     newMethod2: function(foo){
267         // etc.
268     }
269 });
270 </code></pre>
271          * @param {Object} origclass The class to override
272          * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
273          * containing one or more methods.
274          * @method override
275          */
276         override : function(origclass, overrides){
277             if(overrides){
278                 var p = origclass.prototype;
279                 Ext.apply(p, overrides);
280                 if(Ext.isIE && overrides.hasOwnProperty('toString')){
281                     p.toString = overrides.toString;
282                 }
283             }
284         },
285
286         /**
287          * Creates namespaces to be used for scoping variables and classes so that they are not global.
288          * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
289          * <pre><code>
290 Ext.namespace('Company', 'Company.data');
291 Ext.namespace('Company.data'); // equivalent and preferable to above syntax
292 Company.Widget = function() { ... }
293 Company.data.CustomStore = function(config) { ... }
294 </code></pre>
295          * @param {String} namespace1
296          * @param {String} namespace2
297          * @param {String} etc
298          * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
299          * @method namespace
300          */
301         namespace : function(){
302             var o, d;
303             Ext.each(arguments, function(v) {
304                 d = v.split(".");
305                 o = window[d[0]] = window[d[0]] || {};
306                 Ext.each(d.slice(1), function(v2){
307                     o = o[v2] = o[v2] || {};
308                 });
309             });
310             return o;
311         },
312
313         /**
314          * 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.
315          * @param {Object} o
316          * @param {String} pre (optional) A prefix to add to the url encoded string
317          * @return {String}
318          */
319         urlEncode : function(o, pre){
320             var empty,
321                 buf = [],
322                 e = encodeURIComponent;
323
324             Ext.iterate(o, function(key, item){
325                 empty = Ext.isEmpty(item);
326                 Ext.each(empty ? key : item, function(val){
327                     buf.push('&', e(key), '=', (!Ext.isEmpty(val) && (val != key || !empty)) ? (Ext.isDate(val) ? Ext.encode(val).replace(/"/g, '') : e(val)) : '');
328                 });
329             });
330             if(!pre){
331                 buf.shift();
332                 pre = '';
333             }
334             return pre + buf.join('');
335         },
336
337         /**
338          * Takes an encoded URL and and converts it to an object. Example: <pre><code>
339 Ext.urlDecode("foo=1&bar=2"); // returns {foo: "1", bar: "2"}
340 Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2", "3", "4"]}
341 </code></pre>
342          * @param {String} string
343          * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
344          * @return {Object} A literal with members
345          */
346         urlDecode : function(string, overwrite){
347             if(Ext.isEmpty(string)){
348                 return {};
349             }
350             var obj = {},
351                 pairs = string.split('&'),
352                 d = decodeURIComponent,
353                 name,
354                 value;
355             Ext.each(pairs, function(pair) {
356                 pair = pair.split('=');
357                 name = d(pair[0]);
358                 value = d(pair[1]);
359                 obj[name] = overwrite || !obj[name] ? value :
360                             [].concat(obj[name]).concat(value);
361             });
362             return obj;
363         },
364
365         /**
366          * Appends content to the query string of a URL, handling logic for whether to place
367          * a question mark or ampersand.
368          * @param {String} url The URL to append to.
369          * @param {String} s The content to append to the URL.
370          * @return (String) The resulting URL
371          */
372         urlAppend : function(url, s){
373             if(!Ext.isEmpty(s)){
374                 return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
375             }
376             return url;
377         },
378
379         /**
380          * Converts any iterable (numeric indices and a length property) into a true array
381          * Don't use this on strings. IE doesn't support "abc"[0] which this implementation depends on.
382          * For strings, use this instead: "abc".match(/./g) => [a,b,c];
383          * @param {Iterable} the iterable object to be turned into a true Array.
384          * @return (Array) array
385          */
386          toArray : function(){
387              return isIE ?
388                  function(a, i, j, res){
389                      res = [];
390                      for(var x = 0, len = a.length; x < len; x++) {
391                          res.push(a[x]);
392                      }
393                      return res.slice(i || 0, j || res.length);
394                  } :
395                  function(a, i, j){
396                      return Array.prototype.slice.call(a, i || 0, j || a.length);
397                  }
398          }(),
399
400         isIterable : function(v){
401             //check for array or arguments
402             if(Ext.isArray(v) || v.callee){
403                 return true;
404             }
405             //check for node list type
406             if(/NodeList|HTMLCollection/.test(toString.call(v))){
407                 return true;
408             }
409             //NodeList has an item and length property
410             //IXMLDOMNodeList has nextNode method, needs to be checked first.
411             return ((typeof v.nextNode != 'undefined' || v.item) && Ext.isNumber(v.length));
412         },
413
414         /**
415          * Iterates an array calling the supplied function.
416          * @param {Array/NodeList/Mixed} array The array to be iterated. If this
417          * argument is not really an array, the supplied function is called once.
418          * @param {Function} fn The function to be called with each item. If the
419          * supplied function returns false, iteration stops and this method returns
420          * the current <code>index</code>. This function is called with
421          * the following arguments:
422          * <div class="mdetail-params"><ul>
423          * <li><code>item</code> : <i>Mixed</i>
424          * <div class="sub-desc">The item at the current <code>index</code>
425          * in the passed <code>array</code></div></li>
426          * <li><code>index</code> : <i>Number</i>
427          * <div class="sub-desc">The current index within the array</div></li>
428          * <li><code>allItems</code> : <i>Array</i>
429          * <div class="sub-desc">The <code>array</code> passed as the first
430          * argument to <code>Ext.each</code>.</div></li>
431          * </ul></div>
432          * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed.
433          * Defaults to the <code>item</code> at the current <code>index</code>
434          * within the passed <code>array</code>.
435          * @return See description for the fn parameter.
436          */
437         each : function(array, fn, scope){
438             if(Ext.isEmpty(array, true)){
439                 return;
440             }
441             if(!Ext.isIterable(array) || Ext.isPrimitive(array)){
442                 array = [array];
443             }
444             for(var i = 0, len = array.length; i < len; i++){
445                 if(fn.call(scope || array[i], array[i], i, array) === false){
446                     return i;
447                 };
448             }
449         },
450
451         /**
452          * Iterates either the elements in an array, or each of the properties in an object.
453          * <b>Note</b>: If you are only iterating arrays, it is better to call {@link #each}.
454          * @param {Object/Array} object The object or array to be iterated
455          * @param {Function} fn The function to be called for each iteration.
456          * The iteration will stop if the supplied function returns false, or
457          * all array elements / object properties have been covered. The signature
458          * varies depending on the type of object being interated:
459          * <div class="mdetail-params"><ul>
460          * <li>Arrays : <tt>(Object item, Number index, Array allItems)</tt>
461          * <div class="sub-desc">
462          * When iterating an array, the supplied function is called with each item.</div></li>
463          * <li>Objects : <tt>(String key, Object value, Object)</tt>
464          * <div class="sub-desc">
465          * When iterating an object, the supplied function is called with each key-value pair in
466          * the object, and the iterated object</div></li>
467          * </ul></div>
468          * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed. Defaults to
469          * the <code>object</code> being iterated.
470          */
471         iterate : function(obj, fn, scope){
472             if(Ext.isEmpty(obj)){
473                 return;
474             }
475             if(Ext.isIterable(obj)){
476                 Ext.each(obj, fn, scope);
477                 return;
478             }else if(Ext.isObject(obj)){
479                 for(var prop in obj){
480                     if(obj.hasOwnProperty(prop)){
481                         if(fn.call(scope || obj, prop, obj[prop], obj) === false){
482                             return;
483                         };
484                     }
485                 }
486             }
487         },
488
489         /**
490          * Return the dom node for the passed String (id), dom node, or Ext.Element.
491          * Optional 'strict' flag is needed for IE since it can return 'name' and
492          * 'id' elements by using getElementById.
493          * Here are some examples:
494          * <pre><code>
495 // gets dom node based on id
496 var elDom = Ext.getDom('elId');
497 // gets dom node based on the dom node
498 var elDom1 = Ext.getDom(elDom);
499
500 // If we don&#39;t know if we are working with an
501 // Ext.Element or a dom node use Ext.getDom
502 function(el){
503     var dom = Ext.getDom(el);
504     // do something with the dom node
505 }
506          * </code></pre>
507          * <b>Note</b>: the dom node to be found actually needs to exist (be rendered, etc)
508          * when this method is called to be successful.
509          * @param {Mixed} el
510          * @return HTMLElement
511          */
512         getDom : function(el, strict){
513             if(!el || !DOC){
514                 return null;
515             }
516             if (el.dom){
517                 return el.dom;
518             } else {
519                 if (Ext.isString(el)) {
520                     var e = DOC.getElementById(el);
521                     // IE returns elements with the 'name' and 'id' attribute.
522                     // we do a strict check to return the element with only the id attribute
523                     if (e && isIE && strict) {
524                         if (el == e.getAttribute('id')) {
525                             return e;
526                         } else {
527                             return null;
528                         }
529                     }
530                     return e;
531                 } else {
532                     return el;
533                 }
534             }
535         },
536
537         /**
538          * Returns the current document body as an {@link Ext.Element}.
539          * @return Ext.Element The document body
540          */
541         getBody : function(){
542             return Ext.get(DOC.body || DOC.documentElement);
543         },
544
545         /**
546          * Removes a DOM node from the document.
547          */
548         /**
549          * <p>Removes this element from the document, removes all DOM event listeners, and deletes the cache reference.
550          * All DOM event listeners are removed from this element. If {@link Ext#enableNestedListenerRemoval} is
551          * <code>true</code>, then DOM event listeners are also removed from all child nodes. The body node
552          * will be ignored if passed in.</p>
553          * @param {HTMLElement} node The node to remove
554          */
555         removeNode : isIE && !isIE8 ? function(){
556             var d;
557             return function(n){
558                 if(n && n.tagName != 'BODY'){
559                     (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
560                     d = d || DOC.createElement('div');
561                     d.appendChild(n);
562                     d.innerHTML = '';
563                     delete Ext.elCache[n.id];
564                 }
565             }
566         }() : function(n){
567             if(n && n.parentNode && n.tagName != 'BODY'){
568                 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
569                 n.parentNode.removeChild(n);
570                 delete Ext.elCache[n.id];
571             }
572         },
573
574         /**
575          * <p>Returns true if the passed value is empty.</p>
576          * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
577          * <li>null</li>
578          * <li>undefined</li>
579          * <li>an empty array</li>
580          * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
581          * </ul></div>
582          * @param {Mixed} value The value to test
583          * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
584          * @return {Boolean}
585          */
586         isEmpty : function(v, allowBlank){
587             return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
588         },
589
590         /**
591          * Returns true if the passed value is a JavaScript array, otherwise false.
592          * @param {Mixed} value The value to test
593          * @return {Boolean}
594          */
595         isArray : function(v){
596             return toString.apply(v) === '[object Array]';
597         },
598
599         /**
600          * Returns true if the passed object is a JavaScript date object, otherwise false.
601          * @param {Object} object The object to test
602          * @return {Boolean}
603          */
604         isDate : function(v){
605             return toString.apply(v) === '[object Date]';
606         },
607
608         /**
609          * Returns true if the passed value is a JavaScript Object, otherwise false.
610          * @param {Mixed} value The value to test
611          * @return {Boolean}
612          */
613         isObject : function(v){
614             return !!v && Object.prototype.toString.call(v) === '[object Object]';
615         },
616
617         /**
618          * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
619          * @param {Mixed} value The value to test
620          * @return {Boolean}
621          */
622         isPrimitive : function(v){
623             return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
624         },
625
626         /**
627          * Returns true if the passed value is a JavaScript Function, otherwise false.
628          * @param {Mixed} value The value to test
629          * @return {Boolean}
630          */
631         isFunction : function(v){
632             return toString.apply(v) === '[object Function]';
633         },
634
635         /**
636          * Returns true if the passed value is a number. Returns false for non-finite numbers.
637          * @param {Mixed} value The value to test
638          * @return {Boolean}
639          */
640         isNumber : function(v){
641             return typeof v === 'number' && isFinite(v);
642         },
643
644         /**
645          * Returns true if the passed value is a string.
646          * @param {Mixed} value The value to test
647          * @return {Boolean}
648          */
649         isString : function(v){
650             return typeof v === 'string';
651         },
652
653         /**
654          * Returns true if the passed value is a boolean.
655          * @param {Mixed} value The value to test
656          * @return {Boolean}
657          */
658         isBoolean : function(v){
659             return typeof v === 'boolean';
660         },
661
662         /**
663          * Returns true if the passed value is an HTMLElement
664          * @param {Mixed} value The value to test
665          * @return {Boolean}
666          */
667         isElement : function(v) {
668             return !!v && v.tagName;
669         },
670
671         /**
672          * Returns true if the passed value is not undefined.
673          * @param {Mixed} value The value to test
674          * @return {Boolean}
675          */
676         isDefined : function(v){
677             return typeof v !== 'undefined';
678         },
679
680         /**
681          * True if the detected browser is Opera.
682          * @type Boolean
683          */
684         isOpera : isOpera,
685         /**
686          * True if the detected browser uses WebKit.
687          * @type Boolean
688          */
689         isWebKit : isWebKit,
690         /**
691          * True if the detected browser is Chrome.
692          * @type Boolean
693          */
694         isChrome : isChrome,
695         /**
696          * True if the detected browser is Safari.
697          * @type Boolean
698          */
699         isSafari : isSafari,
700         /**
701          * True if the detected browser is Safari 3.x.
702          * @type Boolean
703          */
704         isSafari3 : isSafari3,
705         /**
706          * True if the detected browser is Safari 4.x.
707          * @type Boolean
708          */
709         isSafari4 : isSafari4,
710         /**
711          * True if the detected browser is Safari 2.x.
712          * @type Boolean
713          */
714         isSafari2 : isSafari2,
715         /**
716          * True if the detected browser is Internet Explorer.
717          * @type Boolean
718          */
719         isIE : isIE,
720         /**
721          * True if the detected browser is Internet Explorer 6.x.
722          * @type Boolean
723          */
724         isIE6 : isIE6,
725         /**
726          * True if the detected browser is Internet Explorer 7.x.
727          * @type Boolean
728          */
729         isIE7 : isIE7,
730         /**
731          * True if the detected browser is Internet Explorer 8.x.
732          * @type Boolean
733          */
734         isIE8 : isIE8,
735         /**
736          * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
737          * @type Boolean
738          */
739         isGecko : isGecko,
740         /**
741          * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
742          * @type Boolean
743          */
744         isGecko2 : isGecko2,
745         /**
746          * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
747          * @type Boolean
748          */
749         isGecko3 : isGecko3,
750         /**
751          * True if the detected browser is Internet Explorer running in non-strict mode.
752          * @type Boolean
753          */
754         isBorderBox : isBorderBox,
755         /**
756          * True if the detected platform is Linux.
757          * @type Boolean
758          */
759         isLinux : isLinux,
760         /**
761          * True if the detected platform is Windows.
762          * @type Boolean
763          */
764         isWindows : isWindows,
765         /**
766          * True if the detected platform is Mac OS.
767          * @type Boolean
768          */
769         isMac : isMac,
770         /**
771          * True if the detected platform is Adobe Air.
772          * @type Boolean
773          */
774         isAir : isAir
775     });
776
777     /**
778      * Creates namespaces to be used for scoping variables and classes so that they are not global.
779      * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
780      * <pre><code>
781 Ext.namespace('Company', 'Company.data');
782 Ext.namespace('Company.data'); // equivalent and preferable to above syntax
783 Company.Widget = function() { ... }
784 Company.data.CustomStore = function(config) { ... }
785 </code></pre>
786      * @param {String} namespace1
787      * @param {String} namespace2
788      * @param {String} etc
789      * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
790      * @method ns
791      */
792     Ext.ns = Ext.namespace;
793 })();
794
795 Ext.ns("Ext.util", "Ext.lib", "Ext.data");
796
797 Ext.elCache = {};
798
799 /**
800  * @class Function
801  * These functions are available on every Function object (any JavaScript function).
802  */
803 Ext.apply(Function.prototype, {
804      /**
805      * Creates an interceptor function. The passed function is called before the original one. If it returns false,
806      * the original one is not called. The resulting function returns the results of the original function.
807      * The passed function is called with the parameters of the original function. Example usage:
808      * <pre><code>
809 var sayHi = function(name){
810     alert('Hi, ' + name);
811 }
812
813 sayHi('Fred'); // alerts "Hi, Fred"
814
815 // create a new function that validates input without
816 // directly modifying the original function:
817 var sayHiToFriend = sayHi.createInterceptor(function(name){
818     return name == 'Brian';
819 });
820
821 sayHiToFriend('Fred');  // no alert
822 sayHiToFriend('Brian'); // alerts "Hi, Brian"
823 </code></pre>
824      * @param {Function} fcn The function to call before the original
825      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
826      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
827      * @return {Function} The new function
828      */
829     createInterceptor : function(fcn, scope){
830         var method = this;
831         return !Ext.isFunction(fcn) ?
832                 this :
833                 function() {
834                     var me = this,
835                         args = arguments;
836                     fcn.target = me;
837                     fcn.method = method;
838                     return (fcn.apply(scope || me || window, args) !== false) ?
839                             method.apply(me || window, args) :
840                             null;
841                 };
842     },
843
844      /**
845      * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
846      * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code>
847      * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the
848      * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always
849      * executes in the window scope.
850      * <p>This method is required when you want to pass arguments to a callback function.  If no arguments
851      * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn).
852      * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function
853      * would simply execute immediately when the code is parsed. Example usage:
854      * <pre><code>
855 var sayHi = function(name){
856     alert('Hi, ' + name);
857 }
858
859 // clicking the button alerts "Hi, Fred"
860 new Ext.Button({
861     text: 'Say Hi',
862     renderTo: Ext.getBody(),
863     handler: sayHi.createCallback('Fred')
864 });
865 </code></pre>
866      * @return {Function} The new function
867     */
868     createCallback : function(/*args...*/){
869         // make args available, in function below
870         var args = arguments,
871             method = this;
872         return function() {
873             return method.apply(window, args);
874         };
875     },
876
877     /**
878      * Creates a delegate (callback) that sets the scope to obj.
879      * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code>
880      * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
881      * callback points to obj. Example usage:
882      * <pre><code>
883 var sayHi = function(name){
884     // Note this use of "this.text" here.  This function expects to
885     // execute within a scope that contains a text property.  In this
886     // example, the "this" variable is pointing to the btn object that
887     // was passed in createDelegate below.
888     alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
889 }
890
891 var btn = new Ext.Button({
892     text: 'Say Hi',
893     renderTo: Ext.getBody()
894 });
895
896 // This callback will execute in the scope of the
897 // button instance. Clicking the button alerts
898 // "Hi, Fred. You clicked the "Say Hi" button."
899 btn.on('click', sayHi.createDelegate(btn, ['Fred']));
900 </code></pre>
901      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
902      * <b>If omitted, defaults to the browser window.</b>
903      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
904      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
905      * if a number the args are inserted at the specified position
906      * @return {Function} The new function
907      */
908     createDelegate : function(obj, args, appendArgs){
909         var method = this;
910         return function() {
911             var callArgs = args || arguments;
912             if (appendArgs === true){
913                 callArgs = Array.prototype.slice.call(arguments, 0);
914                 callArgs = callArgs.concat(args);
915             }else if (Ext.isNumber(appendArgs)){
916                 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
917                 var applyArgs = [appendArgs, 0].concat(args); // create method call params
918                 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
919             }
920             return method.apply(obj || window, callArgs);
921         };
922     },
923
924     /**
925      * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
926      * <pre><code>
927 var sayHi = function(name){
928     alert('Hi, ' + name);
929 }
930
931 // executes immediately:
932 sayHi('Fred');
933
934 // executes after 2 seconds:
935 sayHi.defer(2000, this, ['Fred']);
936
937 // this syntax is sometimes useful for deferring
938 // execution of an anonymous function:
939 (function(){
940     alert('Anonymous');
941 }).defer(100);
942 </code></pre>
943      * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
944      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
945      * <b>If omitted, defaults to the browser window.</b>
946      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
947      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
948      * if a number the args are inserted at the specified position
949      * @return {Number} The timeout id that can be used with clearTimeout
950      */
951     defer : function(millis, obj, args, appendArgs){
952         var fn = this.createDelegate(obj, args, appendArgs);
953         if(millis > 0){
954             return setTimeout(fn, millis);
955         }
956         fn();
957         return 0;
958     }
959 });
960
961 /**
962  * @class String
963  * These functions are available on every String object.
964  */
965 Ext.applyIf(String, {
966     /**
967      * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
968      * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
969      * <pre><code>
970 var cls = 'my-class', text = 'Some text';
971 var s = String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
972 // s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
973      * </code></pre>
974      * @param {String} string The tokenized string to be formatted
975      * @param {String} value1 The value to replace token {0}
976      * @param {String} value2 Etc...
977      * @return {String} The formatted string
978      * @static
979      */
980     format : function(format){
981         var args = Ext.toArray(arguments, 1);
982         return format.replace(/\{(\d+)\}/g, function(m, i){
983             return args[i];
984         });
985     }
986 });
987
988 /**
989  * @class Array
990  */
991 Ext.applyIf(Array.prototype, {
992     /**
993      * Checks whether or not the specified object exists in the array.
994      * @param {Object} o The object to check for
995      * @param {Number} from (Optional) The index at which to begin the search
996      * @return {Number} The index of o in the array (or -1 if it is not found)
997      */
998     indexOf : function(o, from){
999         var len = this.length;
1000         from = from || 0;
1001         from += (from < 0) ? len : 0;
1002         for (; from < len; ++from){
1003             if(this[from] === o){
1004                 return from;
1005             }
1006         }
1007         return -1;
1008     },
1009
1010     /**
1011      * Removes the specified object from the array.  If the object is not found nothing happens.
1012      * @param {Object} o The object to remove
1013      * @return {Array} this array
1014      */
1015     remove : function(o){
1016         var index = this.indexOf(o);
1017         if(index != -1){
1018             this.splice(index, 1);
1019         }
1020         return this;
1021     }
1022 });
1023 /**
1024  * @class Ext
1025  */
1026
1027 Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
1028        "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
1029     /**
1030      * Namespace alloted for extensions to the framework.
1031      * @property ux
1032      * @type Object
1033      */
1034
1035 Ext.apply(Ext, function(){
1036     var E = Ext, 
1037         idSeed = 0,
1038         scrollWidth = null;
1039
1040     return {
1041         /**
1042         * A reusable empty function
1043         * @property
1044         * @type Function
1045         */
1046         emptyFn : function(){},
1047
1048         /**
1049          * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images. 
1050          * In older versions of IE, this defaults to "http://extjs.com/s.gif" and you should change this to a URL on your server.
1051          * For other browsers it uses an inline data URL.
1052          * @type String
1053          */
1054         BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
1055                             'http:/' + '/extjs.com/s.gif' :
1056                             'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
1057
1058         extendX : function(supr, fn){
1059             return Ext.extend(supr, fn(supr.prototype));
1060         },
1061
1062         /**
1063          * Returns the current HTML document object as an {@link Ext.Element}.
1064          * @return Ext.Element The document
1065          */
1066         getDoc : function(){
1067             return Ext.get(document);
1068         },
1069
1070         /**
1071          * Utility method for validating that a value is numeric, returning the specified default value if it is not.
1072          * @param {Mixed} value Should be a number, but any type will be handled appropriately
1073          * @param {Number} defaultValue The value to return if the original value is non-numeric
1074          * @return {Number} Value, if numeric, else defaultValue
1075          */
1076         num : function(v, defaultValue){
1077             v = Number(Ext.isEmpty(v) || Ext.isArray(v) || Ext.isBoolean(v) || (Ext.isString(v) && v.trim().length == 0) ? NaN : v);
1078             return isNaN(v) ? defaultValue : v;
1079         },
1080
1081         /**
1082          * <p>Utility method for returning a default value if the passed value is empty.</p>
1083          * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
1084          * <li>null</li>
1085          * <li>undefined</li>
1086          * <li>an empty array</li>
1087          * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
1088          * </ul></div>
1089          * @param {Mixed} value The value to test
1090          * @param {Mixed} defaultValue The value to return if the original value is empty
1091          * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
1092          * @return {Mixed} value, if non-empty, else defaultValue
1093          */
1094         value : function(v, defaultValue, allowBlank){
1095             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
1096         },
1097
1098         /**
1099          * Escapes the passed string for use in a regular expression
1100          * @param {String} str
1101          * @return {String}
1102          */
1103         escapeRe : function(s) {
1104             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
1105         },
1106
1107         sequence : function(o, name, fn, scope){
1108             o[name] = o[name].createSequence(fn, scope);
1109         },
1110
1111         /**
1112          * Applies event listeners to elements by selectors when the document is ready.
1113          * The event name is specified with an <tt>&#64;</tt> suffix.
1114          * <pre><code>
1115 Ext.addBehaviors({
1116     // add a listener for click on all anchors in element with id foo
1117     '#foo a&#64;click' : function(e, t){
1118         // do something
1119     },
1120     
1121     // add the same listener to multiple selectors (separated by comma BEFORE the &#64;)
1122     '#foo a, #bar span.some-class&#64;mouseover' : function(){
1123         // do something
1124     }
1125 });
1126          * </code></pre> 
1127          * @param {Object} obj The list of behaviors to apply
1128          */
1129         addBehaviors : function(o){
1130             if(!Ext.isReady){
1131                 Ext.onReady(function(){
1132                     Ext.addBehaviors(o);
1133                 });
1134             } else {
1135                 var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
1136                     parts,
1137                     b,
1138                     s;
1139                 for (b in o) {
1140                     if ((parts = b.split('@'))[1]) { // for Object prototype breakers
1141                         s = parts[0];
1142                         if(!cache[s]){
1143                             cache[s] = Ext.select(s);
1144                         }
1145                         cache[s].on(parts[1], o[b]);
1146                     }
1147                 }
1148                 cache = null;
1149             }
1150         },
1151         
1152         /**
1153          * Utility method for getting the width of the browser scrollbar. This can differ depending on
1154          * operating system settings, such as the theme or font size.
1155          * @param {Boolean} force (optional) true to force a recalculation of the value.
1156          * @return {Number} The width of the scrollbar.
1157          */
1158         getScrollBarWidth: function(force){
1159             if(!Ext.isReady){
1160                 return 0;
1161             }
1162             
1163             if(force === true || scrollWidth === null){
1164                     // Append our div, do our calculation and then remove it
1165                 var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
1166                     child = div.child('div', true);
1167                 var w1 = child.offsetWidth;
1168                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
1169                 var w2 = child.offsetWidth;
1170                 div.remove();
1171                 // Need to add 2 to ensure we leave enough space
1172                 scrollWidth = w1 - w2 + 2;
1173             }
1174             return scrollWidth;
1175         },
1176
1177
1178         // deprecated
1179         combine : function(){
1180             var as = arguments, l = as.length, r = [];
1181             for(var i = 0; i < l; i++){
1182                 var a = as[i];
1183                 if(Ext.isArray(a)){
1184                     r = r.concat(a);
1185                 }else if(a.length !== undefined && !a.substr){
1186                     r = r.concat(Array.prototype.slice.call(a, 0));
1187                 }else{
1188                     r.push(a);
1189                 }
1190             }
1191             return r;
1192         },
1193
1194         /**
1195          * Copies a set of named properties fom the source object to the destination object.
1196          * <p>example:<pre><code>
1197 ImageComponent = Ext.extend(Ext.BoxComponent, {
1198     initComponent: function() {
1199         this.autoEl = { tag: 'img' };
1200         MyComponent.superclass.initComponent.apply(this, arguments);
1201         this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
1202     }
1203 });
1204          * </code></pre> 
1205          * @param {Object} The destination object.
1206          * @param {Object} The source object.
1207          * @param {Array/String} Either an Array of property names, or a comma-delimited list
1208          * of property names to copy.
1209          * @return {Object} The modified object.
1210         */
1211         copyTo : function(dest, source, names){
1212             if(Ext.isString(names)){
1213                 names = names.split(/[,;\s]/);
1214             }
1215             Ext.each(names, function(name){
1216                 if(source.hasOwnProperty(name)){
1217                     dest[name] = source[name];
1218                 }
1219             }, this);
1220             return dest;
1221         },
1222
1223         /**
1224          * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
1225          * DOM (if applicable) and calling their destroy functions (if available).  This method is primarily
1226          * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
1227          * {@link Ext.util.Observable} can be passed in.  Any number of elements and/or components can be
1228          * passed into this function in a single call as separate arguments.
1229          * @param {Mixed} arg1 An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
1230          * @param {Mixed} arg2 (optional)
1231          * @param {Mixed} etc... (optional)
1232          */
1233         destroy : function(){
1234             Ext.each(arguments, function(arg){
1235                 if(arg){
1236                     if(Ext.isArray(arg)){
1237                         this.destroy.apply(this, arg);
1238                     }else if(Ext.isFunction(arg.destroy)){
1239                         arg.destroy();
1240                     }else if(arg.dom){
1241                         arg.remove();
1242                     }    
1243                 }
1244             }, this);
1245         },
1246
1247         /**
1248          * Attempts to destroy and then remove a set of named properties of the passed object.
1249          * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
1250          * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
1251          * @param {Mixed} etc... More property names to destroy and remove.
1252          */
1253         destroyMembers : function(o, arg1, arg2, etc){
1254             for(var i = 1, a = arguments, len = a.length; i < len; i++) {
1255                 Ext.destroy(o[a[i]]);
1256                 delete o[a[i]];
1257             }
1258         },
1259
1260         /**
1261          * Creates a copy of the passed Array with falsy values removed.
1262          * @param {Array/NodeList} arr The Array from which to remove falsy values.
1263          * @return {Array} The new, compressed Array.
1264          */
1265         clean : function(arr){
1266             var ret = [];
1267             Ext.each(arr, function(v){
1268                 if(!!v){
1269                     ret.push(v);
1270                 }
1271             });
1272             return ret;
1273         },
1274
1275         /**
1276          * Creates a copy of the passed Array, filtered to contain only unique values.
1277          * @param {Array} arr The Array to filter
1278          * @return {Array} The new Array containing unique values.
1279          */
1280         unique : function(arr){
1281             var ret = [],
1282                 collect = {};
1283
1284             Ext.each(arr, function(v) {
1285                 if(!collect[v]){
1286                     ret.push(v);
1287                 }
1288                 collect[v] = true;
1289             });
1290             return ret;
1291         },
1292
1293         /**
1294          * Recursively flattens into 1-d Array. Injects Arrays inline.
1295          * @param {Array} arr The array to flatten
1296          * @return {Array} The new, flattened array.
1297          */
1298         flatten : function(arr){
1299             var worker = [];
1300             function rFlatten(a) {
1301                 Ext.each(a, function(v) {
1302                     if(Ext.isArray(v)){
1303                         rFlatten(v);
1304                     }else{
1305                         worker.push(v);
1306                     }
1307                 });
1308                 return worker;
1309             }
1310             return rFlatten(arr);
1311         },
1312
1313         /**
1314          * Returns the minimum value in the Array.
1315          * @param {Array|NodeList} arr The Array from which to select the minimum value.
1316          * @param {Function} comp (optional) a function to perform the comparision which determines minimization.
1317          *                   If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
1318          * @return {Object} The minimum value in the Array.
1319          */
1320         min : function(arr, comp){
1321             var ret = arr[0];
1322             comp = comp || function(a,b){ return a < b ? -1 : 1; };
1323             Ext.each(arr, function(v) {
1324                 ret = comp(ret, v) == -1 ? ret : v;
1325             });
1326             return ret;
1327         },
1328
1329         /**
1330          * Returns the maximum value in the Array
1331          * @param {Array|NodeList} arr The Array from which to select the maximum value.
1332          * @param {Function} comp (optional) a function to perform the comparision which determines maximization.
1333          *                   If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
1334          * @return {Object} The maximum value in the Array.
1335          */
1336         max : function(arr, comp){
1337             var ret = arr[0];
1338             comp = comp || function(a,b){ return a > b ? 1 : -1; };
1339             Ext.each(arr, function(v) {
1340                 ret = comp(ret, v) == 1 ? ret : v;
1341             });
1342             return ret;
1343         },
1344
1345         /**
1346          * Calculates the mean of the Array
1347          * @param {Array} arr The Array to calculate the mean value of.
1348          * @return {Number} The mean.
1349          */
1350         mean : function(arr){
1351            return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
1352         },
1353
1354         /**
1355          * Calculates the sum of the Array
1356          * @param {Array} arr The Array to calculate the sum value of.
1357          * @return {Number} The sum.
1358          */
1359         sum : function(arr){
1360            var ret = 0;
1361            Ext.each(arr, function(v) {
1362                ret += v;
1363            });
1364            return ret;
1365         },
1366
1367         /**
1368          * Partitions the set into two sets: a true set and a false set.
1369          * Example: 
1370          * Example2: 
1371          * <pre><code>
1372 // Example 1:
1373 Ext.partition([true, false, true, true, false]); // [[true, true, true], [false, false]]
1374
1375 // Example 2:
1376 Ext.partition(
1377     Ext.query("p"),
1378     function(val){
1379         return val.className == "class1"
1380     }
1381 );
1382 // true are those paragraph elements with a className of "class1",
1383 // false set are those that do not have that className.
1384          * </code></pre>
1385          * @param {Array|NodeList} arr The array to partition
1386          * @param {Function} truth (optional) a function to determine truth.  If this is omitted the element
1387          *                   itself must be able to be evaluated for its truthfulness.
1388          * @return {Array} [true<Array>,false<Array>]
1389          */
1390         partition : function(arr, truth){
1391             var ret = [[],[]];
1392             Ext.each(arr, function(v, i, a) {
1393                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
1394             });
1395             return ret;
1396         },
1397
1398         /**
1399          * Invokes a method on each item in an Array.
1400          * <pre><code>
1401 // Example:
1402 Ext.invoke(Ext.query("p"), "getAttribute", "id");
1403 // [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
1404          * </code></pre>
1405          * @param {Array|NodeList} arr The Array of items to invoke the method on.
1406          * @param {String} methodName The method name to invoke.
1407          * @param {Anything} ... Arguments to send into the method invocation.
1408          * @return {Array} The results of invoking the method on each item in the array.
1409          */
1410         invoke : function(arr, methodName){
1411             var ret = [],
1412                 args = Array.prototype.slice.call(arguments, 2);
1413             Ext.each(arr, function(v,i) {
1414                 if (v && Ext.isFunction(v[methodName])) {
1415                     ret.push(v[methodName].apply(v, args));
1416                 } else {
1417                     ret.push(undefined);
1418                 }
1419             });
1420             return ret;
1421         },
1422
1423         /**
1424          * Plucks the value of a property from each item in the Array
1425          * <pre><code>
1426 // Example:
1427 Ext.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
1428          * </code></pre>
1429          * @param {Array|NodeList} arr The Array of items to pluck the value from.
1430          * @param {String} prop The property name to pluck from each element.
1431          * @return {Array} The value from each item in the Array.
1432          */
1433         pluck : function(arr, prop){
1434             var ret = [];
1435             Ext.each(arr, function(v) {
1436                 ret.push( v[prop] );
1437             });
1438             return ret;
1439         },
1440
1441         /**
1442          * <p>Zips N sets together.</p>
1443          * <pre><code>
1444 // Example 1:
1445 Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
1446 // Example 2:
1447 Ext.zip(
1448     [ "+", "-", "+"],
1449     [  12,  10,  22],
1450     [  43,  15,  96],
1451     function(a, b, c){
1452         return "$" + a + "" + b + "." + c
1453     }
1454 ); // ["$+12.43", "$-10.15", "$+22.96"]
1455          * </code></pre>
1456          * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
1457          * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
1458          * @return {Array} The zipped set.
1459          */
1460         zip : function(){
1461             var parts = Ext.partition(arguments, function( val ){ return !Ext.isFunction(val); }),
1462                 arrs = parts[0],
1463                 fn = parts[1][0],
1464                 len = Ext.max(Ext.pluck(arrs, "length")),
1465                 ret = [];
1466
1467             for (var i = 0; i < len; i++) {
1468                 ret[i] = [];
1469                 if(fn){
1470                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
1471                 }else{
1472                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
1473                         ret[i].push( arrs[j][i] );
1474                     }
1475                 }
1476             }
1477             return ret;
1478         },
1479
1480         /**
1481          * This is shorthand reference to {@link Ext.ComponentMgr#get}.
1482          * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
1483          * @param {String} id The component {@link Ext.Component#id id}
1484          * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a
1485          * Class was found.
1486         */
1487         getCmp : function(id){
1488             return Ext.ComponentMgr.get(id);
1489         },
1490
1491         /**
1492          * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
1493          * you may want to set this to true.
1494          * @type Boolean
1495          */
1496         useShims: E.isIE6 || (E.isMac && E.isGecko2),
1497
1498         // inpired by a similar function in mootools library
1499         /**
1500          * Returns the type of object that is passed in. If the object passed in is null or undefined it
1501          * return false otherwise it returns one of the following values:<div class="mdetail-params"><ul>
1502          * <li><b>string</b>: If the object passed is a string</li>
1503          * <li><b>number</b>: If the object passed is a number</li>
1504          * <li><b>boolean</b>: If the object passed is a boolean value</li>
1505          * <li><b>date</b>: If the object passed is a Date object</li>
1506          * <li><b>function</b>: If the object passed is a function reference</li>
1507          * <li><b>object</b>: If the object passed is an object</li>
1508          * <li><b>array</b>: If the object passed is an array</li>
1509          * <li><b>regexp</b>: If the object passed is a regular expression</li>
1510          * <li><b>element</b>: If the object passed is a DOM Element</li>
1511          * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
1512          * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
1513          * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
1514          * </ul></div>
1515          * @param {Mixed} object
1516          * @return {String}
1517          */
1518         type : function(o){
1519             if(o === undefined || o === null){
1520                 return false;
1521             }
1522             if(o.htmlElement){
1523                 return 'element';
1524             }
1525             var t = typeof o;
1526             if(t == 'object' && o.nodeName) {
1527                 switch(o.nodeType) {
1528                     case 1: return 'element';
1529                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
1530                 }
1531             }
1532             if(t == 'object' || t == 'function') {
1533                 switch(o.constructor) {
1534                     case Array: return 'array';
1535                     case RegExp: return 'regexp';
1536                     case Date: return 'date';
1537                 }
1538                 if(Ext.isNumber(o.length) && Ext.isFunction(o.item)) {
1539                     return 'nodelist';
1540                 }
1541             }
1542             return t;
1543         },
1544
1545         intercept : function(o, name, fn, scope){
1546             o[name] = o[name].createInterceptor(fn, scope);
1547         },
1548
1549         // internal
1550         callback : function(cb, scope, args, delay){
1551             if(Ext.isFunction(cb)){
1552                 if(delay){
1553                     cb.defer(delay, scope, args || []);
1554                 }else{
1555                     cb.apply(scope, args || []);
1556                 }
1557             }
1558         }
1559     };
1560 }());
1561
1562 /**
1563  * @class Function
1564  * These functions are available on every Function object (any JavaScript function).
1565  */
1566 Ext.apply(Function.prototype, {
1567     /**
1568      * Create a combined function call sequence of the original function + the passed function.
1569      * The resulting function returns the results of the original function.
1570      * The passed fcn is called with the parameters of the original function. Example usage:
1571      * <pre><code>
1572 var sayHi = function(name){
1573     alert('Hi, ' + name);
1574 }
1575
1576 sayHi('Fred'); // alerts "Hi, Fred"
1577
1578 var sayGoodbye = sayHi.createSequence(function(name){
1579     alert('Bye, ' + name);
1580 });
1581
1582 sayGoodbye('Fred'); // both alerts show
1583 </code></pre>
1584      * @param {Function} fcn The function to sequence
1585      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
1586      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
1587      * @return {Function} The new function
1588      */
1589     createSequence : function(fcn, scope){
1590         var method = this;
1591         return !Ext.isFunction(fcn) ?
1592                 this :
1593                 function(){
1594                     var retval = method.apply(this || window, arguments);
1595                     fcn.apply(scope || this || window, arguments);
1596                     return retval;
1597                 };
1598     }
1599 });
1600
1601
1602 /**
1603  * @class String
1604  * These functions are available as static methods on the JavaScript String object.
1605  */
1606 Ext.applyIf(String, {
1607
1608     /**
1609      * Escapes the passed string for ' and \
1610      * @param {String} string The string to escape
1611      * @return {String} The escaped string
1612      * @static
1613      */
1614     escape : function(string) {
1615         return string.replace(/('|\\)/g, "\\$1");
1616     },
1617
1618     /**
1619      * Pads the left side of a string with a specified character.  This is especially useful
1620      * for normalizing number and date strings.  Example usage:
1621      * <pre><code>
1622 var s = String.leftPad('123', 5, '0');
1623 // s now contains the string: '00123'
1624      * </code></pre>
1625      * @param {String} string The original string
1626      * @param {Number} size The total length of the output string
1627      * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
1628      * @return {String} The padded string
1629      * @static
1630      */
1631     leftPad : function (val, size, ch) {
1632         var result = String(val);
1633         if(!ch) {
1634             ch = " ";
1635         }
1636         while (result.length < size) {
1637             result = ch + result;
1638         }
1639         return result;
1640     }
1641 });
1642
1643 /**
1644  * Utility function that allows you to easily switch a string between two alternating values.  The passed value
1645  * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
1646  * they are already different, the first value passed in is returned.  Note that this method returns the new value
1647  * but does not change the current string.
1648  * <pre><code>
1649 // alternate sort directions
1650 sort = sort.toggle('ASC', 'DESC');
1651
1652 // instead of conditional logic:
1653 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
1654 </code></pre>
1655  * @param {String} value The value to compare to the current string
1656  * @param {String} other The new value to use if the string already equals the first value passed in
1657  * @return {String} The new value
1658  */
1659 String.prototype.toggle = function(value, other){
1660     return this == value ? other : value;
1661 };
1662
1663 /**
1664  * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
1665  * <pre><code>
1666 var s = '  foo bar  ';
1667 alert('-' + s + '-');         //alerts "- foo bar -"
1668 alert('-' + s.trim() + '-');  //alerts "-foo bar-"
1669 </code></pre>
1670  * @return {String} The trimmed string
1671  */
1672 String.prototype.trim = function(){
1673     var re = /^\s+|\s+$/g;
1674     return function(){ return this.replace(re, ""); };
1675 }();
1676
1677 // here to prevent dependency on Date.js
1678 /**
1679  Returns the number of milliseconds between this date and date
1680  @param {Date} date (optional) Defaults to now
1681  @return {Number} The diff in milliseconds
1682  @member Date getElapsed
1683  */
1684 Date.prototype.getElapsed = function(date) {
1685     return Math.abs((date || new Date()).getTime()-this.getTime());
1686 };
1687
1688
1689 /**
1690  * @class Number
1691  */
1692 Ext.applyIf(Number.prototype, {
1693     /**
1694      * Checks whether or not the current number is within a desired range.  If the number is already within the
1695      * range it is returned, otherwise the min or max value is returned depending on which side of the range is
1696      * exceeded.  Note that this method returns the constrained value but does not change the current number.
1697      * @param {Number} min The minimum number in the range
1698      * @param {Number} max The maximum number in the range
1699      * @return {Number} The constrained value if outside the range, otherwise the current value
1700      */
1701     constrain : function(min, max){
1702         return Math.min(Math.max(this, min), max);
1703     }
1704 });
1705 /**
1706  * @class Ext.util.TaskRunner
1707  * Provides the ability to execute one or more arbitrary tasks in a multithreaded
1708  * manner.  Generally, you can use the singleton {@link Ext.TaskMgr} instead, but
1709  * if needed, you can create separate instances of TaskRunner.  Any number of
1710  * separate tasks can be started at any time and will run independently of each
1711  * other. Example usage:
1712  * <pre><code>
1713 // Start a simple clock task that updates a div once per second
1714 var updateClock = function(){
1715     Ext.fly('clock').update(new Date().format('g:i:s A'));
1716
1717 var task = {
1718     run: updateClock,
1719     interval: 1000 //1 second
1720 }
1721 var runner = new Ext.util.TaskRunner();
1722 runner.start(task);
1723
1724 // equivalent using TaskMgr
1725 Ext.TaskMgr.start({
1726     run: updateClock,
1727     interval: 1000
1728 });
1729
1730  * </code></pre>
1731  * Also see {@link Ext.util.DelayedTask}. 
1732  * 
1733  * @constructor
1734  * @param {Number} interval (optional) The minimum precision in milliseconds supported by this TaskRunner instance
1735  * (defaults to 10)
1736  */
1737 Ext.util.TaskRunner = function(interval){
1738     interval = interval || 10;
1739     var tasks = [], 
1740         removeQueue = [],
1741         id = 0,
1742         running = false,
1743
1744         // private
1745         stopThread = function(){
1746                 running = false;
1747                 clearInterval(id);
1748                 id = 0;
1749             },
1750
1751         // private
1752         startThread = function(){
1753                 if(!running){
1754                     running = true;
1755                     id = setInterval(runTasks, interval);
1756                 }
1757             },
1758
1759         // private
1760         removeTask = function(t){
1761                 removeQueue.push(t);
1762                 if(t.onStop){
1763                     t.onStop.apply(t.scope || t);
1764                 }
1765             },
1766             
1767         // private
1768         runTasks = function(){
1769                 var rqLen = removeQueue.length,
1770                         now = new Date().getTime();                                             
1771             
1772                 if(rqLen > 0){
1773                     for(var i = 0; i < rqLen; i++){
1774                         tasks.remove(removeQueue[i]);
1775                     }
1776                     removeQueue = [];
1777                     if(tasks.length < 1){
1778                         stopThread();
1779                         return;
1780                     }
1781                 }               
1782                 for(var i = 0, t, itime, rt, len = tasks.length; i < len; ++i){
1783                     t = tasks[i];
1784                     itime = now - t.taskRunTime;
1785                     if(t.interval <= itime){
1786                         rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
1787                         t.taskRunTime = now;
1788                         if(rt === false || t.taskRunCount === t.repeat){
1789                             removeTask(t);
1790                             return;
1791                         }
1792                     }
1793                     if(t.duration && t.duration <= (now - t.taskStartTime)){
1794                         removeTask(t);
1795                     }
1796                 }
1797             };
1798
1799     /**
1800      * Starts a new task.
1801      * @method start
1802      * @param {Object} task A config object that supports the following properties:<ul>
1803      * <li><code>run</code> : Function<div class="sub-desc">The function to execute each time the task is run. The
1804      * function will be called at each interval and passed the <code>args</code> argument if specified.  If a
1805      * particular scope is required, be sure to specify it using the <code>scope</code> argument.</div></li>
1806      * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
1807      * should be executed.</div></li>
1808      * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
1809      * specified by <code>run</code>.</div></li>
1810      * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
1811      * <code>run</code> function. Defaults to the task config object.</div></li>
1812      * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to execute
1813      * the task before stopping automatically (defaults to indefinite).</div></li>
1814      * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to execute the task before
1815      * stopping automatically (defaults to indefinite).</div></li>
1816      * </ul>
1817      * @return {Object} The task
1818      */
1819     this.start = function(task){
1820         tasks.push(task);
1821         task.taskStartTime = new Date().getTime();
1822         task.taskRunTime = 0;
1823         task.taskRunCount = 0;
1824         startThread();
1825         return task;
1826     };
1827
1828     /**
1829      * Stops an existing running task.
1830      * @method stop
1831      * @param {Object} task The task to stop
1832      * @return {Object} The task
1833      */
1834     this.stop = function(task){
1835         removeTask(task);
1836         return task;
1837     };
1838
1839     /**
1840      * Stops all tasks that are currently running.
1841      * @method stopAll
1842      */
1843     this.stopAll = function(){
1844         stopThread();
1845         for(var i = 0, len = tasks.length; i < len; i++){
1846             if(tasks[i].onStop){
1847                 tasks[i].onStop();
1848             }
1849         }
1850         tasks = [];
1851         removeQueue = [];
1852     };
1853 };
1854
1855 /**
1856  * @class Ext.TaskMgr
1857  * @extends Ext.util.TaskRunner
1858  * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
1859  * {@link Ext.util.TaskRunner} for supported methods and task config properties.
1860  * <pre><code>
1861 // Start a simple clock task that updates a div once per second
1862 var task = {
1863     run: function(){
1864         Ext.fly('clock').update(new Date().format('g:i:s A'));
1865     },
1866     interval: 1000 //1 second
1867 }
1868 Ext.TaskMgr.start(task);
1869 </code></pre>
1870  * @singleton
1871  */
1872 Ext.TaskMgr = new Ext.util.TaskRunner();(function(){\r
1873         var libFlyweight;\r
1874         \r
1875         function fly(el) {\r
1876         if (!libFlyweight) {\r
1877             libFlyweight = new Ext.Element.Flyweight();\r
1878         }\r
1879         libFlyweight.dom = el;\r
1880         return libFlyweight;\r
1881     }\r
1882     \r
1883     (function(){\r
1884         var doc = document,\r
1885                 isCSS1 = doc.compatMode == "CSS1Compat",\r
1886                 MAX = Math.max,         \r
1887         ROUND = Math.round,\r
1888                 PARSEINT = parseInt;\r
1889                 \r
1890         Ext.lib.Dom = {\r
1891             isAncestor : function(p, c) {\r
1892                     var ret = false;\r
1893                         \r
1894                         p = Ext.getDom(p);\r
1895                         c = Ext.getDom(c);\r
1896                         if (p && c) {\r
1897                                 if (p.contains) {\r
1898                                         return p.contains(c);\r
1899                                 } else if (p.compareDocumentPosition) {\r
1900                                         return !!(p.compareDocumentPosition(c) & 16);\r
1901                                 } else {\r
1902                                         while (c = c.parentNode) {\r
1903                                                 ret = c == p || ret;                                    \r
1904                                         }\r
1905                                 }                   \r
1906                         }       \r
1907                         return ret;\r
1908                 },\r
1909                 \r
1910         getViewWidth : function(full) {\r
1911             return full ? this.getDocumentWidth() : this.getViewportWidth();\r
1912         },\r
1913 \r
1914         getViewHeight : function(full) {\r
1915             return full ? this.getDocumentHeight() : this.getViewportHeight();\r
1916         },\r
1917 \r
1918         getDocumentHeight: function() {            \r
1919             return MAX(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, this.getViewportHeight());\r
1920         },\r
1921 \r
1922         getDocumentWidth: function() {            \r
1923             return MAX(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, this.getViewportWidth());\r
1924         },\r
1925 \r
1926         getViewportHeight: function(){\r
1927                 return Ext.isIE ? \r
1928                            (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :\r
1929                            self.innerHeight;\r
1930         },\r
1931 \r
1932         getViewportWidth : function() {\r
1933                 return !Ext.isStrict && !Ext.isOpera ? doc.body.clientWidth :\r
1934                            Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;\r
1935         },\r
1936         \r
1937         getY : function(el) {\r
1938             return this.getXY(el)[1];\r
1939         },\r
1940 \r
1941         getX : function(el) {\r
1942             return this.getXY(el)[0];\r
1943         },\r
1944 \r
1945         getXY : function(el) {\r
1946             var p, \r
1947                 pe, \r
1948                 b,\r
1949                 bt, \r
1950                 bl,     \r
1951                 dbd,            \r
1952                 x = 0,\r
1953                 y = 0, \r
1954                 scroll,\r
1955                 hasAbsolute, \r
1956                 bd = (doc.body || doc.documentElement),\r
1957                 ret = [0,0];\r
1958                 \r
1959             el = Ext.getDom(el);\r
1960 \r
1961             if(el != bd){\r
1962                     if (el.getBoundingClientRect) {\r
1963                         b = el.getBoundingClientRect();\r
1964                         scroll = fly(document).getScroll();\r
1965                         ret = [ROUND(b.left + scroll.left), ROUND(b.top + scroll.top)];\r
1966                     } else {  \r
1967                             p = el;             \r
1968                             hasAbsolute = fly(el).isStyle("position", "absolute");\r
1969                 \r
1970                             while (p) {\r
1971                                     pe = fly(p);                \r
1972                                 x += p.offsetLeft;\r
1973                                 y += p.offsetTop;\r
1974                 \r
1975                                 hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");\r
1976                                                 \r
1977                                 if (Ext.isGecko) {                                  \r
1978                                     y += bt = PARSEINT(pe.getStyle("borderTopWidth"), 10) || 0;\r
1979                                     x += bl = PARSEINT(pe.getStyle("borderLeftWidth"), 10) || 0;        \r
1980                 \r
1981                                     if (p != el && !pe.isStyle('overflow','visible')) {\r
1982                                         x += bl;\r
1983                                         y += bt;\r
1984                                     }\r
1985                                 }\r
1986                                 p = p.offsetParent;\r
1987                             }\r
1988                 \r
1989                             if (Ext.isSafari && hasAbsolute) {\r
1990                                 x -= bd.offsetLeft;\r
1991                                 y -= bd.offsetTop;\r
1992                             }\r
1993                 \r
1994                             if (Ext.isGecko && !hasAbsolute) {\r
1995                                 dbd = fly(bd);\r
1996                                 x += PARSEINT(dbd.getStyle("borderLeftWidth"), 10) || 0;\r
1997                                 y += PARSEINT(dbd.getStyle("borderTopWidth"), 10) || 0;\r
1998                             }\r
1999                 \r
2000                             p = el.parentNode;\r
2001                             while (p && p != bd) {\r
2002                                 if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {\r
2003                                     x -= p.scrollLeft;\r
2004                                     y -= p.scrollTop;\r
2005                                 }\r
2006                                 p = p.parentNode;\r
2007                             }\r
2008                             ret = [x,y];\r
2009                     }\r
2010                 }\r
2011             return ret\r
2012         },\r
2013 \r
2014         setXY : function(el, xy) {\r
2015             (el = Ext.fly(el, '_setXY')).position();\r
2016             \r
2017             var pts = el.translatePoints(xy),\r
2018                 style = el.dom.style,\r
2019                 pos;                    \r
2020             \r
2021             for (pos in pts) {              \r
2022                     if(!isNaN(pts[pos])) style[pos] = pts[pos] + "px"\r
2023             }\r
2024         },\r
2025 \r
2026         setX : function(el, x) {\r
2027             this.setXY(el, [x, false]);\r
2028         },\r
2029 \r
2030         setY : function(el, y) {\r
2031             this.setXY(el, [false, y]);\r
2032         }\r
2033     };\r
2034 })();Ext.lib.Dom.getRegion = function(el) {\r
2035     return Ext.lib.Region.getRegion(el);\r
2036 };Ext.lib.Event = function() {
2037     var loadComplete = false,
2038         unloadListeners = {},
2039         retryCount = 0,
2040         onAvailStack = [],
2041         _interval,
2042         locked = false,
2043         win = window,
2044         doc = document,
2045
2046         // constants
2047         POLL_RETRYS = 200,
2048         POLL_INTERVAL = 20,
2049         EL = 0,
2050         TYPE = 0,
2051         FN = 1,
2052         WFN = 2,
2053         OBJ = 2,
2054         ADJ_SCOPE = 3,
2055         SCROLLLEFT = 'scrollLeft',
2056         SCROLLTOP = 'scrollTop',
2057         UNLOAD = 'unload',
2058         MOUSEOVER = 'mouseover',
2059         MOUSEOUT = 'mouseout',
2060         // private
2061         doAdd = function() {
2062             var ret;
2063             if (win.addEventListener) {
2064                 ret = function(el, eventName, fn, capture) {
2065                     if (eventName == 'mouseenter') {
2066                         fn = fn.createInterceptor(checkRelatedTarget);
2067                         el.addEventListener(MOUSEOVER, fn, (capture));
2068                     } else if (eventName == 'mouseleave') {
2069                         fn = fn.createInterceptor(checkRelatedTarget);
2070                         el.addEventListener(MOUSEOUT, fn, (capture));
2071                     } else {
2072                         el.addEventListener(eventName, fn, (capture));
2073                     }
2074                     return fn;
2075                 };
2076             } else if (win.attachEvent) {
2077                 ret = function(el, eventName, fn, capture) {
2078                     el.attachEvent("on" + eventName, fn);
2079                     return fn;
2080                 };
2081             } else {
2082                 ret = function(){};
2083             }
2084             return ret;
2085         }(),
2086         // private
2087         doRemove = function(){
2088             var ret;
2089             if (win.removeEventListener) {
2090                 ret = function (el, eventName, fn, capture) {
2091                     if (eventName == 'mouseenter') {
2092                         eventName = MOUSEOVER;
2093                     } else if (eventName == 'mouseleave') {
2094                         eventName = MOUSEOUT;
2095                     }
2096                     el.removeEventListener(eventName, fn, (capture));
2097                 };
2098             } else if (win.detachEvent) {
2099                 ret = function (el, eventName, fn) {
2100                     el.detachEvent("on" + eventName, fn);
2101                 };
2102             } else {
2103                 ret = function(){};
2104             }
2105             return ret;
2106         }();
2107
2108     function checkRelatedTarget(e) {
2109         return !elContains(e.currentTarget, pub.getRelatedTarget(e));
2110     }
2111
2112     function elContains(parent, child) {
2113        if(parent && parent.firstChild){
2114          while(child) {
2115             if(child === parent) {
2116                 return true;
2117             }
2118             child = child.parentNode;
2119             if(child && (child.nodeType != 1)) {
2120                 child = null;
2121             }
2122           }
2123         }
2124         return false;
2125     }
2126
2127     // private
2128     function _tryPreloadAttach() {
2129         var ret = false,
2130             notAvail = [],
2131             element, i, len, v,
2132             tryAgain = !loadComplete || (retryCount > 0);
2133
2134         if (!locked) {
2135             locked = true;
2136
2137             for (i = 0, len = onAvailStack.length; i < len; i++) {
2138                 v = onAvailStack[i];
2139                 if(v && (element = doc.getElementById(v.id))){
2140                     if(!v.checkReady || loadComplete || element.nextSibling || (doc && doc.body)) {
2141                         element = v.override ? (v.override === true ? v.obj : v.override) : element;
2142                         v.fn.call(element, v.obj);
2143                         onAvailStack.remove(v);
2144                     } else {
2145                         notAvail.push(v);
2146                     }
2147                 }
2148             }
2149
2150             retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2151
2152             if (tryAgain) {
2153                 startInterval();
2154             } else {
2155                 clearInterval(_interval);
2156                 _interval = null;
2157             }
2158
2159             ret = !(locked = false);
2160         }
2161         return ret;
2162     }
2163
2164     // private
2165     function startInterval() {
2166         if(!_interval){
2167             var callback = function() {
2168                 _tryPreloadAttach();
2169             };
2170             _interval = setInterval(callback, POLL_INTERVAL);
2171         }
2172     }
2173
2174     // private
2175     function getScroll() {
2176         var dd = doc.documentElement,
2177             db = doc.body;
2178         if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
2179             return [dd[SCROLLLEFT], dd[SCROLLTOP]];
2180         }else if(db){
2181             return [db[SCROLLLEFT], db[SCROLLTOP]];
2182         }else{
2183             return [0, 0];
2184         }
2185     }
2186
2187     // private
2188     function getPageCoord (ev, xy) {
2189         ev = ev.browserEvent || ev;
2190         var coord  = ev['page' + xy];
2191         if (!coord && coord !== 0) {
2192             coord = ev['client' + xy] || 0;
2193
2194             if (Ext.isIE) {
2195                 coord += getScroll()[xy == "X" ? 0 : 1];
2196             }
2197         }
2198
2199         return coord;
2200     }
2201
2202     var pub =  {
2203         extAdapter: true,
2204         onAvailable : function(p_id, p_fn, p_obj, p_override) {
2205             onAvailStack.push({
2206                 id:         p_id,
2207                 fn:         p_fn,
2208                 obj:        p_obj,
2209                 override:   p_override,
2210                 checkReady: false });
2211
2212             retryCount = POLL_RETRYS;
2213             startInterval();
2214         },
2215
2216         // This function should ALWAYS be called from Ext.EventManager
2217         addListener: function(el, eventName, fn) {
2218             el = Ext.getDom(el);
2219             if (el && fn) {
2220                 if (eventName == UNLOAD) {
2221                     if (unloadListeners[el.id] === undefined) {
2222                         unloadListeners[el.id] = [];
2223                     }
2224                     unloadListeners[el.id].push([eventName, fn]);
2225                     return fn;
2226                 }
2227                 return doAdd(el, eventName, fn, false);
2228             }
2229             return false;
2230         },
2231
2232         // This function should ALWAYS be called from Ext.EventManager
2233         removeListener: function(el, eventName, fn) {
2234             el = Ext.getDom(el);
2235             var i, len, li, lis;
2236             if (el && fn) {
2237                 if(eventName == UNLOAD){
2238                     if((lis = unloadListeners[el.id]) !== undefined){
2239                         for(i = 0, len = lis.length; i < len; i++){
2240                             if((li = lis[i]) && li[TYPE] == eventName && li[FN] == fn){
2241                                 unloadListeners[el.id].splice(i, 1);
2242                             }
2243                         }
2244                     }
2245                     return;
2246                 }
2247                 doRemove(el, eventName, fn, false);
2248             }
2249         },
2250
2251         getTarget : function(ev) {
2252             ev = ev.browserEvent || ev;
2253             return this.resolveTextNode(ev.target || ev.srcElement);
2254         },
2255
2256         resolveTextNode : Ext.isGecko ? function(node){
2257             if(!node){
2258                 return;
2259             }
2260             // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
2261             var s = HTMLElement.prototype.toString.call(node);
2262             if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
2263                 return;
2264             }
2265             return node.nodeType == 3 ? node.parentNode : node;
2266         } : function(node){
2267             return node && node.nodeType == 3 ? node.parentNode : node;
2268         },
2269
2270         getRelatedTarget : function(ev) {
2271             ev = ev.browserEvent || ev;
2272             return this.resolveTextNode(ev.relatedTarget ||
2273                     (ev.type == MOUSEOUT ? ev.toElement :
2274                      ev.type == MOUSEOVER ? ev.fromElement : null));
2275         },
2276
2277         getPageX : function(ev) {
2278             return getPageCoord(ev, "X");
2279         },
2280
2281         getPageY : function(ev) {
2282             return getPageCoord(ev, "Y");
2283         },
2284
2285
2286         getXY : function(ev) {
2287             return [this.getPageX(ev), this.getPageY(ev)];
2288         },
2289
2290         stopEvent : function(ev) {
2291             this.stopPropagation(ev);
2292             this.preventDefault(ev);
2293         },
2294
2295         stopPropagation : function(ev) {
2296             ev = ev.browserEvent || ev;
2297             if (ev.stopPropagation) {
2298                 ev.stopPropagation();
2299             } else {
2300                 ev.cancelBubble = true;
2301             }
2302         },
2303
2304         preventDefault : function(ev) {
2305             ev = ev.browserEvent || ev;
2306             if (ev.preventDefault) {
2307                 ev.preventDefault();
2308             } else {
2309                 ev.returnValue = false;
2310             }
2311         },
2312
2313         getEvent : function(e) {
2314             e = e || win.event;
2315             if (!e) {
2316                 var c = this.getEvent.caller;
2317                 while (c) {
2318                     e = c.arguments[0];
2319                     if (e && Event == e.constructor) {
2320                         break;
2321                     }
2322                     c = c.caller;
2323                 }
2324             }
2325             return e;
2326         },
2327
2328         getCharCode : function(ev) {
2329             ev = ev.browserEvent || ev;
2330             return ev.charCode || ev.keyCode || 0;
2331         },
2332
2333         //clearCache: function() {},
2334         // deprecated, call from EventManager
2335         getListeners : function(el, eventName) {
2336             Ext.EventManager.getListeners(el, eventName);
2337         },
2338
2339         // deprecated, call from EventManager
2340         purgeElement : function(el, recurse, eventName) {
2341             Ext.EventManager.purgeElement(el, recurse, eventName);
2342         },
2343
2344         _load : function(e) {
2345             loadComplete = true;
2346             var EU = Ext.lib.Event;
2347             if (Ext.isIE && e !== true) {
2348         // IE8 complains that _load is null or not an object
2349         // so lets remove self via arguments.callee
2350                 doRemove(win, "load", arguments.callee);
2351             }
2352         },
2353
2354         _unload : function(e) {
2355              var EU = Ext.lib.Event,
2356                 i, j, l, v, ul, id, len, index, scope;
2357
2358
2359             for (id in unloadListeners) {
2360                 ul = unloadListeners[id];
2361                 for (i = 0, len = ul.length; i < len; i++) {
2362                     v = ul[i];
2363                     if (v) {
2364                         try{
2365                             scope = v[ADJ_SCOPE] ? (v[ADJ_SCOPE] === true ? v[OBJ] : v[ADJ_SCOPE]) :  win;
2366                             v[FN].call(scope, EU.getEvent(e), v[OBJ]);
2367                         }catch(ex){}
2368                     }
2369                 }
2370             };
2371
2372             unloadListeners = null;
2373             Ext.EventManager._unload();
2374
2375             doRemove(win, UNLOAD, EU._unload);
2376         }
2377     };
2378
2379     // Initialize stuff.
2380     pub.on = pub.addListener;
2381     pub.un = pub.removeListener;
2382     if (doc && doc.body) {
2383         pub._load(true);
2384     } else {
2385         doAdd(win, "load", pub._load);
2386     }
2387     doAdd(win, UNLOAD, pub._unload);
2388     _tryPreloadAttach();
2389
2390     return pub;
2391 }();
2392 /*\r
2393 * Portions of this file are based on pieces of Yahoo User Interface Library\r
2394 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.\r
2395 * YUI licensed under the BSD License:\r
2396 * http://developer.yahoo.net/yui/license.txt\r
2397 */\r
2398 Ext.lib.Ajax = function() {     \r
2399     var activeX = ['MSXML2.XMLHTTP.3.0',\r
2400                    'MSXML2.XMLHTTP',\r
2401                    'Microsoft.XMLHTTP'],\r
2402         CONTENTTYPE = 'Content-Type';\r
2403                    \r
2404     // private\r
2405     function setHeader(o) {\r
2406         var conn = o.conn,\r
2407             prop;\r
2408         \r
2409         function setTheHeaders(conn, headers){\r
2410             for (prop in headers) {\r
2411                 if (headers.hasOwnProperty(prop)) {\r
2412                     conn.setRequestHeader(prop, headers[prop]);\r
2413                 }\r
2414             }   \r
2415         }       \r
2416         \r
2417         if (pub.defaultHeaders) {\r
2418             setTheHeaders(conn, pub.defaultHeaders);\r
2419         }\r
2420 \r
2421         if (pub.headers) {\r
2422             setTheHeaders(conn, pub.headers);\r
2423             delete pub.headers;                \r
2424         }\r
2425     }    \r
2426     \r
2427     // private\r
2428     function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {          \r
2429         return {\r
2430             tId : tId,\r
2431             status : isAbort ? -1 : 0,\r
2432             statusText : isAbort ? 'transaction aborted' : 'communication failure',\r
2433             isAbort: isAbort,\r
2434             isTimeout: isTimeout,\r
2435             argument : callbackArg\r
2436         };\r
2437     }  \r
2438     \r
2439     // private \r
2440     function initHeader(label, value) {         \r
2441         (pub.headers = pub.headers || {})[label] = value;                       \r
2442     }\r
2443     \r
2444     // private\r
2445     function createResponseObject(o, callbackArg) {\r
2446         var headerObj = {},\r
2447             headerStr,              \r
2448             conn = o.conn,\r
2449             t,\r
2450             s;\r
2451 \r
2452         try {\r
2453             headerStr = o.conn.getAllResponseHeaders();   \r
2454             Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'), function(v){\r
2455                 t = v.indexOf(':');\r
2456                 if(t >= 0){\r
2457                     s = v.substr(0, t).toLowerCase();\r
2458                     if(v.charAt(t + 1) == ' '){\r
2459                         ++t;\r
2460                     }\r
2461                     headerObj[s] = v.substr(t + 1);\r
2462                 }\r
2463             });\r
2464         } catch(e) {}\r
2465                     \r
2466         return {\r
2467             tId : o.tId,\r
2468             status : conn.status,\r
2469             statusText : conn.statusText,\r
2470             getResponseHeader : function(header){return headerObj[header.toLowerCase()];},\r
2471             getAllResponseHeaders : function(){return headerStr},\r
2472             responseText : conn.responseText,\r
2473             responseXML : conn.responseXML,\r
2474             argument : callbackArg\r
2475         };\r
2476     }\r
2477     \r
2478     // private\r
2479     function releaseObject(o) {\r
2480         o.conn = null;\r
2481         o = null;\r
2482     }        \r
2483     \r
2484     // private\r
2485     function handleTransactionResponse(o, callback, isAbort, isTimeout) {\r
2486         if (!callback) {\r
2487             releaseObject(o);\r
2488             return;\r
2489         }\r
2490 \r
2491         var httpStatus, responseObject;\r
2492 \r
2493         try {\r
2494             if (o.conn.status !== undefined && o.conn.status != 0) {\r
2495                 httpStatus = o.conn.status;\r
2496             }\r
2497             else {\r
2498                 httpStatus = 13030;\r
2499             }\r
2500         }\r
2501         catch(e) {\r
2502             httpStatus = 13030;\r
2503         }\r
2504 \r
2505         if ((httpStatus >= 200 && httpStatus < 300) || (Ext.isIE && httpStatus == 1223)) {\r
2506             responseObject = createResponseObject(o, callback.argument);\r
2507             if (callback.success) {\r
2508                 if (!callback.scope) {\r
2509                     callback.success(responseObject);\r
2510                 }\r
2511                 else {\r
2512                     callback.success.apply(callback.scope, [responseObject]);\r
2513                 }\r
2514             }\r
2515         }\r
2516         else {\r
2517             switch (httpStatus) {\r
2518                 case 12002:\r
2519                 case 12029:\r
2520                 case 12030:\r
2521                 case 12031:\r
2522                 case 12152:\r
2523                 case 13030:\r
2524                     responseObject = createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false), isTimeout);\r
2525                     if (callback.failure) {\r
2526                         if (!callback.scope) {\r
2527                             callback.failure(responseObject);\r
2528                         }\r
2529                         else {\r
2530                             callback.failure.apply(callback.scope, [responseObject]);\r
2531                         }\r
2532                     }\r
2533                     break;\r
2534                 default:\r
2535                     responseObject = createResponseObject(o, callback.argument);\r
2536                     if (callback.failure) {\r
2537                         if (!callback.scope) {\r
2538                             callback.failure(responseObject);\r
2539                         }\r
2540                         else {\r
2541                             callback.failure.apply(callback.scope, [responseObject]);\r
2542                         }\r
2543                     }\r
2544             }\r
2545         }\r
2546 \r
2547         releaseObject(o);\r
2548         responseObject = null;\r
2549     }  \r
2550     \r
2551     // private\r
2552     function handleReadyState(o, callback){\r
2553     callback = callback || {};\r
2554         var conn = o.conn,\r
2555             tId = o.tId,\r
2556             poll = pub.poll,\r
2557             cbTimeout = callback.timeout || null;\r
2558 \r
2559         if (cbTimeout) {\r
2560             pub.timeout[tId] = setTimeout(function() {\r
2561                 pub.abort(o, callback, true);\r
2562             }, cbTimeout);\r
2563         }\r
2564 \r
2565         poll[tId] = setInterval(\r
2566             function() {\r
2567                 if (conn && conn.readyState == 4) {\r
2568                     clearInterval(poll[tId]);\r
2569                     poll[tId] = null;\r
2570 \r
2571                     if (cbTimeout) {\r
2572                         clearTimeout(pub.timeout[tId]);\r
2573                         pub.timeout[tId] = null;\r
2574                     }\r
2575 \r
2576                     handleTransactionResponse(o, callback);\r
2577                 }\r
2578             },\r
2579             pub.pollInterval);\r
2580     }\r
2581     \r
2582     // private\r
2583     function asyncRequest(method, uri, callback, postData) {\r
2584         var o = getConnectionObject() || null;\r
2585 \r
2586         if (o) {\r
2587             o.conn.open(method, uri, true);\r
2588 \r
2589             if (pub.useDefaultXhrHeader) {                    \r
2590                 initHeader('X-Requested-With', pub.defaultXhrHeader);\r
2591             }\r
2592 \r
2593             if(postData && pub.useDefaultHeader && (!pub.headers || !pub.headers[CONTENTTYPE])){\r
2594                 initHeader(CONTENTTYPE, pub.defaultPostHeader);\r
2595             }\r
2596 \r
2597             if (pub.defaultHeaders || pub.headers) {\r
2598                 setHeader(o);\r
2599             }\r
2600 \r
2601             handleReadyState(o, callback);\r
2602             o.conn.send(postData || null);\r
2603         }\r
2604         return o;\r
2605     }\r
2606     \r
2607     // private\r
2608     function getConnectionObject() {\r
2609         var o;          \r
2610 \r
2611         try {\r
2612             if (o = createXhrObject(pub.transactionId)) {\r
2613                 pub.transactionId++;\r
2614             }\r
2615         } catch(e) {\r
2616         } finally {\r
2617             return o;\r
2618         }\r
2619     }\r
2620        \r
2621     // private\r
2622     function createXhrObject(transactionId) {\r
2623         var http;\r
2624             \r
2625         try {\r
2626             http = new XMLHttpRequest();                \r
2627         } catch(e) {\r
2628             for (var i = 0; i < activeX.length; ++i) {              \r
2629                 try {\r
2630                     http = new ActiveXObject(activeX[i]);                        \r
2631                     break;\r
2632                 } catch(e) {}\r
2633             }\r
2634         } finally {\r
2635             return {conn : http, tId : transactionId};\r
2636         }\r
2637     }\r
2638          \r
2639     var pub = {\r
2640         request : function(method, uri, cb, data, options) {\r
2641             if(options){\r
2642                 var me = this,              \r
2643                     xmlData = options.xmlData,\r
2644                     jsonData = options.jsonData,\r
2645                     hs;\r
2646                     \r
2647                 Ext.applyIf(me, options);           \r
2648                 \r
2649                 if(xmlData || jsonData){\r
2650                     hs = me.headers;\r
2651                     if(!hs || !hs[CONTENTTYPE]){\r
2652                         initHeader(CONTENTTYPE, xmlData ? 'text/xml' : 'application/json');\r
2653                     }\r
2654                     data = xmlData || (!Ext.isPrimitive(jsonData) ? Ext.encode(jsonData) : jsonData);\r
2655                 }\r
2656             }                       \r
2657             return asyncRequest(method || options.method || "POST", uri, cb, data);\r
2658         },\r
2659 \r
2660         serializeForm : function(form) {\r
2661             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,\r
2662                 hasSubmit = false,\r
2663                 encoder = encodeURIComponent,\r
2664                 element,\r
2665                 options, \r
2666                 name, \r
2667                 val,                \r
2668                 data = '',\r
2669                 type;\r
2670                 \r
2671             Ext.each(fElements, function(element) {                 \r
2672                 name = element.name;                 \r
2673                 type = element.type;\r
2674                 \r
2675                 if (!element.disabled && name){\r
2676                     if(/select-(one|multiple)/i.test(type)) {\r
2677                         Ext.each(element.options, function(opt) {\r
2678                             if (opt.selected) {\r
2679                                 data += String.format("{0}={1}&", encoder(name), encoder((opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttribute('value') !== null) ? opt.value : opt.text));\r
2680                             }                               \r
2681                         });\r
2682                     } else if(!/file|undefined|reset|button/i.test(type)) {\r
2683                             if(!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)){\r
2684                                 \r
2685                                 data += encoder(name) + '=' + encoder(element.value) + '&';                     \r
2686                                 hasSubmit = /submit/i.test(type);    \r
2687                             }                       \r
2688                     } \r
2689                 }\r
2690             });            \r
2691             return data.substr(0, data.length - 1);\r
2692         },\r
2693         \r
2694         useDefaultHeader : true,\r
2695         defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',\r
2696         useDefaultXhrHeader : true,\r
2697         defaultXhrHeader : 'XMLHttpRequest',        \r
2698         poll : {},\r
2699         timeout : {},\r
2700         pollInterval : 50,\r
2701         transactionId : 0,\r
2702         \r
2703 //  This is never called - Is it worth exposing this?               \r
2704 //          setProgId : function(id) {\r
2705 //              activeX.unshift(id);\r
2706 //          },\r
2707 \r
2708 //  This is never called - Is it worth exposing this?   \r
2709 //          setDefaultPostHeader : function(b) {\r
2710 //              this.useDefaultHeader = b;\r
2711 //          },\r
2712         \r
2713 //  This is never called - Is it worth exposing this?   \r
2714 //          setDefaultXhrHeader : function(b) {\r
2715 //              this.useDefaultXhrHeader = b;\r
2716 //          },\r
2717 \r
2718 //  This is never called - Is it worth exposing this?           \r
2719 //          setPollingInterval : function(i) {\r
2720 //              if (typeof i == 'number' && isFinite(i)) {\r
2721 //                  this.pollInterval = i;\r
2722 //              }\r
2723 //          },\r
2724         \r
2725 //  This is never called - Is it worth exposing this?\r
2726 //          resetDefaultHeaders : function() {\r
2727 //              this.defaultHeaders = null;\r
2728 //          },\r
2729     \r
2730             abort : function(o, callback, isTimeout) {\r
2731                 var me = this,\r
2732                     tId = o.tId,\r
2733                     isAbort = false;\r
2734                 \r
2735                 if (me.isCallInProgress(o)) {\r
2736                     o.conn.abort();\r
2737                     clearInterval(me.poll[tId]);\r
2738                     me.poll[tId] = null;\r
2739                     clearTimeout(pub.timeout[tId]);\r
2740                     me.timeout[tId] = null;\r
2741                     \r
2742                     handleTransactionResponse(o, callback, (isAbort = true), isTimeout);                \r
2743                 }\r
2744                 return isAbort;\r
2745             },\r
2746     \r
2747             isCallInProgress : function(o) {\r
2748                 // if there is a connection and readyState is not 0 or 4\r
2749                 return o.conn && !{0:true,4:true}[o.conn.readyState];           \r
2750             }\r
2751         };\r
2752         return pub;\r
2753     }();        Ext.lib.Region = function(t, r, b, l) {\r
2754                 var me = this;\r
2755         me.top = t;\r
2756         me[1] = t;\r
2757         me.right = r;\r
2758         me.bottom = b;\r
2759         me.left = l;\r
2760         me[0] = l;\r
2761     };\r
2762 \r
2763     Ext.lib.Region.prototype = {\r
2764         contains : function(region) {\r
2765                 var me = this;\r
2766             return ( region.left >= me.left &&\r
2767                      region.right <= me.right &&\r
2768                      region.top >= me.top &&\r
2769                      region.bottom <= me.bottom );\r
2770 \r
2771         },\r
2772 \r
2773         getArea : function() {\r
2774                 var me = this;\r
2775             return ( (me.bottom - me.top) * (me.right - me.left) );\r
2776         },\r
2777 \r
2778         intersect : function(region) {\r
2779             var me = this,\r
2780                 t = Math.max(me.top, region.top),\r
2781                 r = Math.min(me.right, region.right),\r
2782                 b = Math.min(me.bottom, region.bottom),\r
2783                 l = Math.max(me.left, region.left);\r
2784 \r
2785             if (b >= t && r >= l) {\r
2786                 return new Ext.lib.Region(t, r, b, l);\r
2787             }\r
2788         },\r
2789         \r
2790         union : function(region) {\r
2791                 var me = this,\r
2792                 t = Math.min(me.top, region.top),\r
2793                 r = Math.max(me.right, region.right),\r
2794                 b = Math.max(me.bottom, region.bottom),\r
2795                 l = Math.min(me.left, region.left);\r
2796 \r
2797             return new Ext.lib.Region(t, r, b, l);\r
2798         },\r
2799 \r
2800         constrainTo : function(r) {\r
2801                 var me = this;\r
2802             me.top = me.top.constrain(r.top, r.bottom);\r
2803             me.bottom = me.bottom.constrain(r.top, r.bottom);\r
2804             me.left = me.left.constrain(r.left, r.right);\r
2805             me.right = me.right.constrain(r.left, r.right);\r
2806             return me;\r
2807         },\r
2808 \r
2809         adjust : function(t, l, b, r) {\r
2810                 var me = this;\r
2811             me.top += t;\r
2812             me.left += l;\r
2813             me.right += r;\r
2814             me.bottom += b;\r
2815             return me;\r
2816         }\r
2817     };\r
2818 \r
2819     Ext.lib.Region.getRegion = function(el) {\r
2820         var p = Ext.lib.Dom.getXY(el),\r
2821                 t = p[1],\r
2822                 r = p[0] + el.offsetWidth,\r
2823                 b = p[1] + el.offsetHeight,\r
2824                 l = p[0];\r
2825 \r
2826         return new Ext.lib.Region(t, r, b, l);\r
2827     };  Ext.lib.Point = function(x, y) {\r
2828         if (Ext.isArray(x)) {\r
2829             y = x[1];\r
2830             x = x[0];\r
2831         }\r
2832         var me = this;\r
2833         me.x = me.right = me.left = me[0] = x;\r
2834         me.y = me.top = me.bottom = me[1] = y;\r
2835     };\r
2836 \r
2837     Ext.lib.Point.prototype = new Ext.lib.Region();\r
2838 (function(){    \r
2839     var EXTLIB = Ext.lib,\r
2840         noNegatives = /width|height|opacity|padding/i,\r
2841         offsetAttribute = /^((width|height)|(top|left))$/,\r
2842         defaultUnit = /width|height|top$|bottom$|left$|right$/i,\r
2843         offsetUnit =  /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,\r
2844         isset = function(v){\r
2845             return typeof v !== 'undefined';\r
2846         },\r
2847         now = function(){\r
2848             return new Date();    \r
2849         };\r
2850         \r
2851     EXTLIB.Anim = {\r
2852         motion : function(el, args, duration, easing, cb, scope) {\r
2853             return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);\r
2854         },\r
2855 \r
2856         run : function(el, args, duration, easing, cb, scope, type) {\r
2857             type = type || Ext.lib.AnimBase;\r
2858             if (typeof easing == "string") {\r
2859                 easing = Ext.lib.Easing[easing];\r
2860             }\r
2861             var anim = new type(el, args, duration, easing);\r
2862             anim.animateX(function() {\r
2863                 if(Ext.isFunction(cb)){\r
2864                     cb.call(scope);\r
2865                 }\r
2866             });\r
2867             return anim;\r
2868         }\r
2869     };\r
2870     \r
2871     EXTLIB.AnimBase = function(el, attributes, duration, method) {\r
2872         if (el) {\r
2873             this.init(el, attributes, duration, method);\r
2874         }\r
2875     };\r
2876 \r
2877     EXTLIB.AnimBase.prototype = {\r
2878         doMethod: function(attr, start, end) {\r
2879             var me = this;\r
2880             return me.method(me.curFrame, start, end - start, me.totalFrames);\r
2881         },\r
2882 \r
2883 \r
2884         setAttr: function(attr, val, unit) {\r
2885             if (noNegatives.test(attr) && val < 0) {\r
2886                 val = 0;\r
2887             }\r
2888             Ext.fly(this.el, '_anim').setStyle(attr, val + unit);\r
2889         },\r
2890 \r
2891 \r
2892         getAttr: function(attr) {\r
2893             var el = Ext.fly(this.el),\r
2894                 val = el.getStyle(attr),\r
2895                 a = offsetAttribute.exec(attr) || []\r
2896 \r
2897             if (val !== 'auto' && !offsetUnit.test(val)) {\r
2898                 return parseFloat(val);\r
2899             }\r
2900 \r
2901             return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;\r
2902         },\r
2903 \r
2904 \r
2905         getDefaultUnit: function(attr) {\r
2906             return defaultUnit.test(attr) ? 'px' : '';\r
2907         },\r
2908 \r
2909         animateX : function(callback, scope) {\r
2910             var me = this,\r
2911                 f = function() {\r
2912                 me.onComplete.removeListener(f);\r
2913                 if (Ext.isFunction(callback)) {\r
2914                     callback.call(scope || me, me);\r
2915                 }\r
2916             };\r
2917             me.onComplete.addListener(f, me);\r
2918             me.animate();\r
2919         },\r
2920 \r
2921 \r
2922         setRunAttr: function(attr) {            \r
2923             var me = this,\r
2924                 a = this.attributes[attr],\r
2925                 to = a.to,\r
2926                 by = a.by,\r
2927                 from = a.from,\r
2928                 unit = a.unit,\r
2929                 ra = (this.runAttrs[attr] = {}),\r
2930                 end;\r
2931 \r
2932             if (!isset(to) && !isset(by)){\r
2933                 return false;\r
2934             }\r
2935 \r
2936             var start = isset(from) ? from : me.getAttr(attr);\r
2937             if (isset(to)) {\r
2938                 end = to;\r
2939             }else if(isset(by)) {\r
2940                 if (Ext.isArray(start)){\r
2941                     end = [];\r
2942                                         for(var i=0,len=start.length; i<len; i++) {\r
2943                                                 end[i] = start[i] + by[i];\r
2944                                         }\r
2945                 }else{\r
2946                     end = start + by;\r
2947                 }\r
2948             }\r
2949 \r
2950             Ext.apply(ra, {\r
2951                 start: start,\r
2952                 end: end,\r
2953                 unit: isset(unit) ? unit : me.getDefaultUnit(attr)\r
2954             });\r
2955         },\r
2956 \r
2957 \r
2958         init: function(el, attributes, duration, method) {\r
2959             var me = this,\r
2960                 actualFrames = 0,\r
2961                 mgr = EXTLIB.AnimMgr;\r
2962                 \r
2963             Ext.apply(me, {\r
2964                 isAnimated: false,\r
2965                 startTime: null,\r
2966                 el: Ext.getDom(el),\r
2967                 attributes: attributes || {},\r
2968                 duration: duration || 1,\r
2969                 method: method || EXTLIB.Easing.easeNone,\r
2970                 useSec: true,\r
2971                 curFrame: 0,\r
2972                 totalFrames: mgr.fps,\r
2973                 runAttrs: {},\r
2974                 animate: function(){\r
2975                     var me = this,\r
2976                         d = me.duration;\r
2977                     \r
2978                     if(me.isAnimated){\r
2979                         return false;\r
2980                     }\r
2981 \r
2982                     me.curFrame = 0;\r
2983                     me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;\r
2984                     mgr.registerElement(me); \r
2985                 },\r
2986                 \r
2987                 stop: function(finish){\r
2988                     var me = this;\r
2989                 \r
2990                     if(finish){\r
2991                         me.curFrame = me.totalFrames;\r
2992                         me._onTween.fire();\r
2993                     }\r
2994                     mgr.stop(me);\r
2995                 }\r
2996             });\r
2997 \r
2998             var onStart = function(){\r
2999                 var me = this,\r
3000                     attr;\r
3001                 \r
3002                 me.onStart.fire();\r
3003                 me.runAttrs = {};\r
3004                 for(attr in this.attributes){\r
3005                     this.setRunAttr(attr);\r
3006                 }\r
3007 \r
3008                 me.isAnimated = true;\r
3009                 me.startTime = now();\r
3010                 actualFrames = 0;\r
3011             };\r
3012 \r
3013 \r
3014             var onTween = function(){\r
3015                 var me = this;\r
3016 \r
3017                 me.onTween.fire({\r
3018                     duration: now() - me.startTime,\r
3019                     curFrame: me.curFrame\r
3020                 });\r
3021 \r
3022                 var ra = me.runAttrs;\r
3023                 for (var attr in ra) {\r
3024                     this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);\r
3025                 }\r
3026 \r
3027                 ++actualFrames;\r
3028             };\r
3029 \r
3030             var onComplete = function() {\r
3031                 var me = this,\r
3032                     actual = (now() - me.startTime) / 1000,\r
3033                     data = {\r
3034                         duration: actual,\r
3035                         frames: actualFrames,\r
3036                         fps: actualFrames / actual\r
3037                     };\r
3038 \r
3039                 me.isAnimated = false;\r
3040                 actualFrames = 0;\r
3041                 me.onComplete.fire(data);\r
3042             };\r
3043 \r
3044             me.onStart = new Ext.util.Event(me);\r
3045             me.onTween = new Ext.util.Event(me);            \r
3046             me.onComplete = new Ext.util.Event(me);\r
3047             (me._onStart = new Ext.util.Event(me)).addListener(onStart);\r
3048             (me._onTween = new Ext.util.Event(me)).addListener(onTween);\r
3049             (me._onComplete = new Ext.util.Event(me)).addListener(onComplete); \r
3050         }\r
3051     };\r
3052 \r
3053 \r
3054     Ext.lib.AnimMgr = new function() {\r
3055         var me = this,\r
3056             thread = null,\r
3057             queue = [],\r
3058             tweenCount = 0;\r
3059 \r
3060 \r
3061         Ext.apply(me, {\r
3062             fps: 1000,\r
3063             delay: 1,\r
3064             registerElement: function(tween){\r
3065                 queue.push(tween);\r
3066                 ++tweenCount;\r
3067                 tween._onStart.fire();\r
3068                 me.start();\r
3069             },\r
3070             \r
3071             unRegister: function(tween, index){\r
3072                 tween._onComplete.fire();\r
3073                 index = index || getIndex(tween);\r
3074                 if (index != -1) {\r
3075                     queue.splice(index, 1);\r
3076                 }\r
3077 \r
3078                 if (--tweenCount <= 0) {\r
3079                     me.stop();\r
3080                 }\r
3081             },\r
3082             \r
3083             start: function(){\r
3084                 if(thread === null){\r
3085                     thread = setInterval(me.run, me.delay);\r
3086                 }\r
3087             },\r
3088             \r
3089             stop: function(tween){\r
3090                 if(!tween){\r
3091                     clearInterval(thread);\r
3092                     for(var i = 0, len = queue.length; i < len; ++i){\r
3093                         if(queue[0].isAnimated){\r
3094                             me.unRegister(queue[0], 0);\r
3095                         }\r
3096                     }\r
3097 \r
3098                     queue = [];\r
3099                     thread = null;\r
3100                     tweenCount = 0;\r
3101                 }else{\r
3102                     me.unRegister(tween);\r
3103                 }\r
3104             },\r
3105             \r
3106             run: function(){\r
3107                 var tf, i, len, tween;\r
3108                 for(i = 0, len = queue.length; i<len; i++) {\r
3109                     tween = queue[i];\r
3110                     if(tween && tween.isAnimated){\r
3111                         tf = tween.totalFrames;\r
3112                         if(tween.curFrame < tf || tf === null){\r
3113                             ++tween.curFrame;\r
3114                             if(tween.useSec){\r
3115                                 correctFrame(tween);\r
3116                             }\r
3117                             tween._onTween.fire();\r
3118                         }else{\r
3119                             me.stop(tween);\r
3120                         }\r
3121                     }                   \r
3122                 }\r
3123             }\r
3124         });\r
3125 \r
3126         var getIndex = function(anim) {\r
3127             var i, len;\r
3128             for(i = 0, len = queue.length; i<len; i++) {\r
3129                 if(queue[i] === anim) {\r
3130                     return i;\r
3131                 }\r
3132             }\r
3133             return -1;\r
3134         };\r
3135 \r
3136         var correctFrame = function(tween) {\r
3137             var frames = tween.totalFrames,\r
3138                 frame = tween.curFrame,\r
3139                 duration = tween.duration,\r
3140                 expected = (frame * duration * 1000 / frames),\r
3141                 elapsed = (now() - tween.startTime),\r
3142                 tweak = 0;\r
3143 \r
3144             if(elapsed < duration * 1000){\r
3145                 tweak = Math.round((elapsed / expected - 1) * frame);\r
3146             }else{\r
3147                 tweak = frames - (frame + 1);\r
3148             }\r
3149             if(tweak > 0 && isFinite(tweak)){\r
3150                 if(tween.curFrame + tweak >= frames){\r
3151                     tweak = frames - (frame + 1);\r
3152                 }\r
3153                 tween.curFrame += tweak;\r
3154             }\r
3155         };\r
3156     };\r
3157 \r
3158     EXTLIB.Bezier = new function() {\r
3159 \r
3160         this.getPosition = function(points, t) {\r
3161             var n = points.length,\r
3162                 tmp = [],\r
3163                 c = 1 - t, \r
3164                 i,\r
3165                 j;\r
3166 \r
3167             for (i = 0; i < n; ++i) {\r
3168                 tmp[i] = [points[i][0], points[i][1]];\r
3169             }\r
3170 \r
3171             for (j = 1; j < n; ++j) {\r
3172                 for (i = 0; i < n - j; ++i) {\r
3173                     tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];\r
3174                     tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];\r
3175                 }\r
3176             }\r
3177 \r
3178             return [ tmp[0][0], tmp[0][1] ];\r
3179 \r
3180         };\r
3181     };\r
3182 \r
3183 \r
3184     EXTLIB.Easing = {\r
3185         easeNone: function (t, b, c, d) {\r
3186             return c * t / d + b;\r
3187         },\r
3188 \r
3189 \r
3190         easeIn: function (t, b, c, d) {\r
3191             return c * (t /= d) * t + b;\r
3192         },\r
3193 \r
3194 \r
3195         easeOut: function (t, b, c, d) {\r
3196             return -c * (t /= d) * (t - 2) + b;\r
3197         }\r
3198     };\r
3199 \r
3200     (function() {\r
3201         EXTLIB.Motion = function(el, attributes, duration, method) {\r
3202             if (el) {\r
3203                 EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);\r
3204             }\r
3205         };\r
3206 \r
3207         Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);\r
3208 \r
3209         var superclass = EXTLIB.Motion.superclass,\r
3210             proto = EXTLIB.Motion.prototype,\r
3211             pointsRe = /^points$/i;\r
3212 \r
3213         Ext.apply(EXTLIB.Motion.prototype, {\r
3214             setAttr: function(attr, val, unit){\r
3215                 var me = this,\r
3216                     setAttr = superclass.setAttr;\r
3217                     \r
3218                 if (pointsRe.test(attr)) {\r
3219                     unit = unit || 'px';\r
3220                     setAttr.call(me, 'left', val[0], unit);\r
3221                     setAttr.call(me, 'top', val[1], unit);\r
3222                 } else {\r
3223                     setAttr.call(me, attr, val, unit);\r
3224                 }\r
3225             },\r
3226             \r
3227             getAttr: function(attr){\r
3228                 var me = this,\r
3229                     getAttr = superclass.getAttr;\r
3230                     \r
3231                 return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);\r
3232             },\r
3233             \r
3234             doMethod: function(attr, start, end){\r
3235                 var me = this;\r
3236                 \r
3237                 return pointsRe.test(attr)\r
3238                         ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)\r
3239                         : superclass.doMethod.call(me, attr, start, end);\r
3240             },\r
3241             \r
3242             setRunAttr: function(attr){\r
3243                 if(pointsRe.test(attr)){\r
3244                     \r
3245                     var me = this,\r
3246                         el = this.el,\r
3247                         points = this.attributes.points,\r
3248                         control = points.control || [],\r
3249                         from = points.from,\r
3250                         to = points.to,\r
3251                         by = points.by,\r
3252                         DOM = EXTLIB.Dom,\r
3253                         start,\r
3254                         i,\r
3255                         end,\r
3256                         len,\r
3257                         ra;\r
3258                   \r
3259 \r
3260                     if(control.length > 0 && !Ext.isArray(control[0])){\r
3261                         control = [control];\r
3262                     }else{\r
3263                         /*\r
3264                         var tmp = [];\r
3265                         for (i = 0,len = control.length; i < len; ++i) {\r
3266                             tmp[i] = control[i];\r
3267                         }\r
3268                         control = tmp;\r
3269                         */\r
3270                     }\r
3271 \r
3272                     Ext.fly(el, '_anim').position();\r
3273                     DOM.setXY(el, isset(from) ? from : DOM.getXY(el));\r
3274                     start = me.getAttr('points');\r
3275 \r
3276 \r
3277                     if(isset(to)){\r
3278                         end = translateValues.call(me, to, start);\r
3279                         for (i = 0,len = control.length; i < len; ++i) {\r
3280                             control[i] = translateValues.call(me, control[i], start);\r
3281                         }\r
3282                     } else if (isset(by)) {\r
3283                         end = [start[0] + by[0], start[1] + by[1]];\r
3284 \r
3285                         for (i = 0,len = control.length; i < len; ++i) {\r
3286                             control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];\r
3287                         }\r
3288                     }\r
3289 \r
3290                     ra = this.runAttrs[attr] = [start];\r
3291                     if (control.length > 0) {\r
3292                         ra = ra.concat(control);\r
3293                     }\r
3294 \r
3295                     ra[ra.length] = end;\r
3296                 }else{\r
3297                     superclass.setRunAttr.call(this, attr);\r
3298                 }\r
3299             }\r
3300         });\r
3301 \r
3302         var translateValues = function(val, start) {\r
3303             var pageXY = EXTLIB.Dom.getXY(this.el);\r
3304             return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];\r
3305         };\r
3306     })();\r
3307 })();// Easing functions\r
3308 (function(){\r
3309         // shortcuts to aid compression\r
3310         var abs = Math.abs,\r
3311                 pi = Math.PI,\r
3312                 asin = Math.asin,\r
3313                 pow = Math.pow,\r
3314                 sin = Math.sin,\r
3315                 EXTLIB = Ext.lib;\r
3316                 \r
3317     Ext.apply(EXTLIB.Easing, {\r
3318         \r
3319         easeBoth: function (t, b, c, d) {\r
3320                 return ((t /= d / 2) < 1)  ?  c / 2 * t * t + b  :  -c / 2 * ((--t) * (t - 2) - 1) + b;               \r
3321         },\r
3322         \r
3323         easeInStrong: function (t, b, c, d) {\r
3324             return c * (t /= d) * t * t * t + b;\r
3325         },\r
3326 \r
3327         easeOutStrong: function (t, b, c, d) {\r
3328             return -c * ((t = t / d - 1) * t * t * t - 1) + b;\r
3329         },\r
3330 \r
3331         easeBothStrong: function (t, b, c, d) {\r
3332             return ((t /= d / 2) < 1)  ?  c / 2 * t * t * t * t + b  :  -c / 2 * ((t -= 2) * t * t * t - 2) + b;\r
3333         },\r
3334 \r
3335         elasticIn: function (t, b, c, d, a, p) {\r
3336                 if (t == 0 || (t /= d) == 1) {\r
3337                 return t == 0 ? b : b + c;\r
3338             }               \r
3339             p = p || (d * .3);              \r
3340 \r
3341                         var s;\r
3342                         if (a >= abs(c)) {\r
3343                                 s = p / (2 * pi) * asin(c / a);\r
3344                         } else {\r
3345                                 a = c;\r
3346                                 s = p / 4;\r
3347                         }\r
3348         \r
3349             return -(a * pow(2, 10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b;\r
3350                       \r
3351         },      \r
3352         \r
3353                 elasticOut: function (t, b, c, d, a, p) {\r
3354                 if (t == 0 || (t /= d) == 1) {\r
3355                 return t == 0 ? b : b + c;\r
3356             }               \r
3357             p = p || (d * .3);              \r
3358 \r
3359                         var s;\r
3360                         if (a >= abs(c)) {\r
3361                                 s = p / (2 * pi) * asin(c / a);\r
3362                         } else {\r
3363                                 a = c;\r
3364                                 s = p / 4;\r
3365                         }\r
3366         \r
3367             return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b;        \r
3368         },      \r
3369         \r
3370         elasticBoth: function (t, b, c, d, a, p) {\r
3371             if (t == 0 || (t /= d / 2) == 2) {\r
3372                 return t == 0 ? b : b + c;\r
3373             }                           \r
3374                     \r
3375             p = p || (d * (.3 * 1.5));              \r
3376 \r
3377             var s;\r
3378             if (a >= abs(c)) {\r
3379                     s = p / (2 * pi) * asin(c / a);\r
3380             } else {\r
3381                     a = c;\r
3382                 s = p / 4;\r
3383             }\r
3384 \r
3385             return t < 1 ?\r
3386                         -.5 * (a * pow(2, 10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b :\r
3387                     a * pow(2, -10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p) * .5 + c + b;\r
3388         },\r
3389 \r
3390         backIn: function (t, b, c, d, s) {\r
3391             s = s ||  1.70158;              \r
3392             return c * (t /= d) * t * ((s + 1) * t - s) + b;\r
3393         },\r
3394 \r
3395 \r
3396         backOut: function (t, b, c, d, s) {\r
3397             if (!s) {\r
3398                 s = 1.70158;\r
3399             }\r
3400             return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;\r
3401         },\r
3402 \r
3403 \r
3404         backBoth: function (t, b, c, d, s) {\r
3405             s = s || 1.70158;               \r
3406 \r
3407             return ((t /= d / 2 ) < 1) ?\r
3408                     c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b :                  \r
3409                         c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;\r
3410         },\r
3411 \r
3412 \r
3413         bounceIn: function (t, b, c, d) {\r
3414             return c - EXTLIB.Easing.bounceOut(d - t, 0, c, d) + b;\r
3415         },\r
3416 \r
3417 \r
3418         bounceOut: function (t, b, c, d) {\r
3419         if ((t /= d) < (1 / 2.75)) {\r
3420                 return c * (7.5625 * t * t) + b;\r
3421             } else if (t < (2 / 2.75)) {\r
3422                 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;\r
3423             } else if (t < (2.5 / 2.75)) {\r
3424                 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;\r
3425             }\r
3426             return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;\r
3427         },\r
3428 \r
3429 \r
3430         bounceBoth: function (t, b, c, d) {\r
3431             return (t < d / 2) ?\r
3432                    EXTLIB.Easing.bounceIn(t * 2, 0, c, d) * .5 + b : \r
3433                    EXTLIB.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;\r
3434         }\r
3435     });\r
3436 })();\r
3437 \r
3438 (function() {\r
3439     var EXTLIB = Ext.lib;\r
3440         // Color Animation\r
3441         EXTLIB.Anim.color = function(el, args, duration, easing, cb, scope) {\r
3442             return EXTLIB.Anim.run(el, args, duration, easing, cb, scope, EXTLIB.ColorAnim);\r
3443         }\r
3444         \r
3445     EXTLIB.ColorAnim = function(el, attributes, duration, method) {\r
3446         EXTLIB.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);\r
3447     };\r
3448 \r
3449     Ext.extend(EXTLIB.ColorAnim, EXTLIB.AnimBase);\r
3450 \r
3451     var superclass = EXTLIB.ColorAnim.superclass,\r
3452         colorRE = /color$/i,\r
3453         transparentRE = /^transparent|rgba\(0, 0, 0, 0\)$/,\r
3454         rgbRE = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,\r
3455         hexRE= /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,\r
3456         hex3RE = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,\r
3457         isset = function(v){\r
3458             return typeof v !== 'undefined';\r
3459         }\r
3460                 \r
3461         // private      \r
3462     function parseColor(s) {    \r
3463         var pi = parseInt,\r
3464             base,\r
3465             out = null,\r
3466             c;\r
3467         \r
3468             if (s.length == 3) {\r
3469             return s;\r
3470         }\r
3471                 \r
3472         Ext.each([hexRE, rgbRE, hex3RE], function(re, idx){\r
3473             base = (idx % 2 == 0) ? 16 : 10;\r
3474             c = re.exec(s);\r
3475             if(c && c.length == 4){\r
3476                 out = [pi(c[1], base), pi(c[2], base), pi(c[3], base)];\r
3477                 return false;\r
3478             }\r
3479         });\r
3480         return out;\r
3481     }   \r
3482 \r
3483     Ext.apply(EXTLIB.ColorAnim.prototype, {\r
3484         getAttr : function(attr) {\r
3485             var me = this,\r
3486                 el = me.el,\r
3487                 val;                \r
3488             if(colorRE.test(attr)){\r
3489                 while(el && transparentRE.test(val = Ext.fly(el).getStyle(attr))){\r
3490                     el = el.parentNode;\r
3491                     val = "fff";\r
3492                 }\r
3493             }else{\r
3494                 val = superclass.getAttr.call(me, attr);\r
3495             }\r
3496             return val;\r
3497         },\r
3498 \r
3499         doMethod : function(attr, start, end) {\r
3500             var me = this,\r
3501                 val,\r
3502                 floor = Math.floor,\r
3503                                 i, \r
3504                 len,\r
3505                 v;            \r
3506 \r
3507             if(colorRE.test(attr)){\r
3508                 val = [];\r
3509                                 \r
3510                                 for(i = 0, len = start.length; i < len; i++) {\r
3511                                         v = start[i];\r
3512                                         val[i] = superclass.doMethod.call(me, attr, v, end[i]);\r
3513                                 }\r
3514                 val = 'rgb(' + floor(val[0]) + ',' + floor(val[1]) + ',' + floor(val[2]) + ')';\r
3515             }else{\r
3516                 val = superclass.doMethod.call(me, attr, start, end);\r
3517             }\r
3518             return val;\r
3519         },\r
3520 \r
3521         setRunAttr : function(attr) {\r
3522             var me = this,\r
3523                 a = me.attributes[attr],\r
3524                 to = a.to,\r
3525                 by = a.by,\r
3526                 ra;\r
3527                 \r
3528             superclass.setRunAttr.call(me, attr);\r
3529             ra = me.runAttrs[attr];\r
3530             if(colorRE.test(attr)){\r
3531                 var start = parseColor(ra.start),\r
3532                     end = parseColor(ra.end);\r
3533 \r
3534                 if(!isset(to) && isset(by)){\r
3535                     end = parseColor(by);\r
3536                                         for(var i=0,len=start.length; i<len; i++) {\r
3537                                                 end[i] = start[i] + end[i];\r
3538                                         }\r
3539                 }\r
3540                 ra.start = start;\r
3541                 ra.end = end;\r
3542             }\r
3543         }\r
3544         });\r
3545 })();   \r
3546 \r
3547         \r
3548 (function() {\r
3549             // Scroll Animation \r
3550     var EXTLIB = Ext.lib;\r
3551         EXTLIB.Anim.scroll = function(el, args, duration, easing, cb, scope) {          \r
3552             return EXTLIB.Anim.run(el, args, duration, easing, cb, scope, EXTLIB.Scroll);\r
3553         }\r
3554         \r
3555     EXTLIB.Scroll = function(el, attributes, duration, method) {\r
3556         if(el){\r
3557             EXTLIB.Scroll.superclass.constructor.call(this, el, attributes, duration, method);\r
3558         }\r
3559     };\r
3560 \r
3561     Ext.extend(EXTLIB.Scroll, EXTLIB.ColorAnim);\r
3562 \r
3563     var superclass = EXTLIB.Scroll.superclass,\r
3564         SCROLL = 'scroll';\r
3565 \r
3566     Ext.apply(EXTLIB.Scroll.prototype, {\r
3567 \r
3568         doMethod : function(attr, start, end) {\r
3569             var val,\r
3570                 me = this,\r
3571                 curFrame = me.curFrame,\r
3572                 totalFrames = me.totalFrames;\r
3573 \r
3574             if(attr == SCROLL){\r
3575                 val = [me.method(curFrame, start[0], end[0] - start[0], totalFrames),\r
3576                        me.method(curFrame, start[1], end[1] - start[1], totalFrames)];\r
3577             }else{\r
3578                 val = superclass.doMethod.call(me, attr, start, end);\r
3579             }\r
3580             return val;\r
3581         },\r
3582 \r
3583         getAttr : function(attr) {\r
3584             var me = this;\r
3585 \r
3586             if (attr == SCROLL) {\r
3587                 return [me.el.scrollLeft, me.el.scrollTop];\r
3588             }else{\r
3589                 return superclass.getAttr.call(me, attr);\r
3590             }\r
3591         },\r
3592 \r
3593         setAttr : function(attr, val, unit) {\r
3594             var me = this;\r
3595 \r
3596             if(attr == SCROLL){\r
3597                 me.el.scrollLeft = val[0];\r
3598                 me.el.scrollTop = val[1];\r
3599             }else{\r
3600                 superclass.setAttr.call(me, attr, val, unit);\r
3601             }\r
3602         }\r
3603     });\r
3604 })();   \r
3605         if(Ext.isIE) {\r
3606         function fnCleanUp() {\r
3607             var p = Function.prototype;\r
3608             delete p.createSequence;\r
3609             delete p.defer;\r
3610             delete p.createDelegate;\r
3611             delete p.createCallback;\r
3612             delete p.createInterceptor;\r
3613 \r
3614             window.detachEvent("onunload", fnCleanUp);\r
3615         }\r
3616         window.attachEvent("onunload", fnCleanUp);\r
3617     }\r
3618 })();