roojs-core-debug.js
[roojs1] / roojs-core-debug.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11  
12
13
14
15
16 // for old browsers
17 window["undefined"] = window["undefined"];
18
19 /**
20  * @class Roo
21  * Roo core utilities and functions.
22  * @singleton
23  */
24 var Roo = {}; 
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 Roo apply
32  */
33
34  
35 Roo.apply = function(o, c, defaults){
36     if(defaults){
37         // no "this" reference for friendly out of scope calls
38         Roo.apply(o, defaults);
39     }
40     if(o && c && typeof c == 'object'){
41         for(var p in c){
42             o[p] = c[p];
43         }
44     }
45     return o;
46 };
47
48
49 (function(){
50     var idSeed = 0;
51     var ua = navigator.userAgent.toLowerCase();
52
53     var isStrict = document.compatMode == "CSS1Compat",
54         isOpera = ua.indexOf("opera") > -1,
55         isSafari = (/webkit|khtml/).test(ua),
56         isIE = ua.indexOf("msie") > -1,
57         isIE7 = ua.indexOf("msie 7") > -1,
58         isGecko = !isSafari && ua.indexOf("gecko") > -1,
59         isBorderBox = isIE && !isStrict,
60         isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61         isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62         isLinux = (ua.indexOf("linux") != -1),
63         isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
64
65     // remove css image flicker
66         if(isIE && !isIE7){
67         try{
68             document.execCommand("BackgroundImageCache", false, true);
69         }catch(e){}
70     }
71
72     Roo.apply(Roo, {
73         /**
74          * True if the browser is in strict mode
75          * @type Boolean
76          */
77         isStrict : isStrict,
78         /**
79          * True if the page is running over SSL
80          * @type Boolean
81          */
82         isSecure : isSecure,
83         /**
84          * True when the document is fully initialized and ready for action
85          * @type Boolean
86          */
87         isReady : false,
88
89         /**
90          * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
91          * @type Boolean
92          */
93         enableGarbageCollector : true,
94
95         /**
96          * True to automatically purge event listeners after uncaching an element (defaults to false).
97          * Note: this only happens if enableGarbageCollector is true.
98          * @type Boolean
99          */
100         enableListenerCollection:false,
101
102         /**
103          * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
104          * the IE insecure content warning (defaults to javascript:false).
105          * @type String
106          */
107         SSL_SECURE_URL : "javascript:false",
108
109         /**
110          * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
111          * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
112          * @type String
113          */
114         BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
115
116         emptyFn : function(){},
117
118         /**
119          * Copies all the properties of config to obj if they don't already exist.
120          * @param {Object} obj The receiver of the properties
121          * @param {Object} config The source of the properties
122          * @return {Object} returns obj
123          */
124         applyIf : function(o, c){
125             if(o && c){
126                 for(var p in c){
127                     if(typeof o[p] == "undefined"){ o[p] = c[p]; }
128                 }
129             }
130             return o;
131         },
132
133         /**
134          * Applies event listeners to elements by selectors when the document is ready.
135          * The event name is specified with an @ suffix.
136 <pre><code>
137 Roo.addBehaviors({
138    // add a listener for click on all anchors in element with id foo
139    '#foo a@click' : function(e, t){
140        // do something
141    },
142
143    // add the same listener to multiple selectors (separated by comma BEFORE the @)
144    '#foo a, #bar span.some-class@mouseover' : function(){
145        // do something
146    }
147 });
148 </code></pre>
149          * @param {Object} obj The list of behaviors to apply
150          */
151         addBehaviors : function(o){
152             if(!Roo.isReady){
153                 Roo.onReady(function(){
154                     Roo.addBehaviors(o);
155                 });
156                 return;
157             }
158             var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
159             for(var b in o){
160                 var parts = b.split('@');
161                 if(parts[1]){ // for Object prototype breakers
162                     var s = parts[0];
163                     if(!cache[s]){
164                         cache[s] = Roo.select(s);
165                     }
166                     cache[s].on(parts[1], o[b]);
167                 }
168             }
169             cache = null;
170         },
171
172         /**
173          * Generates unique ids. If the element already has an id, it is unchanged
174          * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
175          * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
176          * @return {String} The generated Id.
177          */
178         id : function(el, prefix){
179             prefix = prefix || "roo-gen";
180             el = Roo.getDom(el);
181             var id = prefix + (++idSeed);
182             return el ? (el.id ? el.id : (el.id = id)) : id;
183         },
184          
185        
186         /**
187          * Extends one class with another class and optionally overrides members with the passed literal. This class
188          * also adds the function "override()" to the class that can be used to override
189          * members on an instance.
190          * @param {Object} subclass The class inheriting the functionality
191          * @param {Object} superclass The class being extended
192          * @param {Object} overrides (optional) A literal with members
193          * @method extend
194          */
195         extend : function(){
196             // inline overrides
197             var io = function(o){
198                 for(var m in o){
199                     this[m] = o[m];
200                 }
201             };
202             return function(sb, sp, overrides){
203                 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
204                     overrides = sp;
205                     sp = sb;
206                     sb = function(){sp.apply(this, arguments);};
207                 }
208                 var F = function(){}, sbp, spp = sp.prototype;
209                 F.prototype = spp;
210                 sbp = sb.prototype = new F();
211                 sbp.constructor=sb;
212                 sb.superclass=spp;
213                 
214                 if(spp.constructor == Object.prototype.constructor){
215                     spp.constructor=sp;
216                    
217                 }
218                 
219                 sb.override = function(o){
220                     Roo.override(sb, o);
221                 };
222                 sbp.override = io;
223                 Roo.override(sb, overrides);
224                 return sb;
225             };
226         }(),
227
228         /**
229          * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
230          * Usage:<pre><code>
231 Roo.override(MyClass, {
232     newMethod1: function(){
233         // etc.
234     },
235     newMethod2: function(foo){
236         // etc.
237     }
238 });
239  </code></pre>
240          * @param {Object} origclass The class to override
241          * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
242          * containing one or more methods.
243          * @method override
244          */
245         override : function(origclass, overrides){
246             if(overrides){
247                 var p = origclass.prototype;
248                 for(var method in overrides){
249                     p[method] = overrides[method];
250                 }
251             }
252         },
253         /**
254          * Creates namespaces to be used for scoping variables and classes so that they are not global.  Usage:
255          * <pre><code>
256 Roo.namespace('Company', 'Company.data');
257 Company.Widget = function() { ... }
258 Company.data.CustomStore = function(config) { ... }
259 </code></pre>
260          * @param {String} namespace1
261          * @param {String} namespace2
262          * @param {String} etc
263          * @method namespace
264          */
265         namespace : function(){
266             var a=arguments, o=null, i, j, d, rt;
267             for (i=0; i<a.length; ++i) {
268                 d=a[i].split(".");
269                 rt = d[0];
270                 /** eval:var:o */
271                 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
272                 for (j=1; j<d.length; ++j) {
273                     o[d[j]]=o[d[j]] || {};
274                     o=o[d[j]];
275                 }
276             }
277         },
278         /**
279          * Creates namespaces to be used for scoping variables and classes so that they are not global.  Usage:
280          * <pre><code>
281 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
282 Roo.factory(conf, Roo.data);
283 </code></pre>
284          * @param {String} classname
285          * @param {String} namespace (optional)
286          * @method factory
287          */
288          
289         factory : function(c, ns)
290         {
291             // no xtype, no ns or c.xns - or forced off by c.xns
292             if (!c.xtype   || (!ns && !c.xns) ||  (c.xns === false)) { // not enough info...
293                 return c;
294             }
295             ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
296             if (c.constructor == ns[c.xtype]) {// already created...
297                 return c;
298             }
299             if (ns[c.xtype]) {
300                 if (Roo.debug) console.log("Roo.Factory(" + c.xtype + ")");
301                 var ret = new ns[c.xtype](c);
302                 ret.xns = false;
303                 return ret;
304             }
305             c.xns = false; // prevent recursion..
306             return c;
307         },
308          
309         /**
310          * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2".  Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
311          * @param {Object} o
312          * @return {String}
313          */
314         urlEncode : function(o){
315             if(!o){
316                 return "";
317             }
318             var buf = [];
319             for(var key in o){
320                 var ov = o[key], k = encodeURIComponent(key);
321                 var type = typeof ov;
322                 if(type == 'undefined'){
323                     buf.push(k, "=&");
324                 }else if(type != "function" && type != "object"){
325                     buf.push(k, "=", encodeURIComponent(ov), "&");
326                 }else if(ov instanceof Array){
327                     if (ov.length) {
328                             for(var i = 0, len = ov.length; i < len; i++) {
329                                 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
330                             }
331                         } else {
332                             buf.push(k, "=&");
333                         }
334                 }
335             }
336             buf.pop();
337             return buf.join("");
338         },
339
340         /**
341          * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
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(!string || !string.length){
348                 return {};
349             }
350             var obj = {};
351             var pairs = string.split('&');
352             var pair, name, value;
353             for(var i = 0, len = pairs.length; i < len; i++){
354                 pair = pairs[i].split('=');
355                 name = decodeURIComponent(pair[0]);
356                 value = decodeURIComponent(pair[1]);
357                 if(overwrite !== true){
358                     if(typeof obj[name] == "undefined"){
359                         obj[name] = value;
360                     }else if(typeof obj[name] == "string"){
361                         obj[name] = [obj[name]];
362                         obj[name].push(value);
363                     }else{
364                         obj[name].push(value);
365                     }
366                 }else{
367                     obj[name] = value;
368                 }
369             }
370             return obj;
371         },
372
373         /**
374          * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
375          * passed array is not really an array, your function is called once with it.
376          * The supplied function is called with (Object item, Number index, Array allItems).
377          * @param {Array/NodeList/Mixed} array
378          * @param {Function} fn
379          * @param {Object} scope
380          */
381         each : function(array, fn, scope){
382             if(typeof array.length == "undefined" || typeof array == "string"){
383                 array = [array];
384             }
385             for(var i = 0, len = array.length; i < len; i++){
386                 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
387             }
388         },
389
390         // deprecated
391         combine : function(){
392             var as = arguments, l = as.length, r = [];
393             for(var i = 0; i < l; i++){
394                 var a = as[i];
395                 if(a instanceof Array){
396                     r = r.concat(a);
397                 }else if(a.length !== undefined && !a.substr){
398                     r = r.concat(Array.prototype.slice.call(a, 0));
399                 }else{
400                     r.push(a);
401                 }
402             }
403             return r;
404         },
405
406         /**
407          * Escapes the passed string for use in a regular expression
408          * @param {String} str
409          * @return {String}
410          */
411         escapeRe : function(s) {
412             return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
413         },
414
415         // internal
416         callback : function(cb, scope, args, delay){
417             if(typeof cb == "function"){
418                 if(delay){
419                     cb.defer(delay, scope, args || []);
420                 }else{
421                     cb.apply(scope, args || []);
422                 }
423             }
424         },
425
426         /**
427          * Return the dom node for the passed string (id), dom node, or Roo.Element
428          * @param {String/HTMLElement/Roo.Element} el
429          * @return HTMLElement
430          */
431         getDom : function(el){
432             if(!el){
433                 return null;
434             }
435             return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
436         },
437
438         /**
439         * Shorthand for {@link Roo.ComponentMgr#get}
440         * @param {String} id
441         * @return Roo.Component
442         */
443         getCmp : function(id){
444             return Roo.ComponentMgr.get(id);
445         },
446          
447         num : function(v, defaultValue){
448             if(typeof v != 'number'){
449                 return defaultValue;
450             }
451             return v;
452         },
453
454         destroy : function(){
455             for(var i = 0, a = arguments, len = a.length; i < len; i++) {
456                 var as = a[i];
457                 if(as){
458                     if(as.dom){
459                         as.removeAllListeners();
460                         as.remove();
461                         continue;
462                     }
463                     if(typeof as.purgeListeners == 'function'){
464                         as.purgeListeners();
465                     }
466                     if(typeof as.destroy == 'function'){
467                         as.destroy();
468                     }
469                 }
470             }
471         },
472
473         // inpired by a similar function in mootools library
474         /**
475          * Returns the type of object that is passed in. If the object passed in is null or undefined it
476          * return false otherwise it returns one of the following values:<ul>
477          * <li><b>string</b>: If the object passed is a string</li>
478          * <li><b>number</b>: If the object passed is a number</li>
479          * <li><b>boolean</b>: If the object passed is a boolean value</li>
480          * <li><b>function</b>: If the object passed is a function reference</li>
481          * <li><b>object</b>: If the object passed is an object</li>
482          * <li><b>array</b>: If the object passed is an array</li>
483          * <li><b>regexp</b>: If the object passed is a regular expression</li>
484          * <li><b>element</b>: If the object passed is a DOM Element</li>
485          * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
486          * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
487          * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
488          * @param {Mixed} object
489          * @return {String}
490          */
491         type : function(o){
492             if(o === undefined || o === null){
493                 return false;
494             }
495             if(o.htmlElement){
496                 return 'element';
497             }
498             var t = typeof o;
499             if(t == 'object' && o.nodeName) {
500                 switch(o.nodeType) {
501                     case 1: return 'element';
502                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
503                 }
504             }
505             if(t == 'object' || t == 'function') {
506                 switch(o.constructor) {
507                     case Array: return 'array';
508                     case RegExp: return 'regexp';
509                 }
510                 if(typeof o.length == 'number' && typeof o.item == 'function') {
511                     return 'nodelist';
512                 }
513             }
514             return t;
515         },
516
517         /**
518          * Returns true if the passed value is null, undefined or an empty string (optional).
519          * @param {Mixed} value The value to test
520          * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
521          * @return {Boolean}
522          */
523         isEmpty : function(v, allowBlank){
524             return v === null || v === undefined || (!allowBlank ? v === '' : false);
525         },
526         
527         /** @type Boolean */
528         isOpera : isOpera,
529         /** @type Boolean */
530         isSafari : isSafari,
531         /** @type Boolean */
532         isIE : isIE,
533         /** @type Boolean */
534         isIE7 : isIE7,
535         /** @type Boolean */
536         isGecko : isGecko,
537         /** @type Boolean */
538         isBorderBox : isBorderBox,
539         /** @type Boolean */
540         isWindows : isWindows,
541         /** @type Boolean */
542         isLinux : isLinux,
543         /** @type Boolean */
544         isMac : isMac,
545
546         /**
547          * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
548          * you may want to set this to true.
549          * @type Boolean
550          */
551         useShims : ((isIE && !isIE7) || (isGecko && isMac))
552     });
553
554
555 })();
556
557 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
558                 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
559 /*
560  * Based on:
561  * Ext JS Library 1.1.1
562  * Copyright(c) 2006-2007, Ext JS, LLC.
563  *
564  * Originally Released Under LGPL - original licence link has changed is not relivant.
565  *
566  * Fork - LGPL
567  * <script type="text/javascript">
568  */
569
570 (function() {    
571     // wrappedn so fnCleanup is not in global scope...
572     if(Roo.isIE) {
573         function fnCleanUp() {
574             var p = Function.prototype;
575             delete p.createSequence;
576             delete p.defer;
577             delete p.createDelegate;
578             delete p.createCallback;
579             delete p.createInterceptor;
580
581             window.detachEvent("onunload", fnCleanUp);
582         }
583         window.attachEvent("onunload", fnCleanUp);
584     }
585 })();
586
587
588 /**
589  * @class Function
590  * These functions are available on every Function object (any JavaScript function).
591  */
592 Roo.apply(Function.prototype, {
593      /**
594      * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
595      * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
596      * Will create a function that is bound to those 2 args.
597      * @return {Function} The new function
598     */
599     createCallback : function(/*args...*/){
600         // make args available, in function below
601         var args = arguments;
602         var method = this;
603         return function() {
604             return method.apply(window, args);
605         };
606     },
607
608     /**
609      * Creates a delegate (callback) that sets the scope to obj.
610      * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
611      * Will create a function that is automatically scoped to this.
612      * @param {Object} obj (optional) The object for which the scope is set
613      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
614      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
615      *                                             if a number the args are inserted at the specified position
616      * @return {Function} The new function
617      */
618     createDelegate : function(obj, args, appendArgs){
619         var method = this;
620         return function() {
621             var callArgs = args || arguments;
622             if(appendArgs === true){
623                 callArgs = Array.prototype.slice.call(arguments, 0);
624                 callArgs = callArgs.concat(args);
625             }else if(typeof appendArgs == "number"){
626                 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
627                 var applyArgs = [appendArgs, 0].concat(args); // create method call params
628                 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
629             }
630             return method.apply(obj || window, callArgs);
631         };
632     },
633
634     /**
635      * Calls this function after the number of millseconds specified.
636      * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
637      * @param {Object} obj (optional) The object for which the scope is set
638      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
639      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
640      *                                             if a number the args are inserted at the specified position
641      * @return {Number} The timeout id that can be used with clearTimeout
642      */
643     defer : function(millis, obj, args, appendArgs){
644         var fn = this.createDelegate(obj, args, appendArgs);
645         if(millis){
646             return setTimeout(fn, millis);
647         }
648         fn();
649         return 0;
650     },
651     /**
652      * Create a combined function call sequence of the original function + the passed function.
653      * The resulting function returns the results of the original function.
654      * The passed fcn is called with the parameters of the original function
655      * @param {Function} fcn The function to sequence
656      * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
657      * @return {Function} The new function
658      */
659     createSequence : function(fcn, scope){
660         if(typeof fcn != "function"){
661             return this;
662         }
663         var method = this;
664         return function() {
665             var retval = method.apply(this || window, arguments);
666             fcn.apply(scope || this || window, arguments);
667             return retval;
668         };
669     },
670
671     /**
672      * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
673      * The resulting function returns the results of the original function.
674      * The passed fcn is called with the parameters of the original function.
675      * @addon
676      * @param {Function} fcn The function to call before the original
677      * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
678      * @return {Function} The new function
679      */
680     createInterceptor : function(fcn, scope){
681         if(typeof fcn != "function"){
682             return this;
683         }
684         var method = this;
685         return function() {
686             fcn.target = this;
687             fcn.method = method;
688             if(fcn.apply(scope || this || window, arguments) === false){
689                 return;
690             }
691             return method.apply(this || window, arguments);
692         };
693     }
694 });
695 /*
696  * Based on:
697  * Ext JS Library 1.1.1
698  * Copyright(c) 2006-2007, Ext JS, LLC.
699  *
700  * Originally Released Under LGPL - original licence link has changed is not relivant.
701  *
702  * Fork - LGPL
703  * <script type="text/javascript">
704  */
705
706 Roo.applyIf(String, {
707     
708     /** @scope String */
709     
710     /**
711      * Escapes the passed string for ' and \
712      * @param {String} string The string to escape
713      * @return {String} The escaped string
714      * @static
715      */
716     escape : function(string) {
717         return string.replace(/('|\\)/g, "\\$1");
718     },
719
720     /**
721      * Pads the left side of a string with a specified character.  This is especially useful
722      * for normalizing number and date strings.  Example usage:
723      * <pre><code>
724 var s = String.leftPad('123', 5, '0');
725 // s now contains the string: '00123'
726 </code></pre>
727      * @param {String} string The original string
728      * @param {Number} size The total length of the output string
729      * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
730      * @return {String} The padded string
731      * @static
732      */
733     leftPad : function (val, size, ch) {
734         var result = new String(val);
735         if(ch === null || ch === undefined || ch === '') {
736             ch = " ";
737         }
738         while (result.length < size) {
739             result = ch + result;
740         }
741         return result;
742     },
743
744     /**
745      * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
746      * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
747      * <pre><code>
748 var cls = 'my-class', text = 'Some text';
749 var s = String.format('<div class="{0}">{1}</div>', cls, text);
750 // s now contains the string: '<div class="my-class">Some text</div>'
751 </code></pre>
752      * @param {String} string The tokenized string to be formatted
753      * @param {String} value1 The value to replace token {0}
754      * @param {String} value2 Etc...
755      * @return {String} The formatted string
756      * @static
757      */
758     format : function(format){
759         var args = Array.prototype.slice.call(arguments, 1);
760         return format.replace(/\{(\d+)\}/g, function(m, i){
761             return Roo.util.Format.htmlEncode(args[i]);
762         });
763     }
764 });
765
766 /**
767  * Utility function that allows you to easily switch a string between two alternating values.  The passed value
768  * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
769  * they are already different, the first value passed in is returned.  Note that this method returns the new value
770  * but does not change the current string.
771  * <pre><code>
772 // alternate sort directions
773 sort = sort.toggle('ASC', 'DESC');
774
775 // instead of conditional logic:
776 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
777 </code></pre>
778  * @param {String} value The value to compare to the current string
779  * @param {String} other The new value to use if the string already equals the first value passed in
780  * @return {String} The new value
781  */
782  
783 String.prototype.toggle = function(value, other){
784     return this == value ? other : value;
785 };/*
786  * Based on:
787  * Ext JS Library 1.1.1
788  * Copyright(c) 2006-2007, Ext JS, LLC.
789  *
790  * Originally Released Under LGPL - original licence link has changed is not relivant.
791  *
792  * Fork - LGPL
793  * <script type="text/javascript">
794  */
795
796  /**
797  * @class Number
798  */
799 Roo.applyIf(Number.prototype, {
800     /**
801      * Checks whether or not the current number is within a desired range.  If the number is already within the
802      * range it is returned, otherwise the min or max value is returned depending on which side of the range is
803      * exceeded.  Note that this method returns the constrained value but does not change the current number.
804      * @param {Number} min The minimum number in the range
805      * @param {Number} max The maximum number in the range
806      * @return {Number} The constrained value if outside the range, otherwise the current value
807      */
808     constrain : function(min, max){
809         return Math.min(Math.max(this, min), max);
810     }
811 });/*
812  * Based on:
813  * Ext JS Library 1.1.1
814  * Copyright(c) 2006-2007, Ext JS, LLC.
815  *
816  * Originally Released Under LGPL - original licence link has changed is not relivant.
817  *
818  * Fork - LGPL
819  * <script type="text/javascript">
820  */
821  /**
822  * @class Array
823  */
824 Roo.applyIf(Array.prototype, {
825     /**
826      * Checks whether or not the specified object exists in the array.
827      * @param {Object} o The object to check for
828      * @return {Number} The index of o in the array (or -1 if it is not found)
829      */
830     indexOf : function(o){
831        for (var i = 0, len = this.length; i < len; i++){
832               if(this[i] == o) return i;
833        }
834            return -1;
835     },
836
837     /**
838      * Removes the specified object from the array.  If the object is not found nothing happens.
839      * @param {Object} o The object to remove
840      */
841     remove : function(o){
842        var index = this.indexOf(o);
843        if(index != -1){
844            this.splice(index, 1);
845        }
846     },
847     /**
848      * Map (JS 1.6 compatibility)
849      * @param {Function} function  to call
850      */
851     map : function(fun /*, thisp*/)
852     {
853         var len = this.length >>> 0;
854         if (typeof fun != "function")
855             throw new TypeError();
856
857         var res = new Array(len);
858         var thisp = arguments[1];
859         for (var i = 0; i < len; i++)
860         {
861             if (i in this)
862                 res[i] = fun.call(thisp, this[i], i, this);
863         }
864
865         return res;
866     }
867     
868 });
869
870
871
872 if (!Array.prototype.map)
873 {
874   Array.prototype.
875 }/*
876  * Based on:
877  * Ext JS Library 1.1.1
878  * Copyright(c) 2006-2007, Ext JS, LLC.
879  *
880  * Originally Released Under LGPL - original licence link has changed is not relivant.
881  *
882  * Fork - LGPL
883  * <script type="text/javascript">
884  */
885
886 /**
887  * @class Date
888  *
889  * The date parsing and format syntax is a subset of
890  * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
891  * supported will provide results equivalent to their PHP versions.
892  *
893  * Following is the list of all currently supported formats:
894  *<pre>
895 Sample date:
896 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
897
898 Format  Output      Description
899 ------  ----------  --------------------------------------------------------------
900   d      10         Day of the month, 2 digits with leading zeros
901   D      Wed        A textual representation of a day, three letters
902   j      10         Day of the month without leading zeros
903   l      Wednesday  A full textual representation of the day of the week
904   S      th         English ordinal day of month suffix, 2 chars (use with j)
905   w      3          Numeric representation of the day of the week
906   z      9          The julian date, or day of the year (0-365)
907   W      01         ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
908   F      January    A full textual representation of the month
909   m      01         Numeric representation of a month, with leading zeros
910   M      Jan        Month name abbreviation, three letters
911   n      1          Numeric representation of a month, without leading zeros
912   t      31         Number of days in the given month
913   L      0          Whether it's a leap year (1 if it is a leap year, else 0)
914   Y      2007       A full numeric representation of a year, 4 digits
915   y      07         A two digit representation of a year
916   a      pm         Lowercase Ante meridiem and Post meridiem
917   A      PM         Uppercase Ante meridiem and Post meridiem
918   g      3          12-hour format of an hour without leading zeros
919   G      15         24-hour format of an hour without leading zeros
920   h      03         12-hour format of an hour with leading zeros
921   H      15         24-hour format of an hour with leading zeros
922   i      05         Minutes with leading zeros
923   s      01         Seconds, with leading zeros
924   O      -0600      Difference to Greenwich time (GMT) in hours
925   T      CST        Timezone setting of the machine running the code
926   Z      -21600     Timezone offset in seconds (negative if west of UTC, positive if east)
927 </pre>
928  *
929  * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
930  * <pre><code>
931 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
932 document.write(dt.format('Y-m-d'));                         //2007-01-10
933 document.write(dt.format('F j, Y, g:i a'));                 //January 10, 2007, 3:05 pm
934 document.write(dt.format('l, \\t\\he dS of F Y h:i:s A'));  //Wednesday, the 10th of January 2007 03:05:01 PM
935  </code></pre>
936  *
937  * Here are some standard date/time patterns that you might find helpful.  They
938  * are not part of the source of Date.js, but to use them you can simply copy this
939  * block of code into any script that is included after Date.js and they will also become
940  * globally available on the Date object.  Feel free to add or remove patterns as needed in your code.
941  * <pre><code>
942 Date.patterns = {
943     ISO8601Long:"Y-m-d H:i:s",
944     ISO8601Short:"Y-m-d",
945     ShortDate: "n/j/Y",
946     LongDate: "l, F d, Y",
947     FullDateTime: "l, F d, Y g:i:s A",
948     MonthDay: "F d",
949     ShortTime: "g:i A",
950     LongTime: "g:i:s A",
951     SortableDateTime: "Y-m-d\\TH:i:s",
952     UniversalSortableDateTime: "Y-m-d H:i:sO",
953     YearMonth: "F, Y"
954 };
955 </code></pre>
956  *
957  * Example usage:
958  * <pre><code>
959 var dt = new Date();
960 document.write(dt.format(Date.patterns.ShortDate));
961  </code></pre>
962  */
963
964 /*
965  * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
966  * They generate precompiled functions from date formats instead of parsing and
967  * processing the pattern every time you format a date.  These functions are available
968  * on every Date object (any javascript function).
969  *
970  * The original article and download are here:
971  * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
972  *
973  */
974  
975  
976  // was in core
977 /**
978  Returns the number of milliseconds between this date and date
979  @param {Date} date (optional) Defaults to now
980  @return {Number} The diff in milliseconds
981  @member Date getElapsed
982  */
983 Date.prototype.getElapsed = function(date) {
984         return Math.abs((date || new Date()).getTime()-this.getTime());
985 };
986 // was in date file..
987
988
989 // private
990 Date.parseFunctions = {count:0};
991 // private
992 Date.parseRegexes = [];
993 // private
994 Date.formatFunctions = {count:0};
995
996 // private
997 Date.prototype.dateFormat = function(format) {
998     if (Date.formatFunctions[format] == null) {
999         Date.createNewFormat(format);
1000     }
1001     var func = Date.formatFunctions[format];
1002     return this[func]();
1003 };
1004
1005
1006 /**
1007  * Formats a date given the supplied format string
1008  * @param {String} format The format string
1009  * @return {String} The formatted date
1010  * @method
1011  */
1012 Date.prototype.format = Date.prototype.dateFormat;
1013
1014 // private
1015 Date.createNewFormat = function(format) {
1016     var funcName = "format" + Date.formatFunctions.count++;
1017     Date.formatFunctions[format] = funcName;
1018     var code = "Date.prototype." + funcName + " = function(){return ";
1019     var special = false;
1020     var ch = '';
1021     for (var i = 0; i < format.length; ++i) {
1022         ch = format.charAt(i);
1023         if (!special && ch == "\\") {
1024             special = true;
1025         }
1026         else if (special) {
1027             special = false;
1028             code += "'" + String.escape(ch) + "' + ";
1029         }
1030         else {
1031             code += Date.getFormatCode(ch);
1032         }
1033     }
1034     /** eval:var:zzzzzzzzzzzzz */
1035     eval(code.substring(0, code.length - 3) + ";}");
1036 };
1037
1038 // private
1039 Date.getFormatCode = function(character) {
1040     switch (character) {
1041     case "d":
1042         return "String.leftPad(this.getDate(), 2, '0') + ";
1043     case "D":
1044         return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1045     case "j":
1046         return "this.getDate() + ";
1047     case "l":
1048         return "Date.dayNames[this.getDay()] + ";
1049     case "S":
1050         return "this.getSuffix() + ";
1051     case "w":
1052         return "this.getDay() + ";
1053     case "z":
1054         return "this.getDayOfYear() + ";
1055     case "W":
1056         return "this.getWeekOfYear() + ";
1057     case "F":
1058         return "Date.monthNames[this.getMonth()] + ";
1059     case "m":
1060         return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1061     case "M":
1062         return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1063     case "n":
1064         return "(this.getMonth() + 1) + ";
1065     case "t":
1066         return "this.getDaysInMonth() + ";
1067     case "L":
1068         return "(this.isLeapYear() ? 1 : 0) + ";
1069     case "Y":
1070         return "this.getFullYear() + ";
1071     case "y":
1072         return "('' + this.getFullYear()).substring(2, 4) + ";
1073     case "a":
1074         return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1075     case "A":
1076         return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1077     case "g":
1078         return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1079     case "G":
1080         return "this.getHours() + ";
1081     case "h":
1082         return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1083     case "H":
1084         return "String.leftPad(this.getHours(), 2, '0') + ";
1085     case "i":
1086         return "String.leftPad(this.getMinutes(), 2, '0') + ";
1087     case "s":
1088         return "String.leftPad(this.getSeconds(), 2, '0') + ";
1089     case "O":
1090         return "this.getGMTOffset() + ";
1091     case "T":
1092         return "this.getTimezone() + ";
1093     case "Z":
1094         return "(this.getTimezoneOffset() * -60) + ";
1095     default:
1096         return "'" + String.escape(character) + "' + ";
1097     }
1098 };
1099
1100 /**
1101  * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1102  * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates.  Any part of
1103  * the date format that is not specified will default to the current date value for that part.  Time parts can also
1104  * be specified, but default to 0.  Keep in mind that the input date string must precisely match the specified format
1105  * string or the parse operation will fail.
1106  * Example Usage:
1107 <pre><code>
1108 //dt = Fri May 25 2007 (current date)
1109 var dt = new Date();
1110
1111 //dt = Thu May 25 2006 (today's month/day in 2006)
1112 dt = Date.parseDate("2006", "Y");
1113
1114 //dt = Sun Jan 15 2006 (all date parts specified)
1115 dt = Date.parseDate("2006-1-15", "Y-m-d");
1116
1117 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1118 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1119 </code></pre>
1120  * @param {String} input The unparsed date as a string
1121  * @param {String} format The format the date is in
1122  * @return {Date} The parsed date
1123  * @static
1124  */
1125 Date.parseDate = function(input, format) {
1126     if (Date.parseFunctions[format] == null) {
1127         Date.createParser(format);
1128     }
1129     var func = Date.parseFunctions[format];
1130     return Date[func](input);
1131 };
1132 /**
1133  * @private
1134  */
1135 Date.createParser = function(format) {
1136     var funcName = "parse" + Date.parseFunctions.count++;
1137     var regexNum = Date.parseRegexes.length;
1138     var currentGroup = 1;
1139     Date.parseFunctions[format] = funcName;
1140
1141     var code = "Date." + funcName + " = function(input){\n"
1142         + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1143         + "var d = new Date();\n"
1144         + "y = d.getFullYear();\n"
1145         + "m = d.getMonth();\n"
1146         + "d = d.getDate();\n"
1147         + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1148         + "if (results && results.length > 0) {";
1149     var regex = "";
1150
1151     var special = false;
1152     var ch = '';
1153     for (var i = 0; i < format.length; ++i) {
1154         ch = format.charAt(i);
1155         if (!special && ch == "\\") {
1156             special = true;
1157         }
1158         else if (special) {
1159             special = false;
1160             regex += String.escape(ch);
1161         }
1162         else {
1163             var obj = Date.formatCodeToRegex(ch, currentGroup);
1164             currentGroup += obj.g;
1165             regex += obj.s;
1166             if (obj.g && obj.c) {
1167                 code += obj.c;
1168             }
1169         }
1170     }
1171
1172     code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1173         + "{v = new Date(y, m, d, h, i, s);}\n"
1174         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1175         + "{v = new Date(y, m, d, h, i);}\n"
1176         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1177         + "{v = new Date(y, m, d, h);}\n"
1178         + "else if (y >= 0 && m >= 0 && d > 0)\n"
1179         + "{v = new Date(y, m, d);}\n"
1180         + "else if (y >= 0 && m >= 0)\n"
1181         + "{v = new Date(y, m);}\n"
1182         + "else if (y >= 0)\n"
1183         + "{v = new Date(y);}\n"
1184         + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1185         + "    ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1186         + "        v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1187         + ";}";
1188
1189     Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1190     /** eval:var:zzzzzzzzzzzzz */
1191     eval(code);
1192 };
1193
1194 // private
1195 Date.formatCodeToRegex = function(character, currentGroup) {
1196     switch (character) {
1197     case "D":
1198         return {g:0,
1199         c:null,
1200         s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1201     case "j":
1202         return {g:1,
1203             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1204             s:"(\\d{1,2})"}; // day of month without leading zeroes
1205     case "d":
1206         return {g:1,
1207             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1208             s:"(\\d{2})"}; // day of month with leading zeroes
1209     case "l":
1210         return {g:0,
1211             c:null,
1212             s:"(?:" + Date.dayNames.join("|") + ")"};
1213     case "S":
1214         return {g:0,
1215             c:null,
1216             s:"(?:st|nd|rd|th)"};
1217     case "w":
1218         return {g:0,
1219             c:null,
1220             s:"\\d"};
1221     case "z":
1222         return {g:0,
1223             c:null,
1224             s:"(?:\\d{1,3})"};
1225     case "W":
1226         return {g:0,
1227             c:null,
1228             s:"(?:\\d{2})"};
1229     case "F":
1230         return {g:1,
1231             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1232             s:"(" + Date.monthNames.join("|") + ")"};
1233     case "M":
1234         return {g:1,
1235             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1236             s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1237     case "n":
1238         return {g:1,
1239             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1240             s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1241     case "m":
1242         return {g:1,
1243             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1244             s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1245     case "t":
1246         return {g:0,
1247             c:null,
1248             s:"\\d{1,2}"};
1249     case "L":
1250         return {g:0,
1251             c:null,
1252             s:"(?:1|0)"};
1253     case "Y":
1254         return {g:1,
1255             c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1256             s:"(\\d{4})"};
1257     case "y":
1258         return {g:1,
1259             c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1260                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1261             s:"(\\d{1,2})"};
1262     case "a":
1263         return {g:1,
1264             c:"if (results[" + currentGroup + "] == 'am') {\n"
1265                 + "if (h == 12) { h = 0; }\n"
1266                 + "} else { if (h < 12) { h += 12; }}",
1267             s:"(am|pm)"};
1268     case "A":
1269         return {g:1,
1270             c:"if (results[" + currentGroup + "] == 'AM') {\n"
1271                 + "if (h == 12) { h = 0; }\n"
1272                 + "} else { if (h < 12) { h += 12; }}",
1273             s:"(AM|PM)"};
1274     case "g":
1275     case "G":
1276         return {g:1,
1277             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1278             s:"(\\d{1,2})"}; // 12/24-hr format  format of an hour without leading zeroes
1279     case "h":
1280     case "H":
1281         return {g:1,
1282             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1283             s:"(\\d{2})"}; //  12/24-hr format  format of an hour with leading zeroes
1284     case "i":
1285         return {g:1,
1286             c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1287             s:"(\\d{2})"};
1288     case "s":
1289         return {g:1,
1290             c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1291             s:"(\\d{2})"};
1292     case "O":
1293         return {g:1,
1294             c:[
1295                 "o = results[", currentGroup, "];\n",
1296                 "var sn = o.substring(0,1);\n", // get + / - sign
1297                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1298                 "var mn = o.substring(3,5) % 60;\n", // get minutes
1299                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1300                 "    (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1301             ].join(""),
1302             s:"([+\-]\\d{4})"};
1303     case "T":
1304         return {g:0,
1305             c:null,
1306             s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1307     case "Z":
1308         return {g:1,
1309             c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1310                   + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1311             s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1312     default:
1313         return {g:0,
1314             c:null,
1315             s:String.escape(character)};
1316     }
1317 };
1318
1319 /**
1320  * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1321  * @return {String} The abbreviated timezone name (e.g. 'CST')
1322  */
1323 Date.prototype.getTimezone = function() {
1324     return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1325 };
1326
1327 /**
1328  * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1329  * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1330  */
1331 Date.prototype.getGMTOffset = function() {
1332     return (this.getTimezoneOffset() > 0 ? "-" : "+")
1333         + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1334         + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1335 };
1336
1337 /**
1338  * Get the numeric day number of the year, adjusted for leap year.
1339  * @return {Number} 0 through 364 (365 in leap years)
1340  */
1341 Date.prototype.getDayOfYear = function() {
1342     var num = 0;
1343     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1344     for (var i = 0; i < this.getMonth(); ++i) {
1345         num += Date.daysInMonth[i];
1346     }
1347     return num + this.getDate() - 1;
1348 };
1349
1350 /**
1351  * Get the string representation of the numeric week number of the year
1352  * (equivalent to the format specifier 'W').
1353  * @return {String} '00' through '52'
1354  */
1355 Date.prototype.getWeekOfYear = function() {
1356     // Skip to Thursday of this week
1357     var now = this.getDayOfYear() + (4 - this.getDay());
1358     // Find the first Thursday of the year
1359     var jan1 = new Date(this.getFullYear(), 0, 1);
1360     var then = (7 - jan1.getDay() + 4);
1361     return String.leftPad(((now - then) / 7) + 1, 2, "0");
1362 };
1363
1364 /**
1365  * Whether or not the current date is in a leap year.
1366  * @return {Boolean} True if the current date is in a leap year, else false
1367  */
1368 Date.prototype.isLeapYear = function() {
1369     var year = this.getFullYear();
1370     return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1371 };
1372
1373 /**
1374  * Get the first day of the current month, adjusted for leap year.  The returned value
1375  * is the numeric day index within the week (0-6) which can be used in conjunction with
1376  * the {@link #monthNames} array to retrieve the textual day name.
1377  * Example:
1378  *<pre><code>
1379 var dt = new Date('1/10/2007');
1380 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1381 </code></pre>
1382  * @return {Number} The day number (0-6)
1383  */
1384 Date.prototype.getFirstDayOfMonth = function() {
1385     var day = (this.getDay() - (this.getDate() - 1)) % 7;
1386     return (day < 0) ? (day + 7) : day;
1387 };
1388
1389 /**
1390  * Get the last day of the current month, adjusted for leap year.  The returned value
1391  * is the numeric day index within the week (0-6) which can be used in conjunction with
1392  * the {@link #monthNames} array to retrieve the textual day name.
1393  * Example:
1394  *<pre><code>
1395 var dt = new Date('1/10/2007');
1396 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1397 </code></pre>
1398  * @return {Number} The day number (0-6)
1399  */
1400 Date.prototype.getLastDayOfMonth = function() {
1401     var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1402     return (day < 0) ? (day + 7) : day;
1403 };
1404
1405
1406 /**
1407  * Get the first date of this date's month
1408  * @return {Date}
1409  */
1410 Date.prototype.getFirstDateOfMonth = function() {
1411     return new Date(this.getFullYear(), this.getMonth(), 1);
1412 };
1413
1414 /**
1415  * Get the last date of this date's month
1416  * @return {Date}
1417  */
1418 Date.prototype.getLastDateOfMonth = function() {
1419     return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1420 };
1421 /**
1422  * Get the number of days in the current month, adjusted for leap year.
1423  * @return {Number} The number of days in the month
1424  */
1425 Date.prototype.getDaysInMonth = function() {
1426     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1427     return Date.daysInMonth[this.getMonth()];
1428 };
1429
1430 /**
1431  * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1432  * @return {String} 'st, 'nd', 'rd' or 'th'
1433  */
1434 Date.prototype.getSuffix = function() {
1435     switch (this.getDate()) {
1436         case 1:
1437         case 21:
1438         case 31:
1439             return "st";
1440         case 2:
1441         case 22:
1442             return "nd";
1443         case 3:
1444         case 23:
1445             return "rd";
1446         default:
1447             return "th";
1448     }
1449 };
1450
1451 // private
1452 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1453
1454 /**
1455  * An array of textual month names.
1456  * Override these values for international dates, for example...
1457  * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1458  * @type Array
1459  * @static
1460  */
1461 Date.monthNames =
1462    ["January",
1463     "February",
1464     "March",
1465     "April",
1466     "May",
1467     "June",
1468     "July",
1469     "August",
1470     "September",
1471     "October",
1472     "November",
1473     "December"];
1474
1475 /**
1476  * An array of textual day names.
1477  * Override these values for international dates, for example...
1478  * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1479  * @type Array
1480  * @static
1481  */
1482 Date.dayNames =
1483    ["Sunday",
1484     "Monday",
1485     "Tuesday",
1486     "Wednesday",
1487     "Thursday",
1488     "Friday",
1489     "Saturday"];
1490
1491 // private
1492 Date.y2kYear = 50;
1493 // private
1494 Date.monthNumbers = {
1495     Jan:0,
1496     Feb:1,
1497     Mar:2,
1498     Apr:3,
1499     May:4,
1500     Jun:5,
1501     Jul:6,
1502     Aug:7,
1503     Sep:8,
1504     Oct:9,
1505     Nov:10,
1506     Dec:11};
1507
1508 /**
1509  * Creates and returns a new Date instance with the exact same date value as the called instance.
1510  * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1511  * variable will also be changed.  When the intention is to create a new variable that will not
1512  * modify the original instance, you should create a clone.
1513  *
1514  * Example of correctly cloning a date:
1515  * <pre><code>
1516 //wrong way:
1517 var orig = new Date('10/1/2006');
1518 var copy = orig;
1519 copy.setDate(5);
1520 document.write(orig);  //returns 'Thu Oct 05 2006'!
1521
1522 //correct way:
1523 var orig = new Date('10/1/2006');
1524 var copy = orig.clone();
1525 copy.setDate(5);
1526 document.write(orig);  //returns 'Thu Oct 01 2006'
1527 </code></pre>
1528  * @return {Date} The new Date instance
1529  */
1530 Date.prototype.clone = function() {
1531         return new Date(this.getTime());
1532 };
1533
1534 /**
1535  * Clears any time information from this date
1536  @param {Boolean} clone true to create a clone of this date, clear the time and return it
1537  @return {Date} this or the clone
1538  */
1539 Date.prototype.clearTime = function(clone){
1540     if(clone){
1541         return this.clone().clearTime();
1542     }
1543     this.setHours(0);
1544     this.setMinutes(0);
1545     this.setSeconds(0);
1546     this.setMilliseconds(0);
1547     return this;
1548 };
1549
1550 // private
1551 // safari setMonth is broken
1552 if(Roo.isSafari){
1553     Date.brokenSetMonth = Date.prototype.setMonth;
1554         Date.prototype.setMonth = function(num){
1555                 if(num <= -1){
1556                         var n = Math.ceil(-num);
1557                         var back_year = Math.ceil(n/12);
1558                         var month = (n % 12) ? 12 - n % 12 : 0 ;
1559                         this.setFullYear(this.getFullYear() - back_year);
1560                         return Date.brokenSetMonth.call(this, month);
1561                 } else {
1562                         return Date.brokenSetMonth.apply(this, arguments);
1563                 }
1564         };
1565 }
1566
1567 /** Date interval constant 
1568 * @static 
1569 * @type String */
1570 Date.MILLI = "ms";
1571 /** Date interval constant 
1572 * @static 
1573 * @type String */
1574 Date.SECOND = "s";
1575 /** Date interval constant 
1576 * @static 
1577 * @type String */
1578 Date.MINUTE = "mi";
1579 /** Date interval constant 
1580 * @static 
1581 * @type String */
1582 Date.HOUR = "h";
1583 /** Date interval constant 
1584 * @static 
1585 * @type String */
1586 Date.DAY = "d";
1587 /** Date interval constant 
1588 * @static 
1589 * @type String */
1590 Date.MONTH = "mo";
1591 /** Date interval constant 
1592 * @static 
1593 * @type String */
1594 Date.YEAR = "y";
1595
1596 /**
1597  * Provides a convenient method of performing basic date arithmetic.  This method
1598  * does not modify the Date instance being called - it creates and returns
1599  * a new Date instance containing the resulting date value.
1600  *
1601  * Examples:
1602  * <pre><code>
1603 //Basic usage:
1604 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1605 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1606
1607 //Negative values will subtract correctly:
1608 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1609 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1610
1611 //You can even chain several calls together in one line!
1612 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1613 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1614  </code></pre>
1615  *
1616  * @param {String} interval   A valid date interval enum value
1617  * @param {Number} value      The amount to add to the current date
1618  * @return {Date} The new Date instance
1619  */
1620 Date.prototype.add = function(interval, value){
1621   var d = this.clone();
1622   if (!interval || value === 0) return d;
1623   switch(interval.toLowerCase()){
1624     case Date.MILLI:
1625       d.setMilliseconds(this.getMilliseconds() + value);
1626       break;
1627     case Date.SECOND:
1628       d.setSeconds(this.getSeconds() + value);
1629       break;
1630     case Date.MINUTE:
1631       d.setMinutes(this.getMinutes() + value);
1632       break;
1633     case Date.HOUR:
1634       d.setHours(this.getHours() + value);
1635       break;
1636     case Date.DAY:
1637       d.setDate(this.getDate() + value);
1638       break;
1639     case Date.MONTH:
1640       var day = this.getDate();
1641       if(day > 28){
1642           day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1643       }
1644       d.setDate(day);
1645       d.setMonth(this.getMonth() + value);
1646       break;
1647     case Date.YEAR:
1648       d.setFullYear(this.getFullYear() + value);
1649       break;
1650   }
1651   return d;
1652 };/*
1653  * Based on:
1654  * Ext JS Library 1.1.1
1655  * Copyright(c) 2006-2007, Ext JS, LLC.
1656  *
1657  * Originally Released Under LGPL - original licence link has changed is not relivant.
1658  *
1659  * Fork - LGPL
1660  * <script type="text/javascript">
1661  */
1662
1663 Roo.lib.Dom = {
1664     getViewWidth : function(full) {
1665         return full ? this.getDocumentWidth() : this.getViewportWidth();
1666     },
1667
1668     getViewHeight : function(full) {
1669         return full ? this.getDocumentHeight() : this.getViewportHeight();
1670     },
1671
1672     getDocumentHeight: function() {
1673         var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1674         return Math.max(scrollHeight, this.getViewportHeight());
1675     },
1676
1677     getDocumentWidth: function() {
1678         var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1679         return Math.max(scrollWidth, this.getViewportWidth());
1680     },
1681
1682     getViewportHeight: function() {
1683         var height = self.innerHeight;
1684         var mode = document.compatMode;
1685
1686         if ((mode || Roo.isIE) && !Roo.isOpera) {
1687             height = (mode == "CSS1Compat") ?
1688                      document.documentElement.clientHeight :
1689                      document.body.clientHeight;
1690         }
1691
1692         return height;
1693     },
1694
1695     getViewportWidth: function() {
1696         var width = self.innerWidth;
1697         var mode = document.compatMode;
1698
1699         if (mode || Roo.isIE) {
1700             width = (mode == "CSS1Compat") ?
1701                     document.documentElement.clientWidth :
1702                     document.body.clientWidth;
1703         }
1704         return width;
1705     },
1706
1707     isAncestor : function(p, c) {
1708         p = Roo.getDom(p);
1709         c = Roo.getDom(c);
1710         if (!p || !c) {
1711             return false;
1712         }
1713
1714         if (p.contains && !Roo.isSafari) {
1715             return p.contains(c);
1716         } else if (p.compareDocumentPosition) {
1717             return !!(p.compareDocumentPosition(c) & 16);
1718         } else {
1719             var parent = c.parentNode;
1720             while (parent) {
1721                 if (parent == p) {
1722                     return true;
1723                 }
1724                 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1725                     return false;
1726                 }
1727                 parent = parent.parentNode;
1728             }
1729             return false;
1730         }
1731     },
1732
1733     getRegion : function(el) {
1734         return Roo.lib.Region.getRegion(el);
1735     },
1736
1737     getY : function(el) {
1738         return this.getXY(el)[1];
1739     },
1740
1741     getX : function(el) {
1742         return this.getXY(el)[0];
1743     },
1744
1745     getXY : function(el) {
1746         var p, pe, b, scroll, bd = document.body;
1747         el = Roo.getDom(el);
1748         var fly = Roo.lib.AnimBase.fly;
1749         if (el.getBoundingClientRect) {
1750             b = el.getBoundingClientRect();
1751             scroll = fly(document).getScroll();
1752             return [b.left + scroll.left, b.top + scroll.top];
1753         }
1754         var x = 0, y = 0;
1755
1756         p = el;
1757
1758         var hasAbsolute = fly(el).getStyle("position") == "absolute";
1759
1760         while (p) {
1761
1762             x += p.offsetLeft;
1763             y += p.offsetTop;
1764
1765             if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1766                 hasAbsolute = true;
1767             }
1768
1769             if (Roo.isGecko) {
1770                 pe = fly(p);
1771
1772                 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1773                 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1774
1775
1776                 x += bl;
1777                 y += bt;
1778
1779
1780                 if (p != el && pe.getStyle('overflow') != 'visible') {
1781                     x += bl;
1782                     y += bt;
1783                 }
1784             }
1785             p = p.offsetParent;
1786         }
1787
1788         if (Roo.isSafari && hasAbsolute) {
1789             x -= bd.offsetLeft;
1790             y -= bd.offsetTop;
1791         }
1792
1793         if (Roo.isGecko && !hasAbsolute) {
1794             var dbd = fly(bd);
1795             x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1796             y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1797         }
1798
1799         p = el.parentNode;
1800         while (p && p != bd) {
1801             if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1802                 x -= p.scrollLeft;
1803                 y -= p.scrollTop;
1804             }
1805             p = p.parentNode;
1806         }
1807         return [x, y];
1808     },
1809  
1810   
1811
1812
1813     setXY : function(el, xy) {
1814         el = Roo.fly(el, '_setXY');
1815         el.position();
1816         var pts = el.translatePoints(xy);
1817         if (xy[0] !== false) {
1818             el.dom.style.left = pts.left + "px";
1819         }
1820         if (xy[1] !== false) {
1821             el.dom.style.top = pts.top + "px";
1822         }
1823     },
1824
1825     setX : function(el, x) {
1826         this.setXY(el, [x, false]);
1827     },
1828
1829     setY : function(el, y) {
1830         this.setXY(el, [false, y]);
1831     }
1832 };
1833 /*
1834  * Portions of this file are based on pieces of Yahoo User Interface Library
1835  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1836  * YUI licensed under the BSD License:
1837  * http://developer.yahoo.net/yui/license.txt
1838  * <script type="text/javascript">
1839  *
1840  */
1841
1842 Roo.lib.Event = function() {
1843     var loadComplete = false;
1844     var listeners = [];
1845     var unloadListeners = [];
1846     var retryCount = 0;
1847     var onAvailStack = [];
1848     var counter = 0;
1849     var lastError = null;
1850
1851     return {
1852         POLL_RETRYS: 200,
1853         POLL_INTERVAL: 20,
1854         EL: 0,
1855         TYPE: 1,
1856         FN: 2,
1857         WFN: 3,
1858         OBJ: 3,
1859         ADJ_SCOPE: 4,
1860         _interval: null,
1861
1862         startInterval: function() {
1863             if (!this._interval) {
1864                 var self = this;
1865                 var callback = function() {
1866                     self._tryPreloadAttach();
1867                 };
1868                 this._interval = setInterval(callback, this.POLL_INTERVAL);
1869
1870             }
1871         },
1872
1873         onAvailable: function(p_id, p_fn, p_obj, p_override) {
1874             onAvailStack.push({ id:         p_id,
1875                 fn:         p_fn,
1876                 obj:        p_obj,
1877                 override:   p_override,
1878                 checkReady: false    });
1879
1880             retryCount = this.POLL_RETRYS;
1881             this.startInterval();
1882         },
1883
1884
1885         addListener: function(el, eventName, fn) {
1886             el = Roo.getDom(el);
1887             if (!el || !fn) {
1888                 return false;
1889             }
1890
1891             if ("unload" == eventName) {
1892                 unloadListeners[unloadListeners.length] =
1893                 [el, eventName, fn];
1894                 return true;
1895             }
1896
1897             var wrappedFn = function(e) {
1898                 return fn(Roo.lib.Event.getEvent(e));
1899             };
1900
1901             var li = [el, eventName, fn, wrappedFn];
1902
1903             var index = listeners.length;
1904             listeners[index] = li;
1905
1906             this.doAdd(el, eventName, wrappedFn, false);
1907             return true;
1908
1909         },
1910
1911
1912         removeListener: function(el, eventName, fn) {
1913             var i, len;
1914
1915             el = Roo.getDom(el);
1916
1917             if(!fn) {
1918                 return this.purgeElement(el, false, eventName);
1919             }
1920
1921
1922             if ("unload" == eventName) {
1923
1924                 for (i = 0,len = unloadListeners.length; i < len; i++) {
1925                     var li = unloadListeners[i];
1926                     if (li &&
1927                         li[0] == el &&
1928                         li[1] == eventName &&
1929                         li[2] == fn) {
1930                         unloadListeners.splice(i, 1);
1931                         return true;
1932                     }
1933                 }
1934
1935                 return false;
1936             }
1937
1938             var cacheItem = null;
1939
1940
1941             var index = arguments[3];
1942
1943             if ("undefined" == typeof index) {
1944                 index = this._getCacheIndex(el, eventName, fn);
1945             }
1946
1947             if (index >= 0) {
1948                 cacheItem = listeners[index];
1949             }
1950
1951             if (!el || !cacheItem) {
1952                 return false;
1953             }
1954
1955             this.doRemove(el, eventName, cacheItem[this.WFN], false);
1956
1957             delete listeners[index][this.WFN];
1958             delete listeners[index][this.FN];
1959             listeners.splice(index, 1);
1960
1961             return true;
1962
1963         },
1964
1965
1966         getTarget: function(ev, resolveTextNode) {
1967             ev = ev.browserEvent || ev;
1968             var t = ev.target || ev.srcElement;
1969             return this.resolveTextNode(t);
1970         },
1971
1972
1973         resolveTextNode: function(node) {
1974             if (Roo.isSafari && node && 3 == node.nodeType) {
1975                 return node.parentNode;
1976             } else {
1977                 return node;
1978             }
1979         },
1980
1981
1982         getPageX: function(ev) {
1983             ev = ev.browserEvent || ev;
1984             var x = ev.pageX;
1985             if (!x && 0 !== x) {
1986                 x = ev.clientX || 0;
1987
1988                 if (Roo.isIE) {
1989                     x += this.getScroll()[1];
1990                 }
1991             }
1992
1993             return x;
1994         },
1995
1996
1997         getPageY: function(ev) {
1998             ev = ev.browserEvent || ev;
1999             var y = ev.pageY;
2000             if (!y && 0 !== y) {
2001                 y = ev.clientY || 0;
2002
2003                 if (Roo.isIE) {
2004                     y += this.getScroll()[0];
2005                 }
2006             }
2007
2008
2009             return y;
2010         },
2011
2012
2013         getXY: function(ev) {
2014             ev = ev.browserEvent || ev;
2015             return [this.getPageX(ev), this.getPageY(ev)];
2016         },
2017
2018
2019         getRelatedTarget: function(ev) {
2020             ev = ev.browserEvent || ev;
2021             var t = ev.relatedTarget;
2022             if (!t) {
2023                 if (ev.type == "mouseout") {
2024                     t = ev.toElement;
2025                 } else if (ev.type == "mouseover") {
2026                     t = ev.fromElement;
2027                 }
2028             }
2029
2030             return this.resolveTextNode(t);
2031         },
2032
2033
2034         getTime: function(ev) {
2035             ev = ev.browserEvent || ev;
2036             if (!ev.time) {
2037                 var t = new Date().getTime();
2038                 try {
2039                     ev.time = t;
2040                 } catch(ex) {
2041                     this.lastError = ex;
2042                     return t;
2043                 }
2044             }
2045
2046             return ev.time;
2047         },
2048
2049
2050         stopEvent: function(ev) {
2051             this.stopPropagation(ev);
2052             this.preventDefault(ev);
2053         },
2054
2055
2056         stopPropagation: function(ev) {
2057             ev = ev.browserEvent || ev;
2058             if (ev.stopPropagation) {
2059                 ev.stopPropagation();
2060             } else {
2061                 ev.cancelBubble = true;
2062             }
2063         },
2064
2065
2066         preventDefault: function(ev) {
2067             ev = ev.browserEvent || ev;
2068             if(ev.preventDefault) {
2069                 ev.preventDefault();
2070             } else {
2071                 ev.returnValue = false;
2072             }
2073         },
2074
2075
2076         getEvent: function(e) {
2077             var ev = e || window.event;
2078             if (!ev) {
2079                 var c = this.getEvent.caller;
2080                 while (c) {
2081                     ev = c.arguments[0];
2082                     if (ev && Event == ev.constructor) {
2083                         break;
2084                     }
2085                     c = c.caller;
2086                 }
2087             }
2088             return ev;
2089         },
2090
2091
2092         getCharCode: function(ev) {
2093             ev = ev.browserEvent || ev;
2094             return ev.charCode || ev.keyCode || 0;
2095         },
2096
2097
2098         _getCacheIndex: function(el, eventName, fn) {
2099             for (var i = 0,len = listeners.length; i < len; ++i) {
2100                 var li = listeners[i];
2101                 if (li &&
2102                     li[this.FN] == fn &&
2103                     li[this.EL] == el &&
2104                     li[this.TYPE] == eventName) {
2105                     return i;
2106                 }
2107             }
2108
2109             return -1;
2110         },
2111
2112
2113         elCache: {},
2114
2115
2116         getEl: function(id) {
2117             return document.getElementById(id);
2118         },
2119
2120
2121         clearCache: function() {
2122         },
2123
2124
2125         _load: function(e) {
2126             loadComplete = true;
2127             var EU = Roo.lib.Event;
2128
2129
2130             if (Roo.isIE) {
2131                 EU.doRemove(window, "load", EU._load);
2132             }
2133         },
2134
2135
2136         _tryPreloadAttach: function() {
2137
2138             if (this.locked) {
2139                 return false;
2140             }
2141
2142             this.locked = true;
2143
2144
2145             var tryAgain = !loadComplete;
2146             if (!tryAgain) {
2147                 tryAgain = (retryCount > 0);
2148             }
2149
2150
2151             var notAvail = [];
2152             for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2153                 var item = onAvailStack[i];
2154                 if (item) {
2155                     var el = this.getEl(item.id);
2156
2157                     if (el) {
2158                         if (!item.checkReady ||
2159                             loadComplete ||
2160                             el.nextSibling ||
2161                             (document && document.body)) {
2162
2163                             var scope = el;
2164                             if (item.override) {
2165                                 if (item.override === true) {
2166                                     scope = item.obj;
2167                                 } else {
2168                                     scope = item.override;
2169                                 }
2170                             }
2171                             item.fn.call(scope, item.obj);
2172                             onAvailStack[i] = null;
2173                         }
2174                     } else {
2175                         notAvail.push(item);
2176                     }
2177                 }
2178             }
2179
2180             retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2181
2182             if (tryAgain) {
2183
2184                 this.startInterval();
2185             } else {
2186                 clearInterval(this._interval);
2187                 this._interval = null;
2188             }
2189
2190             this.locked = false;
2191
2192             return true;
2193
2194         },
2195
2196
2197         purgeElement: function(el, recurse, eventName) {
2198             var elListeners = this.getListeners(el, eventName);
2199             if (elListeners) {
2200                 for (var i = 0,len = elListeners.length; i < len; ++i) {
2201                     var l = elListeners[i];
2202                     this.removeListener(el, l.type, l.fn);
2203                 }
2204             }
2205
2206             if (recurse && el && el.childNodes) {
2207                 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2208                     this.purgeElement(el.childNodes[i], recurse, eventName);
2209                 }
2210             }
2211         },
2212
2213
2214         getListeners: function(el, eventName) {
2215             var results = [], searchLists;
2216             if (!eventName) {
2217                 searchLists = [listeners, unloadListeners];
2218             } else if (eventName == "unload") {
2219                 searchLists = [unloadListeners];
2220             } else {
2221                 searchLists = [listeners];
2222             }
2223
2224             for (var j = 0; j < searchLists.length; ++j) {
2225                 var searchList = searchLists[j];
2226                 if (searchList && searchList.length > 0) {
2227                     for (var i = 0,len = searchList.length; i < len; ++i) {
2228                         var l = searchList[i];
2229                         if (l && l[this.EL] === el &&
2230                             (!eventName || eventName === l[this.TYPE])) {
2231                             results.push({
2232                                 type:   l[this.TYPE],
2233                                 fn:     l[this.FN],
2234                                 obj:    l[this.OBJ],
2235                                 adjust: l[this.ADJ_SCOPE],
2236                                 index:  i
2237                             });
2238                         }
2239                     }
2240                 }
2241             }
2242
2243             return (results.length) ? results : null;
2244         },
2245
2246
2247         _unload: function(e) {
2248
2249             var EU = Roo.lib.Event, i, j, l, len, index;
2250
2251             for (i = 0,len = unloadListeners.length; i < len; ++i) {
2252                 l = unloadListeners[i];
2253                 if (l) {
2254                     var scope = window;
2255                     if (l[EU.ADJ_SCOPE]) {
2256                         if (l[EU.ADJ_SCOPE] === true) {
2257                             scope = l[EU.OBJ];
2258                         } else {
2259                             scope = l[EU.ADJ_SCOPE];
2260                         }
2261                     }
2262                     l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2263                     unloadListeners[i] = null;
2264                     l = null;
2265                     scope = null;
2266                 }
2267             }
2268
2269             unloadListeners = null;
2270
2271             if (listeners && listeners.length > 0) {
2272                 j = listeners.length;
2273                 while (j) {
2274                     index = j - 1;
2275                     l = listeners[index];
2276                     if (l) {
2277                         EU.removeListener(l[EU.EL], l[EU.TYPE],
2278                                 l[EU.FN], index);
2279                     }
2280                     j = j - 1;
2281                 }
2282                 l = null;
2283
2284                 EU.clearCache();
2285             }
2286
2287             EU.doRemove(window, "unload", EU._unload);
2288
2289         },
2290
2291
2292         getScroll: function() {
2293             var dd = document.documentElement, db = document.body;
2294             if (dd && (dd.scrollTop || dd.scrollLeft)) {
2295                 return [dd.scrollTop, dd.scrollLeft];
2296             } else if (db) {
2297                 return [db.scrollTop, db.scrollLeft];
2298             } else {
2299                 return [0, 0];
2300             }
2301         },
2302
2303
2304         doAdd: function () {
2305             if (window.addEventListener) {
2306                 return function(el, eventName, fn, capture) {
2307                     el.addEventListener(eventName, fn, (capture));
2308                 };
2309             } else if (window.attachEvent) {
2310                 return function(el, eventName, fn, capture) {
2311                     el.attachEvent("on" + eventName, fn);
2312                 };
2313             } else {
2314                 return function() {
2315                 };
2316             }
2317         }(),
2318
2319
2320         doRemove: function() {
2321             if (window.removeEventListener) {
2322                 return function (el, eventName, fn, capture) {
2323                     el.removeEventListener(eventName, fn, (capture));
2324                 };
2325             } else if (window.detachEvent) {
2326                 return function (el, eventName, fn) {
2327                     el.detachEvent("on" + eventName, fn);
2328                 };
2329             } else {
2330                 return function() {
2331                 };
2332             }
2333         }()
2334     };
2335     
2336 }();
2337 (function() {     
2338    
2339     var E = Roo.lib.Event;
2340     E.on = E.addListener;
2341     E.un = E.removeListener;
2342
2343     if (document && document.body) {
2344         E._load();
2345     } else {
2346         E.doAdd(window, "load", E._load);
2347     }
2348     E.doAdd(window, "unload", E._unload);
2349     E._tryPreloadAttach();
2350 })();
2351
2352 /*
2353  * Portions of this file are based on pieces of Yahoo User Interface Library
2354  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2355  * YUI licensed under the BSD License:
2356  * http://developer.yahoo.net/yui/license.txt
2357  * <script type="text/javascript">
2358  *
2359  */
2360
2361 (function() {
2362     
2363     Roo.lib.Ajax = {
2364         request : function(method, uri, cb, data, options) {
2365             if(options){
2366                 var hs = options.headers;
2367                 if(hs){
2368                     for(var h in hs){
2369                         if(hs.hasOwnProperty(h)){
2370                             this.initHeader(h, hs[h], false);
2371                         }
2372                     }
2373                 }
2374                 if(options.xmlData){
2375                     this.initHeader('Content-Type', 'text/xml', false);
2376                     method = 'POST';
2377                     data = options.xmlData;
2378                 }
2379             }
2380
2381             return this.asyncRequest(method, uri, cb, data);
2382         },
2383
2384         serializeForm : function(form) {
2385             if(typeof form == 'string') {
2386                 form = (document.getElementById(form) || document.forms[form]);
2387             }
2388
2389             var el, name, val, disabled, data = '', hasSubmit = false;
2390             for (var i = 0; i < form.elements.length; i++) {
2391                 el = form.elements[i];
2392                 disabled = form.elements[i].disabled;
2393                 name = form.elements[i].name;
2394                 val = form.elements[i].value;
2395
2396                 if (!disabled && name){
2397                     switch (el.type)
2398                             {
2399                         case 'select-one':
2400                         case 'select-multiple':
2401                             for (var j = 0; j < el.options.length; j++) {
2402                                 if (el.options[j].selected) {
2403                                     if (Roo.isIE) {
2404                                         data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2405                                     }
2406                                     else {
2407                                         data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2408                                     }
2409                                 }
2410                             }
2411                             break;
2412                         case 'radio':
2413                         case 'checkbox':
2414                             if (el.checked) {
2415                                 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2416                             }
2417                             break;
2418                         case 'file':
2419
2420                         case undefined:
2421
2422                         case 'reset':
2423
2424                         case 'button':
2425
2426                             break;
2427                         case 'submit':
2428                             if(hasSubmit == false) {
2429                                 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2430                                 hasSubmit = true;
2431                             }
2432                             break;
2433                         default:
2434                             data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2435                             break;
2436                     }
2437                 }
2438             }
2439             data = data.substr(0, data.length - 1);
2440             return data;
2441         },
2442
2443         headers:{},
2444
2445         hasHeaders:false,
2446
2447         useDefaultHeader:true,
2448
2449         defaultPostHeader:'application/x-www-form-urlencoded',
2450
2451         useDefaultXhrHeader:true,
2452
2453         defaultXhrHeader:'XMLHttpRequest',
2454
2455         hasDefaultHeaders:true,
2456
2457         defaultHeaders:{},
2458
2459         poll:{},
2460
2461         timeout:{},
2462
2463         pollInterval:50,
2464
2465         transactionId:0,
2466
2467         setProgId:function(id)
2468         {
2469             this.activeX.unshift(id);
2470         },
2471
2472         setDefaultPostHeader:function(b)
2473         {
2474             this.useDefaultHeader = b;
2475         },
2476
2477         setDefaultXhrHeader:function(b)
2478         {
2479             this.useDefaultXhrHeader = b;
2480         },
2481
2482         setPollingInterval:function(i)
2483         {
2484             if (typeof i == 'number' && isFinite(i)) {
2485                 this.pollInterval = i;
2486             }
2487         },
2488
2489         createXhrObject:function(transactionId)
2490         {
2491             var obj,http;
2492             try
2493             {
2494
2495                 http = new XMLHttpRequest();
2496
2497                 obj = { conn:http, tId:transactionId };
2498             }
2499             catch(e)
2500             {
2501                 for (var i = 0; i < this.activeX.length; ++i) {
2502                     try
2503                     {
2504
2505                         http = new ActiveXObject(this.activeX[i]);
2506
2507                         obj = { conn:http, tId:transactionId };
2508                         break;
2509                     }
2510                     catch(e) {
2511                     }
2512                 }
2513             }
2514             finally
2515             {
2516                 return obj;
2517             }
2518         },
2519
2520         getConnectionObject:function()
2521         {
2522             var o;
2523             var tId = this.transactionId;
2524
2525             try
2526             {
2527                 o = this.createXhrObject(tId);
2528                 if (o) {
2529                     this.transactionId++;
2530                 }
2531             }
2532             catch(e) {
2533             }
2534             finally
2535             {
2536                 return o;
2537             }
2538         },
2539
2540         asyncRequest:function(method, uri, callback, postData)
2541         {
2542             var o = this.getConnectionObject();
2543
2544             if (!o) {
2545                 return null;
2546             }
2547             else {
2548                 o.conn.open(method, uri, true);
2549
2550                 if (this.useDefaultXhrHeader) {
2551                     if (!this.defaultHeaders['X-Requested-With']) {
2552                         this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2553                     }
2554                 }
2555
2556                 if(postData && this.useDefaultHeader){
2557                     this.initHeader('Content-Type', this.defaultPostHeader);
2558                 }
2559
2560                  if (this.hasDefaultHeaders || this.hasHeaders) {
2561                     this.setHeader(o);
2562                 }
2563
2564                 this.handleReadyState(o, callback);
2565                 o.conn.send(postData || null);
2566
2567                 return o;
2568             }
2569         },
2570
2571         handleReadyState:function(o, callback)
2572         {
2573             var oConn = this;
2574
2575             if (callback && callback.timeout) {
2576                 this.timeout[o.tId] = window.setTimeout(function() {
2577                     oConn.abort(o, callback, true);
2578                 }, callback.timeout);
2579             }
2580
2581             this.poll[o.tId] = window.setInterval(
2582                     function() {
2583                         if (o.conn && o.conn.readyState == 4) {
2584                             window.clearInterval(oConn.poll[o.tId]);
2585                             delete oConn.poll[o.tId];
2586
2587                             if(callback && callback.timeout) {
2588                                 window.clearTimeout(oConn.timeout[o.tId]);
2589                                 delete oConn.timeout[o.tId];
2590                             }
2591
2592                             oConn.handleTransactionResponse(o, callback);
2593                         }
2594                     }
2595                     , this.pollInterval);
2596         },
2597
2598         handleTransactionResponse:function(o, callback, isAbort)
2599         {
2600
2601             if (!callback) {
2602                 this.releaseObject(o);
2603                 return;
2604             }
2605
2606             var httpStatus, responseObject;
2607
2608             try
2609             {
2610                 if (o.conn.status !== undefined && o.conn.status != 0) {
2611                     httpStatus = o.conn.status;
2612                 }
2613                 else {
2614                     httpStatus = 13030;
2615                 }
2616             }
2617             catch(e) {
2618
2619
2620                 httpStatus = 13030;
2621             }
2622
2623             if (httpStatus >= 200 && httpStatus < 300) {
2624                 responseObject = this.createResponseObject(o, callback.argument);
2625                 if (callback.success) {
2626                     if (!callback.scope) {
2627                         callback.success(responseObject);
2628                     }
2629                     else {
2630
2631
2632                         callback.success.apply(callback.scope, [responseObject]);
2633                     }
2634                 }
2635             }
2636             else {
2637                 switch (httpStatus) {
2638
2639                     case 12002:
2640                     case 12029:
2641                     case 12030:
2642                     case 12031:
2643                     case 12152:
2644                     case 13030:
2645                         responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2646                         if (callback.failure) {
2647                             if (!callback.scope) {
2648                                 callback.failure(responseObject);
2649                             }
2650                             else {
2651                                 callback.failure.apply(callback.scope, [responseObject]);
2652                             }
2653                         }
2654                         break;
2655                     default:
2656                         responseObject = this.createResponseObject(o, callback.argument);
2657                         if (callback.failure) {
2658                             if (!callback.scope) {
2659                                 callback.failure(responseObject);
2660                             }
2661                             else {
2662                                 callback.failure.apply(callback.scope, [responseObject]);
2663                             }
2664                         }
2665                 }
2666             }
2667
2668             this.releaseObject(o);
2669             responseObject = null;
2670         },
2671
2672         createResponseObject:function(o, callbackArg)
2673         {
2674             var obj = {};
2675             var headerObj = {};
2676
2677             try
2678             {
2679                 var headerStr = o.conn.getAllResponseHeaders();
2680                 var header = headerStr.split('\n');
2681                 for (var i = 0; i < header.length; i++) {
2682                     var delimitPos = header[i].indexOf(':');
2683                     if (delimitPos != -1) {
2684                         headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2685                     }
2686                 }
2687             }
2688             catch(e) {
2689             }
2690
2691             obj.tId = o.tId;
2692             obj.status = o.conn.status;
2693             obj.statusText = o.conn.statusText;
2694             obj.getResponseHeader = headerObj;
2695             obj.getAllResponseHeaders = headerStr;
2696             obj.responseText = o.conn.responseText;
2697             obj.responseXML = o.conn.responseXML;
2698
2699             if (typeof callbackArg !== undefined) {
2700                 obj.argument = callbackArg;
2701             }
2702
2703             return obj;
2704         },
2705
2706         createExceptionObject:function(tId, callbackArg, isAbort)
2707         {
2708             var COMM_CODE = 0;
2709             var COMM_ERROR = 'communication failure';
2710             var ABORT_CODE = -1;
2711             var ABORT_ERROR = 'transaction aborted';
2712
2713             var obj = {};
2714
2715             obj.tId = tId;
2716             if (isAbort) {
2717                 obj.status = ABORT_CODE;
2718                 obj.statusText = ABORT_ERROR;
2719             }
2720             else {
2721                 obj.status = COMM_CODE;
2722                 obj.statusText = COMM_ERROR;
2723             }
2724
2725             if (callbackArg) {
2726                 obj.argument = callbackArg;
2727             }
2728
2729             return obj;
2730         },
2731
2732         initHeader:function(label, value, isDefault)
2733         {
2734             var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2735
2736             if (headerObj[label] === undefined) {
2737                 headerObj[label] = value;
2738             }
2739             else {
2740
2741
2742                 headerObj[label] = value + "," + headerObj[label];
2743             }
2744
2745             if (isDefault) {
2746                 this.hasDefaultHeaders = true;
2747             }
2748             else {
2749                 this.hasHeaders = true;
2750             }
2751         },
2752
2753
2754         setHeader:function(o)
2755         {
2756             if (this.hasDefaultHeaders) {
2757                 for (var prop in this.defaultHeaders) {
2758                     if (this.defaultHeaders.hasOwnProperty(prop)) {
2759                         o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2760                     }
2761                 }
2762             }
2763
2764             if (this.hasHeaders) {
2765                 for (var prop in this.headers) {
2766                     if (this.headers.hasOwnProperty(prop)) {
2767                         o.conn.setRequestHeader(prop, this.headers[prop]);
2768                     }
2769                 }
2770                 this.headers = {};
2771                 this.hasHeaders = false;
2772             }
2773         },
2774
2775         resetDefaultHeaders:function() {
2776             delete this.defaultHeaders;
2777             this.defaultHeaders = {};
2778             this.hasDefaultHeaders = false;
2779         },
2780
2781         abort:function(o, callback, isTimeout)
2782         {
2783             if(this.isCallInProgress(o)) {
2784                 o.conn.abort();
2785                 window.clearInterval(this.poll[o.tId]);
2786                 delete this.poll[o.tId];
2787                 if (isTimeout) {
2788                     delete this.timeout[o.tId];
2789                 }
2790
2791                 this.handleTransactionResponse(o, callback, true);
2792
2793                 return true;
2794             }
2795             else {
2796                 return false;
2797             }
2798         },
2799
2800
2801         isCallInProgress:function(o)
2802         {
2803             if (o && o.conn) {
2804                 return o.conn.readyState != 4 && o.conn.readyState != 0;
2805             }
2806             else {
2807
2808                 return false;
2809             }
2810         },
2811
2812
2813         releaseObject:function(o)
2814         {
2815
2816             o.conn = null;
2817
2818             o = null;
2819         },
2820
2821         activeX:[
2822         'MSXML2.XMLHTTP.3.0',
2823         'MSXML2.XMLHTTP',
2824         'Microsoft.XMLHTTP'
2825         ]
2826
2827
2828     };
2829 })();/*
2830  * Portions of this file are based on pieces of Yahoo User Interface Library
2831  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2832  * YUI licensed under the BSD License:
2833  * http://developer.yahoo.net/yui/license.txt
2834  * <script type="text/javascript">
2835  *
2836  */
2837
2838 Roo.lib.Region = function(t, r, b, l) {
2839     this.top = t;
2840     this[1] = t;
2841     this.right = r;
2842     this.bottom = b;
2843     this.left = l;
2844     this[0] = l;
2845 };
2846
2847
2848 Roo.lib.Region.prototype = {
2849     contains : function(region) {
2850         return ( region.left >= this.left &&
2851                  region.right <= this.right &&
2852                  region.top >= this.top &&
2853                  region.bottom <= this.bottom    );
2854
2855     },
2856
2857     getArea : function() {
2858         return ( (this.bottom - this.top) * (this.right - this.left) );
2859     },
2860
2861     intersect : function(region) {
2862         var t = Math.max(this.top, region.top);
2863         var r = Math.min(this.right, region.right);
2864         var b = Math.min(this.bottom, region.bottom);
2865         var l = Math.max(this.left, region.left);
2866
2867         if (b >= t && r >= l) {
2868             return new Roo.lib.Region(t, r, b, l);
2869         } else {
2870             return null;
2871         }
2872     },
2873     union : function(region) {
2874         var t = Math.min(this.top, region.top);
2875         var r = Math.max(this.right, region.right);
2876         var b = Math.max(this.bottom, region.bottom);
2877         var l = Math.min(this.left, region.left);
2878
2879         return new Roo.lib.Region(t, r, b, l);
2880     },
2881
2882     adjust : function(t, l, b, r) {
2883         this.top += t;
2884         this.left += l;
2885         this.right += r;
2886         this.bottom += b;
2887         return this;
2888     }
2889 };
2890
2891 Roo.lib.Region.getRegion = function(el) {
2892     var p = Roo.lib.Dom.getXY(el);
2893
2894     var t = p[1];
2895     var r = p[0] + el.offsetWidth;
2896     var b = p[1] + el.offsetHeight;
2897     var l = p[0];
2898
2899     return new Roo.lib.Region(t, r, b, l);
2900 };
2901 /*
2902  * Portions of this file are based on pieces of Yahoo User Interface Library
2903  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2904  * YUI licensed under the BSD License:
2905  * http://developer.yahoo.net/yui/license.txt
2906  * <script type="text/javascript">
2907  *
2908  */
2909 //@@dep Roo.lib.Region
2910
2911
2912 Roo.lib.Point = function(x, y) {
2913     if (x instanceof Array) {
2914         y = x[1];
2915         x = x[0];
2916     }
2917     this.x = this.right = this.left = this[0] = x;
2918     this.y = this.top = this.bottom = this[1] = y;
2919 };
2920
2921 Roo.lib.Point.prototype = new Roo.lib.Region();
2922 /*
2923  * Portions of this file are based on pieces of Yahoo User Interface Library
2924  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2925  * YUI licensed under the BSD License:
2926  * http://developer.yahoo.net/yui/license.txt
2927  * <script type="text/javascript">
2928  *
2929  */
2930  
2931 (function() {   
2932
2933     Roo.lib.Anim = {
2934         scroll : function(el, args, duration, easing, cb, scope) {
2935             this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2936         },
2937
2938         motion : function(el, args, duration, easing, cb, scope) {
2939             this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2940         },
2941
2942         color : function(el, args, duration, easing, cb, scope) {
2943             this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2944         },
2945
2946         run : function(el, args, duration, easing, cb, scope, type) {
2947             type = type || Roo.lib.AnimBase;
2948             if (typeof easing == "string") {
2949                 easing = Roo.lib.Easing[easing];
2950             }
2951             var anim = new type(el, args, duration, easing);
2952             anim.animateX(function() {
2953                 Roo.callback(cb, scope);
2954             });
2955             return anim;
2956         }
2957     };
2958 })();/*
2959  * Portions of this file are based on pieces of Yahoo User Interface Library
2960  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2961  * YUI licensed under the BSD License:
2962  * http://developer.yahoo.net/yui/license.txt
2963  * <script type="text/javascript">
2964  *
2965  */
2966
2967 (function() {    
2968     var libFlyweight;
2969     
2970     function fly(el) {
2971         if (!libFlyweight) {
2972             libFlyweight = new Roo.Element.Flyweight();
2973         }
2974         libFlyweight.dom = el;
2975         return libFlyweight;
2976     }
2977
2978     // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2979     
2980    
2981     
2982     Roo.lib.AnimBase = function(el, attributes, duration, method) {
2983         if (el) {
2984             this.init(el, attributes, duration, method);
2985         }
2986     };
2987
2988     Roo.lib.AnimBase.fly = fly;
2989     
2990     
2991     
2992     Roo.lib.AnimBase.prototype = {
2993
2994         toString: function() {
2995             var el = this.getEl();
2996             var id = el.id || el.tagName;
2997             return ("Anim " + id);
2998         },
2999
3000         patterns: {
3001             noNegatives:        /width|height|opacity|padding/i,
3002             offsetAttribute:  /^((width|height)|(top|left))$/,
3003             defaultUnit:        /width|height|top$|bottom$|left$|right$/i,
3004             offsetUnit:         /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3005         },
3006
3007
3008         doMethod: function(attr, start, end) {
3009             return this.method(this.currentFrame, start, end - start, this.totalFrames);
3010         },
3011
3012
3013         setAttribute: function(attr, val, unit) {
3014             if (this.patterns.noNegatives.test(attr)) {
3015                 val = (val > 0) ? val : 0;
3016             }
3017
3018             Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3019         },
3020
3021
3022         getAttribute: function(attr) {
3023             var el = this.getEl();
3024             var val = fly(el).getStyle(attr);
3025
3026             if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3027                 return parseFloat(val);
3028             }
3029
3030             var a = this.patterns.offsetAttribute.exec(attr) || [];
3031             var pos = !!( a[3] );
3032             var box = !!( a[2] );
3033
3034
3035             if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3036                 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3037             } else {
3038                 val = 0;
3039             }
3040
3041             return val;
3042         },
3043
3044
3045         getDefaultUnit: function(attr) {
3046             if (this.patterns.defaultUnit.test(attr)) {
3047                 return 'px';
3048             }
3049
3050             return '';
3051         },
3052
3053         animateX : function(callback, scope) {
3054             var f = function() {
3055                 this.onComplete.removeListener(f);
3056                 if (typeof callback == "function") {
3057                     callback.call(scope || this, this);
3058                 }
3059             };
3060             this.onComplete.addListener(f, this);
3061             this.animate();
3062         },
3063
3064
3065         setRuntimeAttribute: function(attr) {
3066             var start;
3067             var end;
3068             var attributes = this.attributes;
3069
3070             this.runtimeAttributes[attr] = {};
3071
3072             var isset = function(prop) {
3073                 return (typeof prop !== 'undefined');
3074             };
3075
3076             if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3077                 return false;
3078             }
3079
3080             start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3081
3082
3083             if (isset(attributes[attr]['to'])) {
3084                 end = attributes[attr]['to'];
3085             } else if (isset(attributes[attr]['by'])) {
3086                 if (start.constructor == Array) {
3087                     end = [];
3088                     for (var i = 0, len = start.length; i < len; ++i) {
3089                         end[i] = start[i] + attributes[attr]['by'][i];
3090                     }
3091                 } else {
3092                     end = start + attributes[attr]['by'];
3093                 }
3094             }
3095
3096             this.runtimeAttributes[attr].start = start;
3097             this.runtimeAttributes[attr].end = end;
3098
3099
3100             this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3101         },
3102
3103
3104         init: function(el, attributes, duration, method) {
3105
3106             var isAnimated = false;
3107
3108
3109             var startTime = null;
3110
3111
3112             var actualFrames = 0;
3113
3114
3115             el = Roo.getDom(el);
3116
3117
3118             this.attributes = attributes || {};
3119
3120
3121             this.duration = duration || 1;
3122
3123
3124             this.method = method || Roo.lib.Easing.easeNone;
3125
3126
3127             this.useSeconds = true;
3128
3129
3130             this.currentFrame = 0;
3131
3132
3133             this.totalFrames = Roo.lib.AnimMgr.fps;
3134
3135
3136             this.getEl = function() {
3137                 return el;
3138             };
3139
3140
3141             this.isAnimated = function() {
3142                 return isAnimated;
3143             };
3144
3145
3146             this.getStartTime = function() {
3147                 return startTime;
3148             };
3149
3150             this.runtimeAttributes = {};
3151
3152
3153             this.animate = function() {
3154                 if (this.isAnimated()) {
3155                     return false;
3156                 }
3157
3158                 this.currentFrame = 0;
3159
3160                 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3161
3162                 Roo.lib.AnimMgr.registerElement(this);
3163             };
3164
3165
3166             this.stop = function(finish) {
3167                 if (finish) {
3168                     this.currentFrame = this.totalFrames;
3169                     this._onTween.fire();
3170                 }
3171                 Roo.lib.AnimMgr.stop(this);
3172             };
3173
3174             var onStart = function() {
3175                 this.onStart.fire();
3176
3177                 this.runtimeAttributes = {};
3178                 for (var attr in this.attributes) {
3179                     this.setRuntimeAttribute(attr);
3180                 }
3181
3182                 isAnimated = true;
3183                 actualFrames = 0;
3184                 startTime = new Date();
3185             };
3186
3187
3188             var onTween = function() {
3189                 var data = {
3190                     duration: new Date() - this.getStartTime(),
3191                     currentFrame: this.currentFrame
3192                 };
3193
3194                 data.toString = function() {
3195                     return (
3196                             'duration: ' + data.duration +
3197                             ', currentFrame: ' + data.currentFrame
3198                             );
3199                 };
3200
3201                 this.onTween.fire(data);
3202
3203                 var runtimeAttributes = this.runtimeAttributes;
3204
3205                 for (var attr in runtimeAttributes) {
3206                     this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3207                 }
3208
3209                 actualFrames += 1;
3210             };
3211
3212             var onComplete = function() {
3213                 var actual_duration = (new Date() - startTime) / 1000 ;
3214
3215                 var data = {
3216                     duration: actual_duration,
3217                     frames: actualFrames,
3218                     fps: actualFrames / actual_duration
3219                 };
3220
3221                 data.toString = function() {
3222                     return (
3223                             'duration: ' + data.duration +
3224                             ', frames: ' + data.frames +
3225                             ', fps: ' + data.fps
3226                             );
3227                 };
3228
3229                 isAnimated = false;
3230                 actualFrames = 0;
3231                 this.onComplete.fire(data);
3232             };
3233
3234
3235             this._onStart = new Roo.util.Event(this);
3236             this.onStart = new Roo.util.Event(this);
3237             this.onTween = new Roo.util.Event(this);
3238             this._onTween = new Roo.util.Event(this);
3239             this.onComplete = new Roo.util.Event(this);
3240             this._onComplete = new Roo.util.Event(this);
3241             this._onStart.addListener(onStart);
3242             this._onTween.addListener(onTween);
3243             this._onComplete.addListener(onComplete);
3244         }
3245     };
3246 })();
3247 /*
3248  * Portions of this file are based on pieces of Yahoo User Interface Library
3249  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3250  * YUI licensed under the BSD License:
3251  * http://developer.yahoo.net/yui/license.txt
3252  * <script type="text/javascript">
3253  *
3254  */
3255
3256 Roo.lib.AnimMgr = new function() {
3257
3258         var thread = null;
3259
3260
3261         var queue = [];
3262
3263
3264         var tweenCount = 0;
3265
3266
3267         this.fps = 1000;
3268
3269
3270         this.delay = 1;
3271
3272
3273         this.registerElement = function(tween) {
3274             queue[queue.length] = tween;
3275             tweenCount += 1;
3276             tween._onStart.fire();
3277             this.start();
3278         };
3279
3280
3281         this.unRegister = function(tween, index) {
3282             tween._onComplete.fire();
3283             index = index || getIndex(tween);
3284             if (index != -1) {
3285                 queue.splice(index, 1);
3286             }
3287
3288             tweenCount -= 1;
3289             if (tweenCount <= 0) {
3290                 this.stop();
3291             }
3292         };
3293
3294
3295         this.start = function() {
3296             if (thread === null) {
3297                 thread = setInterval(this.run, this.delay);
3298             }
3299         };
3300
3301
3302         this.stop = function(tween) {
3303             if (!tween) {
3304                 clearInterval(thread);
3305
3306                 for (var i = 0, len = queue.length; i < len; ++i) {
3307                     if (queue[0].isAnimated()) {
3308                         this.unRegister(queue[0], 0);
3309                     }
3310                 }
3311
3312                 queue = [];
3313                 thread = null;
3314                 tweenCount = 0;
3315             }
3316             else {
3317                 this.unRegister(tween);
3318             }
3319         };
3320
3321
3322         this.run = function() {
3323             for (var i = 0, len = queue.length; i < len; ++i) {
3324                 var tween = queue[i];
3325                 if (!tween || !tween.isAnimated()) {
3326                     continue;
3327                 }
3328
3329                 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3330                 {
3331                     tween.currentFrame += 1;
3332
3333                     if (tween.useSeconds) {
3334                         correctFrame(tween);
3335                     }
3336                     tween._onTween.fire();
3337                 }
3338                 else {
3339                     Roo.lib.AnimMgr.stop(tween, i);
3340                 }
3341             }
3342         };
3343
3344         var getIndex = function(anim) {
3345             for (var i = 0, len = queue.length; i < len; ++i) {
3346                 if (queue[i] == anim) {
3347                     return i;
3348                 }
3349             }
3350             return -1;
3351         };
3352
3353
3354         var correctFrame = function(tween) {
3355             var frames = tween.totalFrames;
3356             var frame = tween.currentFrame;
3357             var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3358             var elapsed = (new Date() - tween.getStartTime());
3359             var tweak = 0;
3360
3361             if (elapsed < tween.duration * 1000) {
3362                 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3363             } else {
3364                 tweak = frames - (frame + 1);
3365             }
3366             if (tweak > 0 && isFinite(tweak)) {
3367                 if (tween.currentFrame + tweak >= frames) {
3368                     tweak = frames - (frame + 1);
3369                 }
3370
3371                 tween.currentFrame += tweak;
3372             }
3373         };
3374     };/*
3375  * Portions of this file are based on pieces of Yahoo User Interface Library
3376  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3377  * YUI licensed under the BSD License:
3378  * http://developer.yahoo.net/yui/license.txt
3379  * <script type="text/javascript">
3380  *
3381  */
3382 Roo.lib.Bezier = new function() {
3383
3384         this.getPosition = function(points, t) {
3385             var n = points.length;
3386             var tmp = [];
3387
3388             for (var i = 0; i < n; ++i) {
3389                 tmp[i] = [points[i][0], points[i][1]];
3390             }
3391
3392             for (var j = 1; j < n; ++j) {
3393                 for (i = 0; i < n - j; ++i) {
3394                     tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3395                     tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3396                 }
3397             }
3398
3399             return [ tmp[0][0], tmp[0][1] ];
3400
3401         };
3402     };/*
3403  * Portions of this file are based on pieces of Yahoo User Interface Library
3404  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3405  * YUI licensed under the BSD License:
3406  * http://developer.yahoo.net/yui/license.txt
3407  * <script type="text/javascript">
3408  *
3409  */
3410 (function() {
3411
3412     Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3413         Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3414     };
3415
3416     Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3417
3418     var fly = Roo.lib.AnimBase.fly;
3419     var Y = Roo.lib;
3420     var superclass = Y.ColorAnim.superclass;
3421     var proto = Y.ColorAnim.prototype;
3422
3423     proto.toString = function() {
3424         var el = this.getEl();
3425         var id = el.id || el.tagName;
3426         return ("ColorAnim " + id);
3427     };
3428
3429     proto.patterns.color = /color$/i;
3430     proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3431     proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3432     proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3433     proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3434
3435
3436     proto.parseColor = function(s) {
3437         if (s.length == 3) {
3438             return s;
3439         }
3440
3441         var c = this.patterns.hex.exec(s);
3442         if (c && c.length == 4) {
3443             return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3444         }
3445
3446         c = this.patterns.rgb.exec(s);
3447         if (c && c.length == 4) {
3448             return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3449         }
3450
3451         c = this.patterns.hex3.exec(s);
3452         if (c && c.length == 4) {
3453             return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3454         }
3455
3456         return null;
3457     };
3458     // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3459     proto.getAttribute = function(attr) {
3460         var el = this.getEl();
3461         if (this.patterns.color.test(attr)) {
3462             var val = fly(el).getStyle(attr);
3463
3464             if (this.patterns.transparent.test(val)) {
3465                 var parent = el.parentNode;
3466                 val = fly(parent).getStyle(attr);
3467
3468                 while (parent && this.patterns.transparent.test(val)) {
3469                     parent = parent.parentNode;
3470                     val = fly(parent).getStyle(attr);
3471                     if (parent.tagName.toUpperCase() == 'HTML') {
3472                         val = '#fff';
3473                     }
3474                 }
3475             }
3476         } else {
3477             val = superclass.getAttribute.call(this, attr);
3478         }
3479
3480         return val;
3481     };
3482     proto.getAttribute = function(attr) {
3483         var el = this.getEl();
3484         if (this.patterns.color.test(attr)) {
3485             var val = fly(el).getStyle(attr);
3486
3487             if (this.patterns.transparent.test(val)) {
3488                 var parent = el.parentNode;
3489                 val = fly(parent).getStyle(attr);
3490
3491                 while (parent && this.patterns.transparent.test(val)) {
3492                     parent = parent.parentNode;
3493                     val = fly(parent).getStyle(attr);
3494                     if (parent.tagName.toUpperCase() == 'HTML') {
3495                         val = '#fff';
3496                     }
3497                 }
3498             }
3499         } else {
3500             val = superclass.getAttribute.call(this, attr);
3501         }
3502
3503         return val;
3504     };
3505
3506     proto.doMethod = function(attr, start, end) {
3507         var val;
3508
3509         if (this.patterns.color.test(attr)) {
3510             val = [];
3511             for (var i = 0, len = start.length; i < len; ++i) {
3512                 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3513             }
3514
3515             val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3516         }
3517         else {
3518             val = superclass.doMethod.call(this, attr, start, end);
3519         }
3520
3521         return val;
3522     };
3523
3524     proto.setRuntimeAttribute = function(attr) {
3525         superclass.setRuntimeAttribute.call(this, attr);
3526
3527         if (this.patterns.color.test(attr)) {
3528             var attributes = this.attributes;
3529             var start = this.parseColor(this.runtimeAttributes[attr].start);
3530             var end = this.parseColor(this.runtimeAttributes[attr].end);
3531
3532             if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3533                 end = this.parseColor(attributes[attr].by);
3534
3535                 for (var i = 0, len = start.length; i < len; ++i) {
3536                     end[i] = start[i] + end[i];
3537                 }
3538             }
3539
3540             this.runtimeAttributes[attr].start = start;
3541             this.runtimeAttributes[attr].end = end;
3542         }
3543     };
3544 })();
3545
3546 /*
3547  * Portions of this file are based on pieces of Yahoo User Interface Library
3548  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3549  * YUI licensed under the BSD License:
3550  * http://developer.yahoo.net/yui/license.txt
3551  * <script type="text/javascript">
3552  *
3553  */
3554 Roo.lib.Easing = {
3555
3556
3557     easeNone: function (t, b, c, d) {
3558         return c * t / d + b;
3559     },
3560
3561
3562     easeIn: function (t, b, c, d) {
3563         return c * (t /= d) * t + b;
3564     },
3565
3566
3567     easeOut: function (t, b, c, d) {
3568         return -c * (t /= d) * (t - 2) + b;
3569     },
3570
3571
3572     easeBoth: function (t, b, c, d) {
3573         if ((t /= d / 2) < 1) {
3574             return c / 2 * t * t + b;
3575         }
3576
3577         return -c / 2 * ((--t) * (t - 2) - 1) + b;
3578     },
3579
3580
3581     easeInStrong: function (t, b, c, d) {
3582         return c * (t /= d) * t * t * t + b;
3583     },
3584
3585
3586     easeOutStrong: function (t, b, c, d) {
3587         return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3588     },
3589
3590
3591     easeBothStrong: function (t, b, c, d) {
3592         if ((t /= d / 2) < 1) {
3593             return c / 2 * t * t * t * t + b;
3594         }
3595
3596         return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3597     },
3598
3599
3600
3601     elasticIn: function (t, b, c, d, a, p) {
3602         if (t == 0) {
3603             return b;
3604         }
3605         if ((t /= d) == 1) {
3606             return b + c;
3607         }
3608         if (!p) {
3609             p = d * .3;
3610         }
3611
3612         if (!a || a < Math.abs(c)) {
3613             a = c;
3614             var s = p / 4;
3615         }
3616         else {
3617             var s = p / (2 * Math.PI) * Math.asin(c / a);
3618         }
3619
3620         return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3621     },
3622
3623
3624     elasticOut: function (t, b, c, d, a, p) {
3625         if (t == 0) {
3626             return b;
3627         }
3628         if ((t /= d) == 1) {
3629             return b + c;
3630         }
3631         if (!p) {
3632             p = d * .3;
3633         }
3634
3635         if (!a || a < Math.abs(c)) {
3636             a = c;
3637             var s = p / 4;
3638         }
3639         else {
3640             var s = p / (2 * Math.PI) * Math.asin(c / a);
3641         }
3642
3643         return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3644     },
3645
3646
3647     elasticBoth: function (t, b, c, d, a, p) {
3648         if (t == 0) {
3649             return b;
3650         }
3651
3652         if ((t /= d / 2) == 2) {
3653             return b + c;
3654         }
3655
3656         if (!p) {
3657             p = d * (.3 * 1.5);
3658         }
3659
3660         if (!a || a < Math.abs(c)) {
3661             a = c;
3662             var s = p / 4;
3663         }
3664         else {
3665             var s = p / (2 * Math.PI) * Math.asin(c / a);
3666         }
3667
3668         if (t < 1) {
3669             return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3670                           Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3671         }
3672         return a * Math.pow(2, -10 * (t -= 1)) *
3673                Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3674     },
3675
3676
3677
3678     backIn: function (t, b, c, d, s) {
3679         if (typeof s == 'undefined') {
3680             s = 1.70158;
3681         }
3682         return c * (t /= d) * t * ((s + 1) * t - s) + b;
3683     },
3684
3685
3686     backOut: function (t, b, c, d, s) {
3687         if (typeof s == 'undefined') {
3688             s = 1.70158;
3689         }
3690         return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3691     },
3692
3693
3694     backBoth: function (t, b, c, d, s) {
3695         if (typeof s == 'undefined') {
3696             s = 1.70158;
3697         }
3698
3699         if ((t /= d / 2 ) < 1) {
3700             return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3701         }
3702         return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3703     },
3704
3705
3706     bounceIn: function (t, b, c, d) {
3707         return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3708     },
3709
3710
3711     bounceOut: function (t, b, c, d) {
3712         if ((t /= d) < (1 / 2.75)) {
3713             return c * (7.5625 * t * t) + b;
3714         } else if (t < (2 / 2.75)) {
3715             return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3716         } else if (t < (2.5 / 2.75)) {
3717             return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3718         }
3719         return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3720     },
3721
3722
3723     bounceBoth: function (t, b, c, d) {
3724         if (t < d / 2) {
3725             return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3726         }
3727         return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3728     }
3729 };/*
3730  * Portions of this file are based on pieces of Yahoo User Interface Library
3731  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3732  * YUI licensed under the BSD License:
3733  * http://developer.yahoo.net/yui/license.txt
3734  * <script type="text/javascript">
3735  *
3736  */
3737     (function() {
3738         Roo.lib.Motion = function(el, attributes, duration, method) {
3739             if (el) {
3740                 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3741             }
3742         };
3743
3744         Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3745
3746
3747         var Y = Roo.lib;
3748         var superclass = Y.Motion.superclass;
3749         var proto = Y.Motion.prototype;
3750
3751         proto.toString = function() {
3752             var el = this.getEl();
3753             var id = el.id || el.tagName;
3754             return ("Motion " + id);
3755         };
3756
3757         proto.patterns.points = /^points$/i;
3758
3759         proto.setAttribute = function(attr, val, unit) {
3760             if (this.patterns.points.test(attr)) {
3761                 unit = unit || 'px';
3762                 superclass.setAttribute.call(this, 'left', val[0], unit);
3763                 superclass.setAttribute.call(this, 'top', val[1], unit);
3764             } else {
3765                 superclass.setAttribute.call(this, attr, val, unit);
3766             }
3767         };
3768
3769         proto.getAttribute = function(attr) {
3770             if (this.patterns.points.test(attr)) {
3771                 var val = [
3772                         superclass.getAttribute.call(this, 'left'),
3773                         superclass.getAttribute.call(this, 'top')
3774                         ];
3775             } else {
3776                 val = superclass.getAttribute.call(this, attr);
3777             }
3778
3779             return val;
3780         };
3781
3782         proto.doMethod = function(attr, start, end) {
3783             var val = null;
3784
3785             if (this.patterns.points.test(attr)) {
3786                 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3787                 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3788             } else {
3789                 val = superclass.doMethod.call(this, attr, start, end);
3790             }
3791             return val;
3792         };
3793
3794         proto.setRuntimeAttribute = function(attr) {
3795             if (this.patterns.points.test(attr)) {
3796                 var el = this.getEl();
3797                 var attributes = this.attributes;
3798                 var start;
3799                 var control = attributes['points']['control'] || [];
3800                 var end;
3801                 var i, len;
3802
3803                 if (control.length > 0 && !(control[0] instanceof Array)) {
3804                     control = [control];
3805                 } else {
3806                     var tmp = [];
3807                     for (i = 0,len = control.length; i < len; ++i) {
3808                         tmp[i] = control[i];
3809                     }
3810                     control = tmp;
3811                 }
3812
3813                 Roo.fly(el).position();
3814
3815                 if (isset(attributes['points']['from'])) {
3816                     Roo.lib.Dom.setXY(el, attributes['points']['from']);
3817                 }
3818                 else {
3819                     Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3820                 }
3821
3822                 start = this.getAttribute('points');
3823
3824
3825                 if (isset(attributes['points']['to'])) {
3826                     end = translateValues.call(this, attributes['points']['to'], start);
3827
3828                     var pageXY = Roo.lib.Dom.getXY(this.getEl());
3829                     for (i = 0,len = control.length; i < len; ++i) {
3830                         control[i] = translateValues.call(this, control[i], start);
3831                     }
3832
3833
3834                 } else if (isset(attributes['points']['by'])) {
3835                     end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3836
3837                     for (i = 0,len = control.length; i < len; ++i) {
3838                         control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3839                     }
3840                 }
3841
3842                 this.runtimeAttributes[attr] = [start];
3843
3844                 if (control.length > 0) {
3845                     this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3846                 }
3847
3848                 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3849             }
3850             else {
3851                 superclass.setRuntimeAttribute.call(this, attr);
3852             }
3853         };
3854
3855         var translateValues = function(val, start) {
3856             var pageXY = Roo.lib.Dom.getXY(this.getEl());
3857             val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3858
3859             return val;
3860         };
3861
3862         var isset = function(prop) {
3863             return (typeof prop !== 'undefined');
3864         };
3865     })();
3866 /*
3867  * Portions of this file are based on pieces of Yahoo User Interface Library
3868  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3869  * YUI licensed under the BSD License:
3870  * http://developer.yahoo.net/yui/license.txt
3871  * <script type="text/javascript">
3872  *
3873  */
3874     (function() {
3875         Roo.lib.Scroll = function(el, attributes, duration, method) {
3876             if (el) {
3877                 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3878             }
3879         };
3880
3881         Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3882
3883
3884         var Y = Roo.lib;
3885         var superclass = Y.Scroll.superclass;
3886         var proto = Y.Scroll.prototype;
3887
3888         proto.toString = function() {
3889             var el = this.getEl();
3890             var id = el.id || el.tagName;
3891             return ("Scroll " + id);
3892         };
3893
3894         proto.doMethod = function(attr, start, end) {
3895             var val = null;
3896
3897             if (attr == 'scroll') {
3898                 val = [
3899                         this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3900                         this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3901                         ];
3902
3903             } else {
3904                 val = superclass.doMethod.call(this, attr, start, end);
3905             }
3906             return val;
3907         };
3908
3909         proto.getAttribute = function(attr) {
3910             var val = null;
3911             var el = this.getEl();
3912
3913             if (attr == 'scroll') {
3914                 val = [ el.scrollLeft, el.scrollTop ];
3915             } else {
3916                 val = superclass.getAttribute.call(this, attr);
3917             }
3918
3919             return val;
3920         };
3921
3922         proto.setAttribute = function(attr, val, unit) {
3923             var el = this.getEl();
3924
3925             if (attr == 'scroll') {
3926                 el.scrollLeft = val[0];
3927                 el.scrollTop = val[1];
3928             } else {
3929                 superclass.setAttribute.call(this, attr, val, unit);
3930             }
3931         };
3932     })();
3933 /*
3934  * Based on:
3935  * Ext JS Library 1.1.1
3936  * Copyright(c) 2006-2007, Ext JS, LLC.
3937  *
3938  * Originally Released Under LGPL - original licence link has changed is not relivant.
3939  *
3940  * Fork - LGPL
3941  * <script type="text/javascript">
3942  */
3943  
3944
3945 /**
3946  * @class Roo.DomHelper
3947  * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3948  * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
3949  * @singleton
3950  */
3951 Roo.DomHelper = function(){
3952     var tempTableEl = null;
3953     var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3954     var tableRe = /^table|tbody|tr|td$/i;
3955     var xmlns = {};
3956     // build as innerHTML where available
3957     /** @ignore */
3958     var createHtml = function(o){
3959         if(typeof o == 'string'){
3960             return o;
3961         }
3962         var b = "";
3963         if(!o.tag){
3964             o.tag = "div";
3965         }
3966         b += "<" + o.tag;
3967         for(var attr in o){
3968             if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3969             if(attr == "style"){
3970                 var s = o["style"];
3971                 if(typeof s == "function"){
3972                     s = s.call();
3973                 }
3974                 if(typeof s == "string"){
3975                     b += ' style="' + s + '"';
3976                 }else if(typeof s == "object"){
3977                     b += ' style="';
3978                     for(var key in s){
3979                         if(typeof s[key] != "function"){
3980                             b += key + ":" + s[key] + ";";
3981                         }
3982                     }
3983                     b += '"';
3984                 }
3985             }else{
3986                 if(attr == "cls"){
3987                     b += ' class="' + o["cls"] + '"';
3988                 }else if(attr == "htmlFor"){
3989                     b += ' for="' + o["htmlFor"] + '"';
3990                 }else{
3991                     b += " " + attr + '="' + o[attr] + '"';
3992                 }
3993             }
3994         }
3995         if(emptyTags.test(o.tag)){
3996             b += "/>";
3997         }else{
3998             b += ">";
3999             var cn = o.children || o.cn;
4000             if(cn){
4001                 //http://bugs.kde.org/show_bug.cgi?id=71506
4002                 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4003                     for(var i = 0, len = cn.length; i < len; i++) {
4004                         b += createHtml(cn[i], b);
4005                     }
4006                 }else{
4007                     b += createHtml(cn, b);
4008                 }
4009             }
4010             if(o.html){
4011                 b += o.html;
4012             }
4013             b += "</" + o.tag + ">";
4014         }
4015         return b;
4016     };
4017
4018     // build as dom
4019     /** @ignore */
4020     var createDom = function(o, parentNode){
4021          
4022         // defininition craeted..
4023         var ns = false;
4024         if (o.ns && o.ns != 'html') {
4025                
4026             if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4027                 xmlns[o.ns] = o.xmlns;
4028                 ns = o.xmlns;
4029             }
4030             if (typeof(xmlns[o.ns]) == 'undefined') {
4031                 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4032             }
4033             ns = xmlns[o.ns];
4034         }
4035         
4036         
4037         if (typeof(o) == 'string') {
4038             return parentNode.appendChild(document.createTextNode(o));
4039         }
4040         o.tag = o.tag || div;
4041         if (o.ns && Roo.isIE) {
4042             ns = false;
4043             o.tag = o.ns + ':' + o.tag;
4044             
4045         }
4046         var el = ns ? document.createElementNS( ns, o.tag||'div') :  document.createElement(o.tag||'div');
4047         var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4048         for(var attr in o){
4049             
4050             if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" || 
4051                     attr == "style" || typeof o[attr] == "function") continue;
4052                     
4053             if(attr=="cls" && Roo.isIE){
4054                 el.className = o["cls"];
4055             }else{
4056                 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4057                 else el[attr] = o[attr];
4058             }
4059         }
4060         Roo.DomHelper.applyStyles(el, o.style);
4061         var cn = o.children || o.cn;
4062         if(cn){
4063             //http://bugs.kde.org/show_bug.cgi?id=71506
4064              if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4065                 for(var i = 0, len = cn.length; i < len; i++) {
4066                     createDom(cn[i], el);
4067                 }
4068             }else{
4069                 createDom(cn, el);
4070             }
4071         }
4072         if(o.html){
4073             el.innerHTML = o.html;
4074         }
4075         if(parentNode){
4076            parentNode.appendChild(el);
4077         }
4078         return el;
4079     };
4080
4081     var ieTable = function(depth, s, h, e){
4082         tempTableEl.innerHTML = [s, h, e].join('');
4083         var i = -1, el = tempTableEl;
4084         while(++i < depth){
4085             el = el.firstChild;
4086         }
4087         return el;
4088     };
4089
4090     // kill repeat to save bytes
4091     var ts = '<table>',
4092         te = '</table>',
4093         tbs = ts+'<tbody>',
4094         tbe = '</tbody>'+te,
4095         trs = tbs + '<tr>',
4096         tre = '</tr>'+tbe;
4097
4098     /**
4099      * @ignore
4100      * Nasty code for IE's broken table implementation
4101      */
4102     var insertIntoTable = function(tag, where, el, html){
4103         if(!tempTableEl){
4104             tempTableEl = document.createElement('div');
4105         }
4106         var node;
4107         var before = null;
4108         if(tag == 'td'){
4109             if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4110                 return;
4111             }
4112             if(where == 'beforebegin'){
4113                 before = el;
4114                 el = el.parentNode;
4115             } else{
4116                 before = el.nextSibling;
4117                 el = el.parentNode;
4118             }
4119             node = ieTable(4, trs, html, tre);
4120         }
4121         else if(tag == 'tr'){
4122             if(where == 'beforebegin'){
4123                 before = el;
4124                 el = el.parentNode;
4125                 node = ieTable(3, tbs, html, tbe);
4126             } else if(where == 'afterend'){
4127                 before = el.nextSibling;
4128                 el = el.parentNode;
4129                 node = ieTable(3, tbs, html, tbe);
4130             } else{ // INTO a TR
4131                 if(where == 'afterbegin'){
4132                     before = el.firstChild;
4133                 }
4134                 node = ieTable(4, trs, html, tre);
4135             }
4136         } else if(tag == 'tbody'){
4137             if(where == 'beforebegin'){
4138                 before = el;
4139                 el = el.parentNode;
4140                 node = ieTable(2, ts, html, te);
4141             } else if(where == 'afterend'){
4142                 before = el.nextSibling;
4143                 el = el.parentNode;
4144                 node = ieTable(2, ts, html, te);
4145             } else{
4146                 if(where == 'afterbegin'){
4147                     before = el.firstChild;
4148                 }
4149                 node = ieTable(3, tbs, html, tbe);
4150             }
4151         } else{ // TABLE
4152             if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4153                 return;
4154             }
4155             if(where == 'afterbegin'){
4156                 before = el.firstChild;
4157             }
4158             node = ieTable(2, ts, html, te);
4159         }
4160         el.insertBefore(node, before);
4161         return node;
4162     };
4163
4164     return {
4165     /** True to force the use of DOM instead of html fragments @type Boolean */
4166     useDom : false,
4167
4168     /**
4169      * Returns the markup for the passed Element(s) config
4170      * @param {Object} o The Dom object spec (and children)
4171      * @return {String}
4172      */
4173     markup : function(o){
4174         return createHtml(o);
4175     },
4176
4177     /**
4178      * Applies a style specification to an element
4179      * @param {String/HTMLElement} el The element to apply styles to
4180      * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4181      * a function which returns such a specification.
4182      */
4183     applyStyles : function(el, styles){
4184         if(styles){
4185            el = Roo.fly(el);
4186            if(typeof styles == "string"){
4187                var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4188                var matches;
4189                while ((matches = re.exec(styles)) != null){
4190                    el.setStyle(matches[1], matches[2]);
4191                }
4192            }else if (typeof styles == "object"){
4193                for (var style in styles){
4194                   el.setStyle(style, styles[style]);
4195                }
4196            }else if (typeof styles == "function"){
4197                 Roo.DomHelper.applyStyles(el, styles.call());
4198            }
4199         }
4200     },
4201
4202     /**
4203      * Inserts an HTML fragment into the Dom
4204      * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4205      * @param {HTMLElement} el The context element
4206      * @param {String} html The HTML fragmenet
4207      * @return {HTMLElement} The new node
4208      */
4209     insertHtml : function(where, el, html){
4210         where = where.toLowerCase();
4211         if(el.insertAdjacentHTML){
4212             if(tableRe.test(el.tagName)){
4213                 var rs;
4214                 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4215                     return rs;
4216                 }
4217             }
4218             switch(where){
4219                 case "beforebegin":
4220                     el.insertAdjacentHTML('BeforeBegin', html);
4221                     return el.previousSibling;
4222                 case "afterbegin":
4223                     el.insertAdjacentHTML('AfterBegin', html);
4224                     return el.firstChild;
4225                 case "beforeend":
4226                     el.insertAdjacentHTML('BeforeEnd', html);
4227                     return el.lastChild;
4228                 case "afterend":
4229                     el.insertAdjacentHTML('AfterEnd', html);
4230                     return el.nextSibling;
4231             }
4232             throw 'Illegal insertion point -> "' + where + '"';
4233         }
4234         var range = el.ownerDocument.createRange();
4235         var frag;
4236         switch(where){
4237              case "beforebegin":
4238                 range.setStartBefore(el);
4239                 frag = range.createContextualFragment(html);
4240                 el.parentNode.insertBefore(frag, el);
4241                 return el.previousSibling;
4242              case "afterbegin":
4243                 if(el.firstChild){
4244                     range.setStartBefore(el.firstChild);
4245                     frag = range.createContextualFragment(html);
4246                     el.insertBefore(frag, el.firstChild);
4247                     return el.firstChild;
4248                 }else{
4249                     el.innerHTML = html;
4250                     return el.firstChild;
4251                 }
4252             case "beforeend":
4253                 if(el.lastChild){
4254                     range.setStartAfter(el.lastChild);
4255                     frag = range.createContextualFragment(html);
4256                     el.appendChild(frag);
4257                     return el.lastChild;
4258                 }else{
4259                     el.innerHTML = html;
4260                     return el.lastChild;
4261                 }
4262             case "afterend":
4263                 range.setStartAfter(el);
4264                 frag = range.createContextualFragment(html);
4265                 el.parentNode.insertBefore(frag, el.nextSibling);
4266                 return el.nextSibling;
4267             }
4268             throw 'Illegal insertion point -> "' + where + '"';
4269     },
4270
4271     /**
4272      * Creates new Dom element(s) and inserts them before el
4273      * @param {String/HTMLElement/Element} el The context element
4274      * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4275      * @param {Boolean} returnElement (optional) true to return a Roo.Element
4276      * @return {HTMLElement/Roo.Element} The new node
4277      */
4278     insertBefore : function(el, o, returnElement){
4279         return this.doInsert(el, o, returnElement, "beforeBegin");
4280     },
4281
4282     /**
4283      * Creates new Dom element(s) and inserts them after el
4284      * @param {String/HTMLElement/Element} el The context element
4285      * @param {Object} o The Dom object spec (and children)
4286      * @param {Boolean} returnElement (optional) true to return a Roo.Element
4287      * @return {HTMLElement/Roo.Element} The new node
4288      */
4289     insertAfter : function(el, o, returnElement){
4290         return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4291     },
4292
4293     /**
4294      * Creates new Dom element(s) and inserts them as the first child of el
4295      * @param {String/HTMLElement/Element} el The context element
4296      * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4297      * @param {Boolean} returnElement (optional) true to return a Roo.Element
4298      * @return {HTMLElement/Roo.Element} The new node
4299      */
4300     insertFirst : function(el, o, returnElement){
4301         return this.doInsert(el, o, returnElement, "afterBegin");
4302     },
4303
4304     // private
4305     doInsert : function(el, o, returnElement, pos, sibling){
4306         el = Roo.getDom(el);
4307         var newNode;
4308         if(this.useDom || o.ns){
4309             newNode = createDom(o, null);
4310             el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4311         }else{
4312             var html = createHtml(o);
4313             newNode = this.insertHtml(pos, el, html);
4314         }
4315         return returnElement ? Roo.get(newNode, true) : newNode;
4316     },
4317
4318     /**
4319      * Creates new Dom element(s) and appends them to el
4320      * @param {String/HTMLElement/Element} el The context element
4321      * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4322      * @param {Boolean} returnElement (optional) true to return a Roo.Element
4323      * @return {HTMLElement/Roo.Element} The new node
4324      */
4325     append : function(el, o, returnElement){
4326         el = Roo.getDom(el);
4327         var newNode;
4328         if(this.useDom || o.ns){
4329             newNode = createDom(o, null);
4330             el.appendChild(newNode);
4331         }else{
4332             var html = createHtml(o);
4333             newNode = this.insertHtml("beforeEnd", el, html);
4334         }
4335         return returnElement ? Roo.get(newNode, true) : newNode;
4336     },
4337
4338     /**
4339      * Creates new Dom element(s) and overwrites the contents of el with them
4340      * @param {String/HTMLElement/Element} el The context element
4341      * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4342      * @param {Boolean} returnElement (optional) true to return a Roo.Element
4343      * @return {HTMLElement/Roo.Element} The new node
4344      */
4345     overwrite : function(el, o, returnElement){
4346         el = Roo.getDom(el);
4347         if (o.ns) {
4348           
4349             while (el.childNodes.length) {
4350                 el.removeChild(el.firstChild);
4351             }
4352             createDom(o, el);
4353         } else {
4354             el.innerHTML = createHtml(o);   
4355         }
4356         
4357         return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4358     },
4359
4360     /**
4361      * Creates a new Roo.DomHelper.Template from the Dom object spec
4362      * @param {Object} o The Dom object spec (and children)
4363      * @return {Roo.DomHelper.Template} The new template
4364      */
4365     createTemplate : function(o){
4366         var html = createHtml(o);
4367         return new Roo.Template(html);
4368     }
4369     };
4370 }();