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