]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/yui/ext/yui-ext.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / yui / ext / yui-ext.js
1 /*
2  * yui-ext 0.33
3  * Copyright(c) 2006, Jack Slocum.
4  *
5  * Redistribution and use in source and binary forms, with or without modification, 
6  * are permitted provided that the following conditions are met:
7  * 
8  *     * Redistributions of source code must retain the above copyright notice, 
9  *       this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above copyright notice, 
11  *       this list of conditions and the following disclaimer in the documentation 
12  *       and/or other materials provided with the distribution.
13  *     * Neither the name yui-ext nor the names of its contributors 
14  *       may be used to endorse or promote products derived from this software 
15  *       without specific prior written permission.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 YAHOO.namespace('ext', 'ext.util', 'ext.grid');
30 YAHOO.ext.Strict = (document.compatMode == 'CSS1Compat');
31 YAHOO.ext.SSL_SECURE_URL = 'javascript:false';
32
33 window.undefined = undefined;
34
35  
36  
37 Function.prototype.createCallback = function(){
38     
39     var args = arguments;
40     var method = this;
41     return function() {
42         return method.apply(window, args);
43     };
44 };
45
46
47 Function.prototype.createDelegate = function(obj, args, appendArgs){
48     var method = this;
49     return function() {
50         var callArgs = args || arguments;
51         if(appendArgs === true){
52             callArgs = Array.prototype.slice.call(arguments, 0);
53             callArgs = callArgs.concat(args);
54         }else if(typeof appendArgs == 'number'){
55             callArgs = Array.prototype.slice.call(arguments, 0); 
56             var applyArgs = [appendArgs, 0].concat(args); 
57             Array.prototype.splice.apply(callArgs, applyArgs); 
58         }
59         return method.apply(obj || window, callArgs);
60     };
61 };
62
63
64 Function.prototype.defer = function(millis, obj, args, appendArgs){
65     return setTimeout(this.createDelegate(obj, args, appendArgs), millis);
66 };
67
68 Function.prototype.createSequence = function(fcn, scope){
69     if(typeof fcn != 'function'){
70         return this;
71     }
72     var method = this;
73     return function() {
74         var retval = method.apply(this || window, arguments);
75         fcn.apply(scope || this || window, arguments);
76         return retval;
77     };
78 };
79
80
81 YAHOO.util.Event.on(window, 'unload', function(){
82     delete Function.prototype.createSequence;
83     delete Function.prototype.defer;
84     delete Function.prototype.createDelegate;
85     delete Function.prototype.createCallback;
86     delete Function.prototype.createInterceptor;
87 });
88
89
90 Function.prototype.createInterceptor = function(fcn, scope){
91     if(typeof fcn != 'function'){
92         return this;
93     }
94     var method = this;
95     return function() {
96         fcn.target = this;
97         fcn.method = method;
98         if(fcn.apply(scope || this || window, arguments) === false){
99             return;
100         }
101         return method.apply(this || window, arguments);;
102     };
103 };
104
105
106 YAHOO.ext.util.Browser = new function(){
107         var ua = navigator.userAgent.toLowerCase();
108         
109         this.isOpera = (ua.indexOf('opera') > -1);
110         
111         this.isSafari = (ua.indexOf('webkit') > -1);
112         
113         this.isIE = (window.ActiveXObject);
114         
115         this.isIE7 = (ua.indexOf('msie 7') > -1);
116         
117         this.isGecko = !this.isSafari && (ua.indexOf('gecko') > -1);
118         
119         if(ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1){
120             
121             this.isWindows = true;
122         }else if(ua.indexOf("macintosh") != -1){
123                 
124             this.isMac = true;
125         }
126         if(this.isIE && !this.isIE7){
127         try{
128             document.execCommand("BackgroundImageCache", false, true);
129         }catch(e){}
130     }
131 }();
132
133 YAHOO.print = function(arg1, arg2, etc){
134     if(!YAHOO.ext._console){
135         var cs = YAHOO.ext.DomHelper.insertBefore(document.body.firstChild,
136         {tag: 'div',style:'width:250px;height:350px;overflow:auto;border:3px solid #c3daf9;' +
137                 'background:white;position:absolute;right:5px;top:5px;' +
138                 'font:normal 8pt arial,verdana,helvetica;z-index:50000;padding:5px;'}, true);
139         new YAHOO.ext.Resizable(cs, {
140             transparent:true,
141             handles: 'all',
142             pinned:true, 
143             adjustments: [0,0], 
144             wrap:true, 
145             draggable:(YAHOO.util.DD ? true : false)
146         });
147         cs.on('dblclick', cs.hide);
148         YAHOO.ext._console = cs;
149     }
150     var msg = '';
151     for(var i = 0, len = arguments.length; i < len; i++) {
152         msg += arguments[i] + '<hr noshade style="color:#eeeeee;" size="1">';
153     }
154     YAHOO.ext._console.dom.innerHTML = msg + YAHOO.ext._console.dom.innerHTML;
155     YAHOO.ext._console.dom.scrollTop = 0;
156     YAHOO.ext._console.show();
157 };
158
159 YAHOO.printf = function(format, arg1, arg2, etc){
160     var args = Array.prototype.slice.call(arguments, 1);
161     YAHOO.print(format.replace(
162       /\{\{[^{}]*\}\}|\{(\d+)(,\s*([\w.]+))?\}/g,
163       function(m, a1, a2, a3) {
164         if (m.chatAt == '{') {
165           return m.slice(1, -1);
166         }
167         var rpl = args[a1];
168         if (a3) {
169           var f = eval(a3);
170           rpl = f(rpl);
171         }
172         return rpl ? rpl : '';
173       }));
174 }
175
176  
177 YAHOO.util.CustomEvent.prototype.fireDirect = function(){
178     var len=this.subscribers.length;
179     for (var i=0; i<len; ++i) {
180         var s = this.subscribers[i];
181         if(s){
182             var scope = (s.override) ? s.obj : this.scope;
183             if(s.fn.apply(scope, arguments) === false){
184                 return false;
185             }
186         }
187     }
188     return true;
189 };
190
191 YAHOO.extendX = function(subclass, superclass, overrides){
192     YAHOO.extend(subclass, superclass);
193     subclass.override = function(o){
194         YAHOO.override(subclass, o);
195     };
196     if(!subclass.prototype.override){
197         subclass.prototype.override = function(o){
198             for(var method in o){
199                 this[method] = o[method];
200             }  
201         };
202     }
203     if(overrides){
204         subclass.override(overrides);
205     }
206 };
207
208 YAHOO.override = function(origclass, overrides){
209     if(overrides){
210         var p = origclass.prototype;
211         for(var method in overrides){
212             p[method] = overrides[method];
213         }
214     }
215 };
216
217
218 YAHOO.ext.util.DelayedTask = function(fn, scope, args){
219     var timeoutId = null;
220     
221     
222     this.delay = function(delay, newFn, newScope, newArgs){
223         if(timeoutId){
224             clearTimeout(timeoutId);
225         }
226         fn = newFn || fn;
227         scope = newScope || scope;
228         args = newArgs || args;
229         timeoutId = setTimeout(fn.createDelegate(scope, args), delay);
230     };
231     
232     
233     this.cancel = function(){
234         if(timeoutId){
235             clearTimeout(timeoutId);
236             timeoutId = null;
237         }
238     };
239 };
240
241
242 YAHOO.ext.KeyMap = function(el, config, eventName){
243     this.el  = getEl(el);
244     this.eventName = eventName || 'keydown';
245     this.bindings = [];
246     if(config instanceof Array){
247             for(var i = 0, len = config.length; i < len; i++){
248                 this.addBinding(config[i]);
249             }
250     }else{
251         this.addBinding(config);
252     }
253     this.keyDownDelegate = YAHOO.ext.EventManager.wrap(this.handleKeyDown, this, true);
254     this.enable();
255 }
256
257 YAHOO.ext.KeyMap.prototype = {
258     
259         addBinding : function(config){
260         var keyCode = config.key, 
261             shift = config.shift, 
262             ctrl = config.ctrl, 
263             alt = config.alt,
264             fn = config.fn,
265             scope = config.scope;
266         if(typeof keyCode == 'string'){
267             var ks = [];
268             var keyString = keyCode.toUpperCase();
269             for(var j = 0, len = keyString.length; j < len; j++){
270                 ks.push(keyString.charCodeAt(j));
271             }
272             keyCode = ks;
273         }        
274         var keyArray = keyCode instanceof Array;
275         var handler = function(e){
276             if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
277                 var k = e.getKey();
278                 if(keyArray){
279                     for(var i = 0, len = keyCode.length; i < len; i++){
280                         if(keyCode[i] == k){
281                           fn.call(scope || window, k, e);
282                           return;
283                         }
284                     }
285                 }else{
286                     if(k == keyCode){
287                         fn.call(scope || window, k, e);
288                     }
289                 }
290             }
291         };
292         this.bindings.push(handler);  
293         },
294         
295         handleKeyDown : function(e){
296             if(this.enabled){ 
297             var b = this.bindings;
298             for(var i = 0, len = b.length; i < len; i++){
299                 b[i](e);
300             }
301             }
302         },
303         
304         
305         isEnabled : function(){
306             return this.enabled;  
307         },
308         
309         
310         enable: function(){
311                 if (!this.enabled){
312                 this.el.on(this.eventName, this.keyDownDelegate);
313                     this.enabled = true;
314                 }
315         },
316
317         
318         disable: function(){
319                 if (this.enabled){
320                         this.el.removeListener(this.eventName, this.keyDownDelegate);
321                     this.enabled = false;
322                 }
323         }
324 };
325
326
327 YAHOO.ext.util.Observable = function(){};
328 YAHOO.ext.util.Observable.prototype = {
329     
330     fireEvent : function(){
331         var ce = this.events[arguments[0].toLowerCase()];
332         if(typeof ce == 'object'){
333             return ce.fireDirect.apply(ce, Array.prototype.slice.call(arguments, 1));
334         }else{
335             return true;
336         }
337     },
338     
339     addListener : function(eventName, fn, scope, override){
340         eventName = eventName.toLowerCase();
341         var ce = this.events[eventName];
342         if(!ce){
343             
344             throw 'You are trying to listen for an event that does not exist: "' + eventName + '".';
345         }
346         if(typeof ce == 'boolean'){
347             ce = new YAHOO.util.CustomEvent(eventName);
348             this.events[eventName] = ce;
349         }
350         ce.subscribe(fn, scope, override);
351     },
352     
353     
354     delayedListener : function(eventName, fn, scope, delay){
355         var newFn = function(){
356             setTimeout(fn.createDelegate(scope, arguments), delay || 1);
357         }
358         this.addListener(eventName, newFn);
359         return newFn;
360     },
361     
362     
363     bufferedListener : function(eventName, fn, scope, millis){
364         var task = new YAHOO.ext.util.DelayedTask();
365         var newFn = function(){
366             task.delay(millis || 250, fn, scope, Array.prototype.slice.call(arguments, 0));
367         }
368         this.addListener(eventName, newFn);
369         return newFn;
370     },
371     
372     
373     removeListener : function(eventName, fn, scope){
374         var ce = this.events[eventName.toLowerCase()];
375         if(typeof ce == 'object'){
376             ce.unsubscribe(fn, scope);
377         }
378     },
379     
380     
381     purgeListeners : function(){
382         for(var evt in this.events){
383             if(typeof this.events[evt] == 'object'){
384                  this.events[evt].unsubscribeAll();
385             }
386         }
387     }
388 };
389
390 YAHOO.ext.util.Observable.prototype.on = YAHOO.ext.util.Observable.prototype.addListener;
391
392
393 YAHOO.ext.util.Config = {
394     
395     apply : function(obj, config, defaults){
396         if(defaults){
397             this.apply(obj, defaults);
398         }
399         if(config){
400             for(var prop in config){
401                 obj[prop] = config[prop];
402             }
403         }
404         return obj;
405     }
406 };
407
408 if(!String.escape){
409     String.escape = function(string) {
410         return string.replace(/('|\\)/g, "\\$1");
411     };
412 };
413
414 String.leftPad = function (val, size, ch) {
415     var result = new String(val);
416     if (ch == null) {
417         ch = " ";
418     }
419     while (result.length < size) {
420         result = ch + result;
421     }
422     return result;
423 };
424
425 /*
426 if(YAHOO.util.Connect){
427     YAHOO.util.Connect.setHeader = function(o){
428                 for(var prop in this._http_header){
429                     
430                         if(typeof this._http_header[prop] != 'function'){
431                                 o.conn.setRequestHeader(prop, this._http_header[prop]);
432                         }
433                 }
434                 delete this._http_header;
435                 this._http_header = {};
436                 this._has_http_headers = false;
437         };   
438 }
439 */
440 if(YAHOO.util.DragDrop){
441     
442     YAHOO.util.DragDrop.prototype.defaultPadding = {left:0, right:0, top:0, bottom:0};
443     
444     
445     YAHOO.util.DragDrop.prototype.constrainTo = function(constrainTo, pad, inContent){
446         if(typeof pad == 'number'){
447             pad = {left: pad, right:pad, top:pad, bottom:pad};
448         }
449         pad = pad || this.defaultPadding;
450         var b = getEl(this.getEl()).getBox();
451         var ce = getEl(constrainTo);
452         var c = ce.dom == document.body ? { x: 0, y: 0,
453                 width: YAHOO.util.Dom.getViewportWidth(),
454                 height: YAHOO.util.Dom.getViewportHeight()} : ce.getBox(inContent || false);
455         var topSpace = b.y - c.y;
456         var leftSpace = b.x - c.x;
457
458         this.resetConstraints();
459         this.setXConstraint(leftSpace - (pad.left||0), 
460                 c.width - leftSpace - b.width - (pad.right||0) 
461         );
462         this.setYConstraint(topSpace - (pad.top||0), 
463                 c.height - topSpace - b.height - (pad.bottom||0) 
464         );
465     } 
466 }
467
468 YAHOO.ext.util.MixedCollection = function(allowFunctions){
469     this.items = [];
470     this.keys = [];
471     this.events = {
472         
473         'clear' : new YAHOO.util.CustomEvent('clear'),
474         
475         'add' : new YAHOO.util.CustomEvent('add'),
476         
477         'replace' : new YAHOO.util.CustomEvent('replace'),
478         
479         'remove' : new YAHOO.util.CustomEvent('remove')
480     }
481     this.allowFunctions = allowFunctions === true;
482 };
483
484 YAHOO.extendX(YAHOO.ext.util.MixedCollection, YAHOO.ext.util.Observable, {
485     allowFunctions : false,
486    
487
488     add : function(key, o){
489         if(arguments.length == 1){
490             o = arguments[0];
491             key = this.getKey(o);
492         }
493         this.items.push(o);
494         if(typeof key != 'undefined' && key != null){
495             this.items[key] = o;
496             this.keys.push(key);
497         }
498         this.fireEvent('add', this.items.length-1, o, key);
499         return o;
500     },
501    
502
503     getKey : function(o){
504          return null; 
505     },
506    
507
508     replace : function(key, o){
509         if(arguments.length == 1){
510             o = arguments[0];
511             key = this.getKey(o);
512         }
513         if(typeof this.items[key] == 'undefined'){
514             return this.add(key, o);
515         }
516         var old = this.items[key];
517         if(typeof key == 'number'){ 
518             this.items[key] = o;
519         }else{
520             var index = this.indexOfKey(key);
521             this.items[index] = o;
522             this.items[key] = o;
523         }
524         this.fireEvent('replace', key, old, o);
525         return o;
526     },
527    
528
529     addAll : function(objs){
530         if(arguments.length > 1 || objs instanceof Array){
531             var args = arguments.length > 1 ? arguments : objs;
532             for(var i = 0, len = args.length; i < len; i++){
533                 this.add(args[i]);
534             }
535         }else{
536             for(var key in objs){
537                 if(this.allowFunctions || typeof objs[key] != 'function'){
538                     this.add(objs[key], key);
539                 }
540             }
541         }
542     },
543    
544
545     each : function(fn, scope){
546         for(var i = 0, len = this.items.length; i < len; i++){
547             fn.call(scope || window, this.items[i]);
548         }
549     },
550    
551
552     eachKey : function(fn, scope){
553         for(var i = 0, len = this.keys.length; i < len; i++){
554             fn.call(scope || window, this.keys[i], this.items[i]);
555         }
556     },
557    
558
559     find : function(fn, scope){
560         for(var i = 0, len = this.items.length; i < len; i++){
561             if(fn.call(scope || window, this.items[i])){
562                 return this.items[i];
563             }
564         }
565         return null;
566     },
567    
568
569     insert : function(index, key, o){
570         if(arguments.length == 2){
571             o = arguments[1];
572             key = this.getKey(o);
573         }
574         if(index >= this.items.length){
575             return this.add(o, key);
576         }
577         this.items.splice(index, 0, o);
578         if(typeof key != 'undefined' && key != null){
579             this.items[key] = o;
580             this.keys.splice(index, 0, key);
581         }
582         this.fireEvent('add', index, o, key);
583         return o;
584     },
585    
586
587     remove : function(o){
588         var index = this.indexOf(o);
589         this.items.splice(index, 1);
590         if(typeof this.keys[index] != 'undefined'){
591             var key = this.keys[index];
592             this.keys.splice(index, 1);
593             delete this.items[key];
594         }
595         this.fireEvent('remove', o);
596         return o;
597     },
598    
599
600     removeAt : function(index){
601         this.items.splice(index, 1);
602         var key = this.keys[index];
603         if(typeof key != 'undefined'){
604              this.keys.splice(index, 1);
605              delete this.items[key];
606         }
607         this.fireEvent('remove', o, key);
608     },
609    
610
611     removeKey : function(key){
612         var o = this.items[key];
613         var index = this.indexOf(o);
614         this.items.splice(index, 1);
615         this.keys.splice(index, 1);
616         delete this.items[key];
617         this.fireEvent('remove', o, key);
618     },
619    
620
621     getCount : function(){
622         return this.items.length; 
623     },
624    
625
626     indexOf : function(o){
627         if(!this.items.indexOf){
628             for(var i = 0, len = this.items.length; i < len; i++){
629                 if(this.items[i] == o) return i;
630             }
631             return -1;
632         }else{
633             return this.items.indexOf(o);
634         }
635     },
636    
637
638     indexOfKey : function(key){
639         if(!this.keys.indexOf){
640             for(var i = 0, len = this.keys.length; i < len; i++){
641                 if(this.keys[i] == key) return i;
642             }
643             return -1;
644         }else{
645             return this.keys.indexOf(key);
646         }
647     },
648    
649
650     item : function(key){
651         return this.items[key];
652     },
653    
654
655     contains : function(o){
656         return this.indexOf(o) != -1;
657     },
658    
659
660     containsKey : function(key){
661         return typeof this.items[key] != 'undefined';
662     },
663    
664
665     clear : function(o){
666         this.items = [];
667         this.keys = [];
668         this.fireEvent('clear');
669     },
670    
671
672     first : function(){
673         return this.items[0]; 
674     },
675    
676
677     last : function(){
678         return this.items[this.items.length];   
679     }
680 });
681
682 YAHOO.ext.util.MixedCollection.prototype.get = YAHOO.ext.util.MixedCollection.prototype.item;
683
684 YAHOO.ext.util.JSON = new function(){
685     var useHasOwn = {}.hasOwnProperty ? true : false;
686     
687     
688     
689     
690     var pad = function(n) {
691         return n < 10 ? '0' + n : n;
692     };
693     
694     var m = {
695         '\b': '\\b',
696         '\t': '\\t',
697         '\n': '\\n',
698         '\f': '\\f',
699         '\r': '\\r',
700         '"' : '\\"',
701         '\\': '\\\\'
702     };
703
704     var encodeString = function(s){
705         if (/["\\\x00-\x1f]/.test(s)) {
706             return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
707                 var c = m[b];
708                 if(c){
709                     return c;
710                 }
711                 c = b.charCodeAt();
712                 return '\\u00' +
713                     Math.floor(c / 16).toString(16) +
714                     (c % 16).toString(16);
715             }) + '"';
716         }
717         return '"' + s + '"';
718     };
719     
720     var encodeArray = function(o){
721         var a = ['['], b, i, l = o.length, v;
722             for (i = 0; i < l; i += 1) {
723                 v = o[i];
724                 switch (typeof v) {
725                     case 'undefined':
726                     case 'function':
727                     case 'unknown':
728                         break;
729                     default:
730                         if (b) {
731                             a.push(',');
732                         }
733                         a.push(v === null ? "null" : YAHOO.ext.util.JSON.encode(v));
734                         b = true;
735                 }
736             }
737             a.push(']');
738             return a.join('');
739     };
740     
741     var encodeDate = function(o){
742         return '"' + o.getFullYear() + '-' +
743                 pad(o.getMonth() + 1) + '-' +
744                 pad(o.getDate()) + 'T' +
745                 pad(o.getHours()) + ':' +
746                 pad(o.getMinutes()) + ':' +
747                 pad(o.getSeconds()) + '"';
748     };
749     
750     
751     this.encode = function(o){
752         if(typeof o == 'undefined' || o === null){
753             return 'null';
754         }else if(o instanceof Array){
755             return encodeArray(o);
756         }else if(o instanceof Date){
757             return encodeDate(o);
758         }else if(typeof o == 'string'){
759             return encodeString(o);
760         }else if(typeof o == 'number'){
761             return isFinite(o) ? String(o) : "null";
762         }else if(typeof o == 'boolean'){
763             return String(o);
764         }else {
765             var a = ['{'], b, i, v;
766             for (var i in o) {
767                 if(!useHasOwn || o.hasOwnProperty(i)) {
768                     v = o[i];
769                     switch (typeof v) {
770                     case 'undefined':
771                     case 'function':
772                     case 'unknown':
773                         break;
774                     default:
775                         if(b){
776                             a.push(',');
777                         }
778                         a.push(this.encode(i), ':',
779                                 v === null ? "null" : this.encode(v));
780                         b = true;
781                     }
782                 }
783             }
784             a.push('}');
785             return a.join('');
786         }
787     };
788     
789     
790     this.decode = function(json){
791         
792         
793             
794                 return eval('(' + json + ')');
795            
796        
797        
798        
799     };
800 }();
801
802 YAHOO.ext.util.CSS = new function(){
803         var rules = null;
804         
805         var toCamel = function(property) {
806       var convert = function(prop) {
807          var test = /(-[a-z])/i.exec(prop);
808          return prop.replace(RegExp.$1, RegExp.$1.substr(1).toUpperCase());
809       };
810       while(property.indexOf('-') > -1) {
811          property = convert(property);
812       }
813       return property;
814    };
815    
816    
817    this.getRules = function(refreshCache){
818                 if(rules == null || refreshCache){
819                         rules = {};
820                         var ds = document.styleSheets;
821                         for(var i =0, len = ds.length; i < len; i++){
822                             try{
823                         var ss = ds[i];
824                         var ssRules = ss.cssRules || ss.rules;
825                         for(var j = ssRules.length-1; j >= 0; --j){
826                                 rules[ssRules[j].selectorText] = ssRules[j];
827                         }
828                             }catch(e){} 
829                 }
830                 }
831                 return rules;
832         };
833         
834         
835    this.getRule = function(selector, refreshCache){
836                 var rs = this.getRules(refreshCache);
837                 if(!(selector instanceof Array)){
838                     return rs[selector];
839                 }
840                 for(var i = 0; i < selector.length; i++){
841                         if(rs[selector[i]]){
842                                 return rs[selector[i]];
843                         }
844                 }
845                 return null;
846         };
847         
848         
849         
850    this.updateRule = function(selector, property, value){
851                 if(!(selector instanceof Array)){
852                         var rule = this.getRule(selector);
853                         if(rule){
854                                 rule.style[toCamel(property)] = value;
855                                 return true;
856                         }
857                 }else{
858                         for(var i = 0; i < selector.length; i++){
859                                 if(this.updateRule(selector[i], property, value)){
860                                         return true;
861                                 }
862                         }
863                 }
864                 return false;
865         };
866         
867         
868    this.apply = function(el, selector){
869                 if(!(selector instanceof Array)){
870                         var rule = this.getRule(selector);
871                         if(rule){
872                             var s = rule.style;
873                                 for(var key in s){
874                                     if(typeof s[key] != 'function'){
875                                         if(s[key] && String(s[key]).indexOf(':') < 0 && s[key] != 'false'){
876                                                 try{el.style[key] = s[key];}catch(e){}
877                                         }
878                                     }
879                                 }
880                                 return true;
881                         }
882                 }else{
883                         for(var i = 0; i < selector.length; i++){
884                                 if(this.apply(el, selector[i])){
885                                         return true;
886                                 }
887                         }
888                 }
889                 return false;
890         };
891         
892         this.applyFirst = function(el, id, selector){
893                 var selectors = [
894                         '#' + id + ' ' + selector,
895                         selector
896                 ];
897                 return this.apply(el, selectors);
898         };
899         
900         this.revert = function(el, selector){
901                 if(!(selector instanceof Array)){
902                         var rule = this.getRule(selector);
903                         if(rule){
904                                 for(key in rule.style){
905                                         if(rule.style[key] && String(rule.style[key]).indexOf(':') < 0 && rule.style[key] != 'false'){
906                                                 try{el.style[key] = '';}catch(e){}
907                                         }
908                                 }
909                                 return true;
910                         }
911                 }else{
912                         for(var i = 0; i < selector.length; i++){
913                                 if(this.revert(el, selector[i])){
914                                         return true;
915                                 }
916                         }
917                 }
918                 return false;
919         };
920         
921         this.revertFirst = function(el, id, selector){
922                 var selectors = [
923                         '#' + id + ' ' + selector,
924                         selector
925                 ];
926                 return this.revert(el, selectors);
927         };
928 }();
929 YAHOO.ext.util.Bench = function(){
930    this.timers = {};
931    this.lastKey = null;
932 };
933 YAHOO.ext.util.Bench.prototype = {
934    start : function(key){
935        this.lastKey = key;
936        this.timers[key] = {};
937        this.timers[key].startTime = new Date().getTime(); 
938    },
939    
940    stop : function(key){
941        key = key || this.lastKey;
942        this.timers[key].endTime = new Date().getTime(); 
943    },
944    
945    getElapsed : function(key){
946        key = key || this.lastKey;
947        return this.timers[key].endTime - this.timers[key].startTime;
948    },
949    
950    toString : function(html){
951        var results = "";
952        for(var key in this.timers){
953            if(typeof this.timers[key] != 'function'){
954                results += key + ":\t" + (this.getElapsed(key) / 1000) + " seconds\n";
955            }
956        }
957        if(html){
958            results = results.replace("\n", '<br>');
959        }
960        return results;
961    },
962    
963    show : function(){
964        alert(this.toString());
965    }
966 };
967
968 YAHOO.ext.DomHelper = new function(){
969     
970     var d = document;
971     var tempTableEl = null;
972     
973     this.useDom = false;
974     var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i;
975     
976     this.applyStyles = function(el, styles){
977         if(styles){
978            var D = YAHOO.util.Dom;
979            if (typeof styles == "string"){
980                var re = /\s?([a-z\-]*)\:([^;]*);?/gi;
981                var matches;
982                while ((matches = re.exec(styles)) != null){
983                    D.setStyle(el, matches[1], matches[2]);
984                }
985            }else if (typeof styles == "object"){
986                for (var style in styles){
987                   D.setStyle(el, style, styles[style]);
988                }
989            }else if (typeof styles == "function"){
990                 YAHOO.ext.DomHelper.applyStyles(el, styles.call());
991            }
992         }
993     }; 
994     
995     
996     
997     var createHtml = function(o){
998         var b = '';
999         b += '<' + o.tag;
1000         for(var attr in o){
1001             if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue;
1002             if(attr == 'style'){
1003                 var s = o['style'];
1004                 if(typeof s == 'function'){
1005                     s = s.call();
1006                 }
1007                 if(typeof s == 'string'){
1008                     b += ' style="' + s + '"';
1009                 }else if(typeof s == 'object'){
1010                     b += ' style="';
1011                     for(var key in s){
1012                         if(typeof s[key] != 'function'){
1013                             b += key + ':' + s[key] + ';';
1014                         }
1015                     }
1016                     b += '"';
1017                 }
1018             }else{
1019                 if(attr == 'cls'){
1020                     b += ' class="' + o['cls'] + '"';
1021                 }else if(attr == 'htmlFor'){
1022                     b += ' for="' + o['htmlFor'] + '"';
1023                 }else{
1024                     b += ' ' + attr + '="' + o[attr] + '"';
1025                 }
1026             }
1027         }
1028         if(emptyTags.test(o.tag)){
1029             b += ' />';
1030         }else{
1031             b += '>';
1032             if(o.children){
1033                 for(var i = 0, len = o.children.length; i < len; i++) {
1034                     b += createHtml(o.children[i], b);
1035                 }
1036             }
1037             if(o.html){
1038                 b += o.html;
1039             }
1040             b += '</' + o.tag + '>';
1041         }
1042         return b;
1043     }
1044     
1045     
1046     
1047     var createDom = function(o, parentNode){
1048         var el = d.createElement(o.tag);
1049         var useSet = el.setAttribute ? true : false; 
1050         for(var attr in o){
1051             if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue;
1052             if(attr=='cls'){
1053                 el.className = o['cls'];
1054             }else{
1055                 if(useSet) el.setAttribute(attr, o[attr]);
1056                 else el[attr] = o[attr];
1057             }
1058         }
1059         YAHOO.ext.DomHelper.applyStyles(el, o.style);
1060         if(o.children){
1061             for(var i = 0, len = o.children.length; i < len; i++) {
1062                 createDom(o.children[i], el);
1063             }
1064         }
1065         if(o.html){
1066             el.innerHTML = o.html;
1067         }
1068         if(parentNode){
1069            parentNode.appendChild(el);
1070         }
1071         return el;
1072     };
1073     
1074     
1075     var insertIntoTable = function(tag, where, el, html){
1076         if(!tempTableEl){
1077             tempTableEl = document.createElement('div');
1078         }
1079         var node;
1080         if(tag == 'table' || tag == 'tbody'){
1081            tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>';
1082            node = tempTableEl.firstChild.firstChild.firstChild;
1083         }else{
1084            tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
1085            node = tempTableEl.firstChild.firstChild.firstChild.firstChild;
1086         }
1087         if(where == 'beforebegin'){
1088             el.parentNode.insertBefore(node, el);
1089             return node;
1090         }else if(where == 'afterbegin'){
1091             el.insertBefore(node, el.firstChild);
1092             return node;
1093         }else if(where == 'beforeend'){
1094             el.appendChild(node);
1095             return node;
1096         }else if(where == 'afterend'){
1097             el.parentNode.insertBefore(node, el.nextSibling);
1098             return node;
1099         }
1100     } 
1101     
1102     
1103     this.insertHtml = function(where, el, html){
1104         where = where.toLowerCase();
1105         if(el.insertAdjacentHTML){
1106             var tag = el.tagName.toLowerCase();
1107             if(tag == 'table' || tag == 'tbody' || tag == 'tr'){
1108                return insertIntoTable(tag, where, el, html);
1109             }
1110             switch(where){
1111                 case 'beforebegin':
1112                     el.insertAdjacentHTML(where, html);
1113                     return el.previousSibling;
1114                 case 'afterbegin':
1115                     el.insertAdjacentHTML(where, html);
1116                     return el.firstChild;
1117                 case 'beforeend':
1118                     el.insertAdjacentHTML(where, html);
1119                     return el.lastChild;
1120                 case 'afterend':
1121                     el.insertAdjacentHTML(where, html);
1122                     return el.nextSibling;
1123             }
1124             throw 'Illegal insertion point -> "' + where + '"';
1125         }
1126         var range = el.ownerDocument.createRange();
1127         var frag;
1128         switch(where){
1129              case 'beforebegin':
1130                 range.setStartBefore(el);
1131                 frag = range.createContextualFragment(html);
1132                 el.parentNode.insertBefore(frag, el);
1133                 return el.previousSibling;
1134              case 'afterbegin':
1135                 if(el.firstChild){ 
1136                     range.setStartBefore(el.firstChild);
1137                 }else{
1138                     range.selectNodeContents(el);
1139                     range.collapse(true);
1140                 }
1141                 frag = range.createContextualFragment(html);
1142                 el.insertBefore(frag, el.firstChild);
1143                 return el.firstChild;
1144             case 'beforeend':
1145                 if(el.lastChild){
1146                     range.setStartAfter(el.lastChild); 
1147                 }else{
1148                     range.selectNodeContents(el);
1149                     range.collapse(false);
1150                 }
1151                 frag = range.createContextualFragment(html);
1152                 el.appendChild(frag);
1153                 return el.lastChild;
1154             case 'afterend':
1155                 range.setStartAfter(el);
1156                 frag = range.createContextualFragment(html);
1157                 el.parentNode.insertBefore(frag, el.nextSibling);
1158                 return el.nextSibling;
1159             }
1160             throw 'Illegal insertion point -> "' + where + '"';
1161     };
1162     
1163     
1164     this.insertBefore = function(el, o, returnElement){
1165         el = YAHOO.util.Dom.get(el);
1166         var newNode;
1167         if(this.useDom){
1168             newNode = createDom(o, null);
1169             el.parentNode.insertBefore(newNode, el);
1170         }else{
1171             var html = createHtml(o);
1172             newNode = this.insertHtml('beforeBegin', el, html);
1173         }
1174         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1175     };
1176     
1177     
1178     this.insertAfter = function(el, o, returnElement){
1179         el = YAHOO.util.Dom.get(el);
1180         var newNode;
1181         if(this.useDom){
1182             newNode = createDom(o, null);
1183             el.parentNode.insertBefore(newNode, el.nextSibling);
1184         }else{
1185             var html = createHtml(o);
1186             newNode = this.insertHtml('afterEnd', el, html);
1187         }
1188         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1189     };
1190     
1191     
1192     this.append = function(el, o, returnElement){
1193         el = YAHOO.util.Dom.get(el);
1194         var newNode;
1195         if(this.useDom){
1196             newNode = createDom(o, null);
1197             el.appendChild(newNode);
1198         }else{
1199             var html = createHtml(o);
1200             newNode = this.insertHtml('beforeEnd', el, html);
1201         }
1202         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1203     };
1204     
1205     
1206     this.overwrite = function(el, o, returnElement){
1207         el = YAHOO.util.Dom.get(el);
1208         el.innerHTML = createHtml(o);
1209         return returnElement ? YAHOO.ext.Element.get(el.firstChild, true) : el.firstChild;
1210     };
1211     
1212     
1213     this.createTemplate = function(o){
1214         var html = createHtml(o);
1215         return new YAHOO.ext.DomHelper.Template(html);
1216     };
1217 }();
1218
1219
1220 YAHOO.ext.DomHelper.Template = function(html){
1221     
1222     this.html = html;
1223 };
1224 YAHOO.ext.DomHelper.Template.prototype = {
1225     
1226     applyTemplate : function(values){
1227         if(this.compiled){
1228             return this.compiled(values);
1229         }
1230         var empty = '';
1231         var fn = function(match, index){
1232             if(typeof values[index] != 'undefined'){
1233                 return values[index];
1234             }else{
1235                 return empty;
1236             }
1237         }
1238         return this.html.replace(this.re, fn);
1239     },
1240     
1241     
1242     re : /\{(\w+)\}/g,
1243     
1244     
1245     compile : function(){
1246         var html = this.html;
1247         var re = this.re;
1248         var body = [];
1249         body.push("this.compiled = function(values){ return [");
1250         var result;
1251         var lastMatchEnd = 0;
1252         while ((result = re.exec(html)) != null){
1253             body.push("'", html.substring(lastMatchEnd, result.index), "', ");
1254             body.push("values['", html.substring(result.index+1,re.lastIndex-1), "'], ");
1255             lastMatchEnd = re.lastIndex;
1256         }
1257         body.push("'", html.substr(lastMatchEnd), "'].join('');};");
1258         eval(body.join(''));
1259     },
1260    
1261     
1262     insertBefore: function(el, values, returnElement){
1263         el = YAHOO.util.Dom.get(el);
1264         var newNode = YAHOO.ext.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values));
1265         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1266     },
1267     
1268     
1269     insertAfter : function(el, values, returnElement){
1270         el = YAHOO.util.Dom.get(el);
1271         var newNode = YAHOO.ext.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values));
1272         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1273     },
1274     
1275     
1276     append : function(el, values, returnElement){
1277         el = YAHOO.util.Dom.get(el);
1278         var newNode = YAHOO.ext.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values));
1279         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1280     },
1281     
1282     
1283     overwrite : function(el, values, returnElement){
1284         el = YAHOO.util.Dom.get(el);
1285         el.innerHTML = '';
1286         var newNode = YAHOO.ext.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values));
1287         return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode;
1288     }
1289 };
1290
1291 YAHOO.ext.Template = YAHOO.ext.DomHelper.Template;
1292
1293 YAHOO.ext.Element = function(element, forceNew){
1294     var dom = YAHOO.util.Dom.get(element);
1295     if(!dom){ 
1296         return null;
1297     }
1298     if(!forceNew && YAHOO.ext.Element.cache[dom.id]){ 
1299         return YAHOO.ext.Element.cache[dom.id];
1300     }
1301     
1302     this.dom = dom;
1303     
1304     
1305     this.id = this.dom.id;
1306     
1307     this.visibilityMode = YAHOO.ext.Element.VISIBILITY;
1308     
1309     
1310     
1311     this.originalDisplay = YAHOO.util.Dom.getStyle(this.dom, 'display') || '';
1312     if(this.autoDisplayMode){
1313         if(this.originalDisplay == 'none'){
1314             this.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
1315         }
1316     }
1317     if(this.originalDisplay == 'none'){
1318         this.originalDisplay = '';
1319     }
1320     
1321     
1322     this.defaultUnit = 'px';
1323 }
1324
1325 YAHOO.ext.Element.prototype = {    
1326     
1327     setVisibilityMode : function(visMode){
1328         this.visibilityMode = visMode;
1329         return this;
1330     },
1331     
1332     
1333     enableDisplayMode : function(display){
1334         this.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
1335         if(typeof display != 'undefined') this.originalDisplay = display;
1336         return this;
1337     },
1338     
1339     
1340     animate : function(args, duration, onComplete, easing, animType){
1341         this.anim(args, duration, onComplete, easing, animType);
1342         return this;
1343     },
1344     
1345     
1346     anim : function(args, duration, onComplete, easing, animType){
1347         animType = animType || YAHOO.util.Anim;
1348         var anim = new animType(this.dom, args, duration || .35, 
1349                 easing || YAHOO.util.Easing.easeBoth);
1350         if(onComplete){
1351             if(!(onComplete instanceof Array)){
1352                 anim.onComplete.subscribe(onComplete, this, true);
1353             }else{
1354                 for(var i = 0; i < onComplete.length; i++){
1355                     var fn = onComplete[i];
1356                     if(fn) anim.onComplete.subscribe(fn, this, true);
1357                 }
1358             }
1359         }
1360         anim.animate();
1361     },
1362     
1363     
1364     scrollIntoView : function(container){
1365         var c = getEl(container || document.body, true);
1366         var cp = c.getStyle('position');
1367         var restorePos = false;
1368         if(cp != 'relative' && cp != 'absolute'){
1369             c.setStyle('position', 'relative');
1370             restorePos = true;
1371         }
1372         var el = this.dom;
1373         var childTop = parseInt(el.offsetTop, 10);
1374         var childBottom = childTop + el.offsetHeight;
1375         var containerTop = parseInt(c.scrollTop, 10); 
1376         var containerBottom = containerTop + c.clientHeight;
1377         if(childTop < containerTop){
1378                 c.scrollTop = childTop;
1379         }else if(childBottom > containerBottom){
1380             c.scrollTop = childBottom-c.clientHeight;
1381         }
1382         if(restorePos){
1383             c.setStyle('position', cp);
1384         }
1385         return this;
1386     },
1387         
1388     
1389     autoHeight : function(animate, duration, onComplete, easing){
1390         var oldHeight = this.getHeight();
1391         this.clip();
1392         this.setHeight(1); 
1393         setTimeout(function(){
1394             var height = parseInt(this.dom.scrollHeight, 10); 
1395             if(!animate){
1396                 this.setHeight(height);
1397                 this.unclip();
1398                 if(typeof onComplete == 'function'){
1399                     onComplete();
1400                 }
1401             }else{
1402                 this.setHeight(oldHeight); 
1403                 this.setHeight(height, animate, duration, function(){
1404                     this.unclip();
1405                     if(typeof onComplete == 'function') onComplete();
1406                 }.createDelegate(this), easing);
1407             }
1408         }.createDelegate(this), 0);
1409         return this;
1410     },
1411     
1412     
1413     isVisible : function(deep) {
1414         var vis = YAHOO.util.Dom.getStyle(this.dom, 'visibility') != 'hidden' 
1415                && YAHOO.util.Dom.getStyle(this.dom, 'display') != 'none';
1416         if(!deep || !vis){
1417             return vis;
1418         }
1419         var p = this.dom.parentNode;
1420         while(p && p.tagName.toLowerCase() != 'body'){
1421             if(YAHOO.util.Dom.getStyle(p, 'visibility') == 'hidden' || YAHOO.util.Dom.getStyle(p, 'display') == 'none'){
1422                 return false;
1423             }
1424             p = p.parentNode;
1425         }
1426         return true;
1427     },
1428     
1429     
1430     select : function(selector, unique){
1431         return YAHOO.ext.Element.select('#' + this.dom.id + ' ' + selector, unique);  
1432     },
1433     
1434     
1435     initDD : function(group, config, overrides){
1436         var dd = new YAHOO.util.DD(YAHOO.util.Dom.generateId(this.dom), group, config);
1437         return YAHOO.ext.util.Config.apply(dd, overrides);
1438     },
1439    
1440     
1441     initDDProxy : function(group, config, overrides){
1442         var dd = new YAHOO.util.DDProxy(YAHOO.util.Dom.generateId(this.dom), group, config);
1443         return YAHOO.ext.util.Config.apply(dd, overrides);
1444     },
1445    
1446     
1447     initDDTarget : function(group, config, overrides){
1448         var dd = new YAHOO.util.DDTarget(YAHOO.util.Dom.generateId(this.dom), group, config);
1449         return YAHOO.ext.util.Config.apply(dd, overrides);
1450     },
1451    
1452     
1453      setVisible : function(visible, animate, duration, onComplete, easing){
1454         
1455         if(!animate || !YAHOO.util.Anim){
1456             if(this.visibilityMode == YAHOO.ext.Element.DISPLAY){
1457                 this.setDisplayed(visible);
1458             }else{
1459                 YAHOO.util.Dom.setStyle(this.dom, 'visibility', visible ? 'visible' : 'hidden');
1460             }
1461         }else{
1462             
1463             this.setOpacity(visible?0:1);
1464             YAHOO.util.Dom.setStyle(this.dom, 'visibility', 'visible');
1465             if(this.visibilityMode == YAHOO.ext.Element.DISPLAY){
1466                 this.setDisplayed(true);
1467             }
1468             var args = {opacity: { from: (visible?0:1), to: (visible?1:0) }};
1469             var anim = new YAHOO.util.Anim(this.dom, args, duration || .35, 
1470                 easing || (visible ? YAHOO.util.Easing.easeIn : YAHOO.util.Easing.easeOut));
1471             anim.onComplete.subscribe((function(){
1472                 if(this.visibilityMode == YAHOO.ext.Element.DISPLAY){
1473                     this.setDisplayed(visible);
1474                 }else{
1475                     YAHOO.util.Dom.setStyle(this.dom, 'visibility', visible ? 'visible' : 'hidden');
1476                 }
1477             }).createDelegate(this));
1478             if(onComplete){
1479                 anim.onComplete.subscribe(onComplete);
1480             }
1481             anim.animate();
1482         }
1483         return this;
1484     },
1485     
1486     
1487     isDisplayed : function() {
1488         return YAHOO.util.Dom.getStyle(this.dom, 'display') != 'none';
1489     },
1490     
1491     
1492     toggle : function(animate, duration, onComplete, easing){
1493         this.setVisible(!this.isVisible(), animate, duration, onComplete, easing);
1494         return this;
1495     },
1496     
1497     
1498     setDisplayed : function(value) {
1499         if(typeof value == 'boolean'){
1500            value = value ? this.originalDisplay : 'none';
1501         }
1502         YAHOO.util.Dom.setStyle(this.dom, 'display', value);
1503         return this;
1504     },
1505     
1506     
1507     focus : function() {
1508         try{
1509             this.dom.focus();
1510         }catch(e){}
1511         return this;
1512     },
1513     
1514     
1515     blur : function() {
1516         try{
1517             this.dom.blur();
1518         }catch(e){}
1519         return this;
1520     },
1521     
1522     
1523     addClass : function(className){
1524         if(className instanceof Array){
1525             for(var i = 0, len = className.length; i < len; i++) {
1526                 this.addClass(className[i]);
1527             }
1528         }else{
1529             if(!this.hasClass(className)){
1530                 this.dom.className = this.dom.className + ' ' + className;
1531             }
1532         }
1533         return this;
1534     },
1535     
1536     
1537     radioClass : function(className){
1538         var siblings = this.dom.parentNode.childNodes;
1539         for(var i = 0; i < siblings.length; i++) {
1540                 var s = siblings[i];
1541                 if(s.nodeType == 1){
1542                     YAHOO.util.Dom.removeClass(s, className);
1543                 }
1544         }
1545         this.addClass(className);
1546         return this;
1547     },
1548     
1549     removeClass : function(className){
1550         if(className instanceof Array){
1551             for(var i = 0, len = className.length; i < len; i++) {
1552                 this.removeClass(className[i]);
1553             }
1554         }else{
1555             var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g');
1556             var c = this.dom.className;
1557             if(re.test(c)){
1558                 this.dom.className = c.replace(re, ' ');
1559             }
1560         }
1561         return this;
1562     },
1563     
1564     
1565     toggleClass : function(className){
1566         if(this.hasClass(className)){
1567             this.removeClass(className);
1568         }else{
1569             this.addClass(className);
1570         }
1571         return this;
1572     },
1573     
1574     
1575     hasClass : function(className){
1576         var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
1577         return re.test(this.dom.className);
1578     },
1579     
1580     
1581     replaceClass : function(oldClassName, newClassName){
1582         this.removeClass(oldClassName);
1583         this.addClass(newClassName);
1584         return this;
1585     },
1586     
1587     
1588     getStyle : function(name){
1589         return YAHOO.util.Dom.getStyle(this.dom, name);
1590     },
1591     
1592     
1593     setStyle : function(name, value){
1594         if(typeof name == 'string'){
1595             YAHOO.util.Dom.setStyle(this.dom, name, value);
1596         }else{
1597             var D = YAHOO.util.Dom;
1598             for(var style in name){
1599                 if(typeof name[style] != 'function'){
1600                    D.setStyle(this.dom, style, name[style]);
1601                 }
1602             }
1603         }
1604         return this;
1605     },
1606     
1607     
1608     applyStyles : function(style){
1609        YAHOO.ext.DomHelper.applyStyles(this.dom, style);
1610     },
1611     
1612     
1613     getX : function(){
1614         return YAHOO.util.Dom.getX(this.dom);
1615     },
1616     
1617     
1618     getY : function(){
1619         return YAHOO.util.Dom.getY(this.dom);
1620     },
1621     
1622     
1623     getXY : function(){
1624         return YAHOO.util.Dom.getXY(this.dom);
1625     },
1626     
1627     
1628     setX : function(x, animate, duration, onComplete, easing){
1629         if(!animate || !YAHOO.util.Anim){
1630             YAHOO.util.Dom.setX(this.dom, x);
1631         }else{
1632             this.setXY([x, this.getY()], animate, duration, onComplete, easing);
1633         }
1634         return this;
1635     },
1636     
1637     
1638     setY : function(y, animate, duration, onComplete, easing){
1639         if(!animate || !YAHOO.util.Anim){
1640             YAHOO.util.Dom.setY(this.dom, y);
1641         }else{
1642             this.setXY([this.getX(), y], animate, duration, onComplete, easing);
1643         }
1644         return this;
1645     },
1646     
1647     
1648     setLeft : function(left){
1649         YAHOO.util.Dom.setStyle(this.dom, 'left', this.addUnits(left));
1650         return this;
1651     },
1652     
1653     
1654     setTop : function(top){
1655         YAHOO.util.Dom.setStyle(this.dom, 'top', this.addUnits(top));
1656         return this;
1657     },
1658     
1659     
1660     setRight : function(right){
1661         YAHOO.util.Dom.setStyle(this.dom, 'right', this.addUnits(right));
1662         return this;
1663     },
1664     
1665     
1666     setBottom : function(bottom){
1667         YAHOO.util.Dom.setStyle(this.dom, 'bottom', this.addUnits(bottom));
1668         return this;
1669     },
1670     
1671     
1672     setXY : function(pos, animate, duration, onComplete, easing){
1673         if(!animate || !YAHOO.util.Anim){
1674             YAHOO.util.Dom.setXY(this.dom, pos);
1675         }else{
1676             this.anim({points: {to: pos}}, duration, onComplete, easing, YAHOO.util.Motion);
1677         }
1678         return this;
1679     },
1680     
1681     
1682     setLocation : function(x, y, animate, duration, onComplete, easing){
1683         this.setXY([x, y], animate, duration, onComplete, easing);
1684         return this;
1685     },
1686     
1687     
1688     moveTo : function(x, y, animate, duration, onComplete, easing){
1689         
1690         
1691         this.setXY([x, y], animate, duration, onComplete, easing);
1692         return this;
1693     },
1694     
1695     
1696     getRegion : function(){
1697         return YAHOO.util.Dom.getRegion(this.dom);
1698     },
1699     
1700     
1701     getHeight : function(contentHeight){
1702         var h = this.dom.offsetHeight;
1703         return contentHeight !== true ? h : h-this.getBorderWidth('tb')-this.getPadding('tb');
1704     },
1705     
1706     
1707     getWidth : function(contentWidth){
1708         var w = this.dom.offsetWidth;
1709         return contentWidth !== true ? w : w-this.getBorderWidth('lr')-this.getPadding('lr');
1710     },
1711     
1712     
1713     getSize : function(contentSize){
1714         return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
1715     },
1716     
1717     
1718     adjustWidth : function(width){
1719         if(typeof width == 'number'){
1720             if(this.autoBoxAdjust && !this.isBorderBox()){
1721                width -= (this.getBorderWidth('lr') + this.getPadding('lr'));
1722             }
1723             if(width < 0){
1724                 width = 0;
1725             }
1726         }
1727         return width;
1728     },
1729     
1730     
1731     adjustHeight : function(height){
1732         if(typeof height == 'number'){
1733            if(this.autoBoxAdjust && !this.isBorderBox()){
1734                height -= (this.getBorderWidth('tb') + this.getPadding('tb'));
1735            }
1736            if(height < 0){
1737                height = 0;
1738            }
1739         }
1740         return height;
1741     },
1742     
1743     
1744     setWidth : function(width, animate, duration, onComplete, easing){
1745         width = this.adjustWidth(width);
1746         if(!animate || !YAHOO.util.Anim){
1747             YAHOO.util.Dom.setStyle(this.dom, 'width', this.addUnits(width));
1748         }else{
1749             this.anim({width: {to: width}}, duration, onComplete, 
1750                 easing || (width > this.getWidth() ? YAHOO.util.Easing.easeOut : YAHOO.util.Easing.easeIn));
1751         }
1752         return this;
1753     },
1754     
1755     
1756      setHeight : function(height, animate, duration, onComplete, easing){
1757         height = this.adjustHeight(height);
1758         if(!animate || !YAHOO.util.Anim){
1759             YAHOO.util.Dom.setStyle(this.dom, 'height', this.addUnits(height));
1760         }else{
1761             this.anim({height: {to: height}}, duration, onComplete,  
1762                    easing || (height > this.getHeight() ? YAHOO.util.Easing.easeOut : YAHOO.util.Easing.easeIn));
1763         }
1764         return this;
1765     },
1766     
1767     
1768      setSize : function(width, height, animate, duration, onComplete, easing){
1769         if(!animate || !YAHOO.util.Anim){
1770             this.setWidth(width);
1771             this.setHeight(height);
1772         }else{
1773             width = this.adjustWidth(width); height = this.adjustHeight(height);
1774             this.anim({width: {to: width}, height: {to: height}}, duration, onComplete, easing);
1775         }
1776         return this;
1777     },
1778     
1779     
1780     setBounds : function(x, y, width, height, animate, duration, onComplete, easing){
1781         if(!animate || !YAHOO.util.Anim){
1782             this.setWidth(width);
1783             this.setHeight(height);
1784             this.setLocation(x, y);
1785         }else{
1786             width = this.adjustWidth(width); height = this.adjustHeight(height);
1787             this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}}, duration, onComplete, easing, YAHOO.util.Motion);
1788         }
1789         return this;
1790     },
1791     
1792     
1793     setRegion : function(region, animate, duration, onComplete, easing){
1794         this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, animate, duration, onComplete, easing);
1795         return this;
1796     },
1797     
1798     
1799     addListener : function(eventName, handler, scope, override){
1800         YAHOO.util.Event.addListener(this.dom, eventName, handler, scope || this, true);
1801         return this;
1802     },
1803     
1804     bufferedListener : function(eventName, fn, scope, millis){
1805         var task = new YAHOO.ext.util.DelayedTask();
1806         scope = scope || this;
1807         var newFn = function(){
1808             task.delay(millis || 250, fn, scope, Array.prototype.slice.call(arguments, 0));
1809         }
1810         this.addListener(eventName, newFn);
1811         return newFn;
1812     },
1813     
1814     
1815     
1816     addHandler : function(eventName, stopPropagation, handler, scope, override){
1817         var fn = YAHOO.ext.Element.createStopHandler(stopPropagation, handler, scope || this, true);
1818         YAHOO.util.Event.addListener(this.dom, eventName, fn);
1819         return this;
1820     },
1821     
1822     
1823     on : function(eventName, handler, scope, override){
1824         YAHOO.util.Event.addListener(this.dom, eventName, handler, scope || this, true);
1825         return this;
1826     },
1827     
1828     
1829     addManagedListener : function(eventName, fn, scope, override){
1830         return YAHOO.ext.EventManager.on(this.dom, eventName, fn, scope || this, true);
1831     },
1832     
1833     
1834     mon : function(eventName, fn, scope, override){
1835         return YAHOO.ext.EventManager.on(this.dom, eventName, fn, scope || this, true);
1836     },
1837     
1838     removeListener : function(eventName, handler, scope){
1839         YAHOO.util.Event.removeListener(this.dom, eventName, handler);
1840         return this;
1841     },
1842     
1843     
1844     removeAllListeners : function(){
1845         YAHOO.util.Event.purgeElement(this.dom);
1846         return this;
1847     },
1848     
1849     
1850     
1851      setOpacity : function(opacity, animate, duration, onComplete, easing){
1852         if(!animate || !YAHOO.util.Anim){
1853             YAHOO.util.Dom.setStyle(this.dom, 'opacity', opacity);
1854         }else{
1855             this.anim({opacity: {to: opacity}}, duration, onComplete, easing);
1856         }
1857         return this;
1858     },
1859     
1860     
1861     getLeft : function(local){
1862         if(!local){
1863             return this.getX();
1864         }else{
1865             return parseInt(this.getStyle('left'), 10) || 0;
1866         }
1867     },
1868     
1869     
1870     getRight : function(local){
1871         if(!local){
1872             return this.getX() + this.getWidth();
1873         }else{
1874             return (this.getLeft(true) + this.getWidth()) || 0;
1875         }
1876     },
1877     
1878     
1879     getTop : function(local) {
1880         if(!local){
1881             return this.getY();
1882         }else{
1883             return parseInt(this.getStyle('top'), 10) || 0;
1884         }
1885     },
1886     
1887     
1888     getBottom : function(local){
1889         if(!local){
1890             return this.getY() + this.getHeight();
1891         }else{
1892             return (this.getTop(true) + this.getHeight()) || 0;
1893         }
1894     },
1895     
1896     
1897     setAbsolutePositioned : function(zIndex){
1898         this.setStyle('position', 'absolute');
1899         if(zIndex){
1900             this.setStyle('z-index', zIndex);
1901         }
1902         return this;
1903     },
1904     
1905     
1906     setRelativePositioned : function(zIndex){
1907         this.setStyle('position', 'relative');
1908         if(zIndex){
1909             this.setStyle('z-index', zIndex);
1910         }
1911         return this;
1912     },
1913     
1914     
1915     clearPositioning : function(){
1916         this.setStyle('position', '');
1917         this.setStyle('left', '');
1918         this.setStyle('right', '');
1919         this.setStyle('top', '');
1920         this.setStyle('bottom', '');
1921         return this;
1922     },
1923     
1924     
1925     getPositioning : function(){
1926         return {
1927             'position' : this.getStyle('position'),
1928             'left' : this.getStyle('left'),
1929             'right' : this.getStyle('right'),
1930             'top' : this.getStyle('top'),
1931             'bottom' : this.getStyle('bottom')
1932         };
1933     },
1934     
1935     
1936     getBorderWidth : function(side){
1937         return this.addStyles(side, YAHOO.ext.Element.borders);
1938     },
1939     
1940     
1941     getPadding : function(side){
1942         return this.addStyles(side, YAHOO.ext.Element.paddings);
1943     },
1944     
1945     
1946     setPositioning : function(positionCfg){
1947         if(positionCfg.position)this.setStyle('position', positionCfg.position);
1948         if(positionCfg.left)this.setLeft(positionCfg.left);
1949         if(positionCfg.right)this.setRight(positionCfg.right);
1950         if(positionCfg.top)this.setTop(positionCfg.top);
1951         if(positionCfg.bottom)this.setBottom(positionCfg.bottom);
1952         return this;
1953     },
1954     
1955     
1956     
1957      setLeftTop : function(left, top){
1958         this.dom.style.left = this.addUnits(left);
1959         this.dom.style.top = this.addUnits(top);
1960         return this;
1961     },
1962     
1963     
1964      move : function(direction, distance, animate, duration, onComplete, easing){
1965         var xy = this.getXY();
1966         direction = direction.toLowerCase();
1967         switch(direction){
1968             case 'l':
1969             case 'left':
1970                 this.moveTo(xy[0]-distance, xy[1], animate, duration, onComplete, easing);
1971                 break;
1972            case 'r':
1973            case 'right':
1974                 this.moveTo(xy[0]+distance, xy[1], animate, duration, onComplete, easing);
1975                 break;
1976            case 't':
1977            case 'top':
1978            case 'up':
1979                 this.moveTo(xy[0], xy[1]-distance, animate, duration, onComplete, easing);
1980                 break;
1981            case 'b':
1982            case 'bottom':
1983            case 'down':
1984                 this.moveTo(xy[0], xy[1]+distance, animate, duration, onComplete, easing);
1985                 break;
1986         }
1987         return this;
1988     },
1989     
1990     
1991     clip : function(){
1992         if(!this.isClipped){
1993            this.isClipped = true;
1994            this.originalClip = {
1995                'o': this.getStyle('overflow'), 
1996                'x': this.getStyle('overflow-x'),
1997                'y': this.getStyle('overflow-y')
1998            };
1999            this.setStyle('overflow', 'hidden');
2000            this.setStyle('overflow-x', 'hidden');
2001            this.setStyle('overflow-y', 'hidden');
2002         }
2003         return this;
2004     },
2005     
2006     
2007     unclip : function(){
2008         if(this.isClipped){
2009             this.isClipped = false;
2010             var o = this.originalClip;
2011             if(o.o){this.setStyle('overflow', o.o);}
2012             if(o.x){this.setStyle('overflow-x', o.x);}
2013             if(o.y){this.setStyle('overflow-y', o.y);}
2014         }
2015         return this;
2016     },
2017     
2018     
2019      alignTo : function(element, position, offsets, animate, duration, onComplete, easing){
2020         var otherEl = getEl(element);
2021         if(!otherEl){
2022             return this; 
2023         }
2024         offsets = offsets || [0, 0];
2025         var r = otherEl.getRegion();
2026         position = position.toLowerCase();
2027         switch(position){
2028            case 'bl':
2029                 this.moveTo(r.left + offsets[0], r.bottom + offsets[1], 
2030                             animate, duration, onComplete, easing);
2031                 break;
2032            case 'br':
2033                 this.moveTo(r.right + offsets[0], r.bottom + offsets[1], 
2034                             animate, duration, onComplete, easing);
2035                 break;
2036            case 'tl':
2037                 this.moveTo(r.left + offsets[0], r.top + offsets[1], 
2038                             animate, duration, onComplete, easing);
2039                 break;
2040            case 'tr':
2041                 this.moveTo(r.right + offsets[0], r.top + offsets[1], 
2042                             animate, duration, onComplete, easing);
2043                 break;
2044         }
2045         return this;
2046     },
2047     
2048     
2049     clearOpacity : function(){
2050         if (window.ActiveXObject) {
2051             this.dom.style.filter = '';
2052         } else {
2053             this.dom.style.opacity = '';
2054             this.dom.style['-moz-opacity'] = '';
2055             this.dom.style['-khtml-opacity'] = '';
2056         }
2057         return this;
2058     },
2059     
2060     
2061     hide : function(animate, duration, onComplete, easing){
2062         this.setVisible(false, animate, duration, onComplete, easing);
2063         return this;
2064     },
2065     
2066     
2067     show : function(animate, duration, onComplete, easing){
2068         this.setVisible(true, animate, duration, onComplete, easing);
2069         return this;
2070     },
2071     
2072     
2073     addUnits : function(size){
2074         if(size === '' || size == 'auto' || typeof size == 'undefined'){
2075             return size;
2076         }
2077         if(typeof size == 'number' || !YAHOO.ext.Element.unitPattern.test(size)){
2078             return size + this.defaultUnit;
2079         }
2080         return size;
2081     },
2082     
2083     
2084     beginMeasure : function(){
2085         var el = this.dom;
2086         if(el.offsetWidth || el.offsetHeight){
2087             return this; 
2088         }
2089         var changed = [];
2090         var p = this.dom; 
2091         while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p.tagName.toLowerCase() != 'body'){
2092             if(YAHOO.util.Dom.getStyle(p, 'display') == 'none'){
2093                 changed.push({el: p, visibility: YAHOO.util.Dom.getStyle(p, 'visibility')});
2094                 p.style.visibility = 'hidden';
2095                 p.style.display = 'block';
2096             }
2097             p = p.parentNode;
2098         }
2099         this._measureChanged = changed;
2100         return this;
2101                
2102     },
2103     
2104     
2105     endMeasure : function(){
2106         var changed = this._measureChanged;
2107         if(changed){
2108             for(var i = 0, len = changed.length; i < len; i++) {
2109                 var r = changed[i];
2110                 r.el.style.visibility = r.visibility;
2111                 r.el.style.display = 'none';
2112             }
2113             this._measureChanged = null;
2114         }
2115         return this;
2116     },
2117     
2118     
2119     update : function(html, loadScripts, callback){
2120         if(typeof html == 'undefined'){
2121             html = '';
2122         }
2123         if(loadScripts !== true){
2124             this.dom.innerHTML = html;
2125             if(typeof callback == 'function'){
2126                 callback();
2127             }
2128             return this;
2129         }
2130         var id = YAHOO.util.Dom.generateId();
2131         var dom = this.dom;
2132         
2133         html += '<span id="' + id + '"></span>';
2134         
2135         YAHOO.util.Event.onAvailable(id, function(){
2136             var hd = document.getElementsByTagName("head")[0];
2137             var re = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/img; 
2138             var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
2139             var match;
2140             while(match = re.exec(html)){
2141                 var srcMatch = match[0].match(srcRe);
2142                 if(srcMatch && srcMatch[2]){
2143                    var s = document.createElement("script");
2144                    s.src = srcMatch[2];
2145                    hd.appendChild(s);
2146                 }else if(match[1] && match[1].length > 0){
2147                    eval(match[1]);
2148                 }                     
2149             }
2150             var el = document.getElementById(id);
2151             if(el){el.parentNode.removeChild(el);}
2152             if(typeof callback == 'function'){
2153                 callback();
2154             }
2155         });
2156         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/img, '');
2157         return this;
2158     },
2159     
2160     
2161     load : function(){
2162         var um = this.getUpdateManager();
2163         um.update.apply(um, arguments);
2164         return this;
2165     },
2166     
2167     
2168     getUpdateManager : function(){
2169         if(!this.updateManager){
2170             this.updateManager = new YAHOO.ext.UpdateManager(this);
2171         }
2172         return this.updateManager;
2173     },
2174     
2175     
2176     unselectable : function(){
2177         this.dom.unselectable = 'on';
2178         this.swallowEvent('selectstart', true);
2179         this.applyStyles('-moz-user-select:none;-khtml-user-select:none;');
2180         return this;
2181     },
2182     
2183     
2184     getCenterXY : function(offsetScroll){
2185         var centerX = Math.round((YAHOO.util.Dom.getViewportWidth()-this.getWidth())/2);
2186         var centerY = Math.round((YAHOO.util.Dom.getViewportHeight()-this.getHeight())/2);
2187         if(!offsetScroll){
2188             return [centerX, centerY];
2189         }else{
2190             var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft || 0;
2191             var scrollY = document.documentElement.scrollTop || document.body.scrollTop || 0;
2192             return[centerX + scrollX, centerY + scrollY];
2193         }
2194     },
2195     
2196     
2197     center : function(centerIn) {
2198         if(!centerIn){
2199             this.setXY(this.getCenterXY(true));
2200         }else{
2201             var box = YAHOO.ext.Element.get(centerIn).getBox();
2202             this.setXY([box.x + (box.width / 2) - (this.getWidth() / 2),
2203                    box.y + (box.height / 2) - (this.getHeight() / 2)]);
2204         }
2205         return this;
2206     },
2207
2208     
2209     getChildrenByTagName : function(tagName){
2210         var children = this.dom.getElementsByTagName(tagName);
2211         var len = children.length;
2212         var ce = new Array(len);
2213         for(var i = 0; i < len; ++i){
2214             ce[i] = YAHOO.ext.Element.get(children[i], true);
2215         }
2216         return ce;
2217     },
2218     
2219     
2220     getChildrenByClassName : function(className, tagName){
2221         var children = YAHOO.util.Dom.getElementsByClassName(className, tagName, this.dom);
2222         var len = children.length;
2223         var ce = new Array(len);
2224         for(var i = 0; i < len; ++i){
2225             ce[i] = YAHOO.ext.Element.get(children[i], true);
2226         }
2227         return ce;
2228     },
2229     
2230     
2231     isBorderBox : function(){
2232         if(typeof this.bbox == 'undefined'){
2233             var el = this.dom;
2234             var b = YAHOO.ext.util.Browser;
2235             var strict = YAHOO.ext.Strict;
2236             this.bbox = ((b.isIE && !strict && el.style.boxSizing != 'content-box') || 
2237                (b.isGecko && YAHOO.util.Dom.getStyle(el, "-moz-box-sizing") == 'border-box') || 
2238                (!b.isSafari && YAHOO.util.Dom.getStyle(el, "box-sizing") == 'border-box'));
2239         }
2240         return this.bbox; 
2241     },
2242     
2243     
2244     getBox : function(contentBox, local){
2245         var xy;
2246         if(!local){
2247             xy = this.getXY();
2248         }else{
2249             var left = parseInt(YAHOO.util.Dom.getStyle('left'), 10) || 0;
2250             var top = parseInt(YAHOO.util.Dom.getStyle('top'), 10) || 0;
2251             xy = [left, top];
2252         }
2253         var el = this.dom;
2254         var w = el.offsetWidth;
2255         var h = el.offsetHeight;
2256         if(!contentBox){
2257             return {x: xy[0], y: xy[1], width: w, height: h};
2258         }else{
2259             var l = this.getBorderWidth('l')+this.getPadding('l');
2260             var r = this.getBorderWidth('r')+this.getPadding('r');
2261             var t = this.getBorderWidth('t')+this.getPadding('t');
2262             var b = this.getBorderWidth('b')+this.getPadding('b');
2263             return {x: xy[0]+l, y: xy[1]+t, width: w-(l+r), height: h-(t+b)};
2264         }
2265     },
2266     
2267     
2268     setBox : function(box, adjust, animate, duration, onComplete, easing){
2269         var w = box.width, h = box.height;
2270         if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
2271            w -= (this.getBorderWidth('lr') + this.getPadding('lr'));
2272            h -= (this.getBorderWidth('tb') + this.getPadding('tb'));
2273         }
2274         this.setBounds(box.x, box.y, w, h, animate, duration, onComplete, easing);
2275         return this;
2276     },
2277     
2278     
2279      repaint : function(){
2280         var dom = this.dom;
2281         YAHOO.util.Dom.addClass(dom, 'yui-ext-repaint');
2282         setTimeout(function(){
2283             YAHOO.util.Dom.removeClass(dom, 'yui-ext-repaint');
2284         }, 1);
2285         return this;
2286     },
2287     
2288     
2289     getMargins : function(side){
2290         if(!side){
2291             return {
2292                 top: parseInt(this.getStyle('margin-top'), 10) || 0,
2293                 left: parseInt(this.getStyle('margin-left'), 10) || 0,
2294                 bottom: parseInt(this.getStyle('margin-bottom'), 10) || 0,
2295                 right: parseInt(this.getStyle('margin-right'), 10) || 0
2296             };
2297         }else{
2298             return this.addStyles(side, YAHOO.ext.Element.margins);
2299          }
2300     },
2301     
2302     addStyles : function(sides, styles){
2303         var val = 0;
2304         for(var i = 0, len = sides.length; i < len; i++){
2305              var w = parseInt(this.getStyle(styles[sides.charAt(i)]), 10);
2306              if(!isNaN(w)) val += w;
2307         }
2308         return val;
2309     },
2310     
2311     
2312     createProxy : function(config, renderTo, matchBox){
2313         if(renderTo){
2314             renderTo = YAHOO.util.Dom.get(renderTo);
2315         }else{
2316             renderTo = document.body;
2317         }
2318         config = typeof config == 'object' ? 
2319             config : {tag : 'div', cls: config};
2320         var proxy = YAHOO.ext.DomHelper.append(renderTo, config, true);
2321         if(matchBox){
2322            proxy.setBox(this.getBox());
2323         }
2324         return proxy;
2325     },
2326     
2327     
2328     createShim : function(){
2329         var config = {
2330             tag : 'iframe', 
2331             frameBorder:'no', 
2332             cls: 'yiframe-shim', 
2333             style: 'position:absolute;visibility:hidden;left:0;top:0;overflow:hidden;', 
2334             src: YAHOO.ext.SSL_SECURE_URL
2335         };
2336         var shim = YAHOO.ext.DomHelper.append(this.dom.parentNode, config, true);
2337         shim.setBox(this.getBox());
2338         return shim;
2339     },
2340     
2341     
2342     remove : function(){
2343                 this.dom.parentNode.removeChild(this.dom);
2344                 delete YAHOO.ext.Element.cache[this.dom.id];
2345     },
2346     
2347     
2348     addClassOnOver : function(className){
2349         this.on('mouseover', function(){
2350             this.addClass(className);
2351         }, this, true);
2352         this.on('mouseout', function(){
2353             this.removeClass(className);
2354         }, this, true);
2355         return this;
2356     },
2357     
2358     
2359     swallowEvent : function(eventName, preventDefault){
2360         var fn = function(e){
2361             e.stopPropagation();
2362             if(preventDefault){
2363                 e.preventDefault();
2364             }
2365         };
2366         this.mon(eventName, fn);
2367         return this;
2368     },
2369     
2370     
2371     fitToParent : function(monitorResize){
2372         var p = getEl(this.dom.parentNode, true);
2373         p.beginMeasure(); 
2374         var box = p.getBox(true, true);
2375         p.endMeasure();
2376         this.setSize(box.width, box.height);
2377         if(monitorResize === true){
2378             YAHOO.ext.EventManager.onWindowResize(this.fitToParent, this, true);
2379         }
2380         return this;
2381     },
2382     
2383     
2384     getNextSibling : function(){
2385         var n = this.dom.nextSibling;
2386         while(n && n.nodeType != 1){
2387             n = n.nextSibling;
2388         }
2389         return n;
2390     },
2391     
2392     
2393     getPrevSibling : function(){
2394         var n = this.dom.previousSibling;
2395         while(n && n.nodeType != 1){
2396             n = n.previousSibling;
2397         }
2398         return n;
2399     },
2400     
2401     
2402     
2403     appendChild: function(el){
2404         el = getEl(el);
2405         el.appendTo(this);
2406         return this;
2407     },
2408     
2409     
2410     createChild: function(config, insertBefore){
2411         var c;
2412         if(insertBefore){
2413             c = YAHOO.ext.DomHelper.insertBefore(insertBefore, config, true);
2414         }else{
2415             c = YAHOO.ext.DomHelper.append(this.dom, config, true);
2416         }
2417         return c;
2418     },
2419     
2420     
2421     appendTo: function(el){
2422         var node = getEl(el).dom;
2423         node.appendChild(this.dom);
2424         return this;
2425     },
2426     
2427     
2428     insertBefore: function(el){
2429         var node = getEl(el).dom;
2430         node.parentNode.insertBefore(this.dom, node);
2431         return this;
2432     },
2433     
2434     
2435     insertAfter: function(el){
2436         var node = getEl(el).dom;
2437         node.parentNode.insertBefore(this.dom, node.nextSibling);
2438         return this;
2439     },
2440     
2441     
2442     wrap: function(config){
2443         if(!config){
2444             config = {tag: 'div'};
2445         }
2446         var newEl = YAHOO.ext.DomHelper.insertBefore(this.dom, config, true);
2447         newEl.dom.appendChild(this.dom);
2448         return newEl;
2449     },
2450     
2451     
2452     replace: function(el){
2453         el = getEl(el);
2454         this.insertBefore(el);
2455         el.remove();
2456         return this;
2457     },
2458     
2459     
2460     insertHtml : function(where, html){
2461         YAHOO.ext.DomHelper.insertHtml(where, this.dom, html);
2462         return this;
2463     },
2464     
2465     
2466     set : function(o){
2467         var el = this.dom;
2468         var useSet = el.setAttribute ? true : false;
2469         for(var attr in o){
2470             if(attr == 'style' || typeof o[attr] == 'function') continue;
2471             if(attr=='cls'){
2472                 el.className = o['cls'];
2473             }else{
2474                 if(useSet) el.setAttribute(attr, o[attr]);
2475                 else el[attr] = o[attr];
2476             }
2477         }
2478         YAHOO.ext.DomHelper.applyStyles(el, o.style);
2479         return this;
2480     },
2481     
2482     
2483     addKeyListener : function(key, fn, scope){
2484         var config;
2485         if(typeof key != 'object' || key instanceof Array){
2486             config = {
2487                 key: key,
2488                 fn: fn,
2489                 scope: scope 
2490             };
2491         }else{
2492             config = {
2493                 key : key.key,
2494                 shift : key.shift,
2495                 ctrl : key.ctrl,
2496                 alt : key.alt,
2497                 fn: fn,
2498                 scope: scope
2499             };
2500         }
2501         var map = new YAHOO.ext.KeyMap(this, config);
2502         return map; 
2503     },
2504     
2505     
2506     addKeyMap : function(config){
2507         return new YAHOO.ext.KeyMap(this, config);
2508     }
2509 };
2510
2511
2512 YAHOO.ext.Element.prototype.autoBoxAdjust = true;
2513
2514 YAHOO.ext.Element.prototype.autoDisplayMode = true;
2515
2516 YAHOO.ext.Element.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
2517
2518 YAHOO.ext.Element.VISIBILITY = 1;
2519
2520 YAHOO.ext.Element.DISPLAY = 2;
2521
2522 YAHOO.ext.Element.blockElements = /^(?:address|blockquote|center|dir|div|dl|fieldset|form|h\d|hr|isindex|menu|ol|ul|p|pre|table|dd|dt|li|tbody|tr|td|thead|tfoot|iframe)$/i;
2523 YAHOO.ext.Element.borders = {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'};
2524 YAHOO.ext.Element.paddings = {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'};
2525 YAHOO.ext.Element.margins = {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'};
2526         
2527
2528 YAHOO.ext.Element.createStopHandler = function(stopPropagation, handler, scope, override){
2529     return function(e){
2530         if(e){
2531             if(stopPropagation){
2532                 YAHOO.util.Event.stopEvent(e);
2533             }else {
2534                 YAHOO.util.Event.preventDefault(e);
2535             }
2536         }
2537         handler.call(override && scope ? scope : window, e, scope);
2538     };
2539 };
2540
2541
2542 YAHOO.ext.Element.cache = {};
2543
2544
2545 YAHOO.ext.Element.get = function(el, autoGenerateId){
2546     if(!el){ return null; }
2547     autoGenerateId = true; 
2548     if(el instanceof YAHOO.ext.Element){
2549         el.dom = YAHOO.util.Dom.get(el.id); 
2550         YAHOO.ext.Element.cache[el.id] = el; 
2551         return el;
2552     }else if(el.isComposite){
2553         return el;
2554     }else if(el instanceof Array){
2555         return YAHOO.ext.Element.select(el);
2556     }else if(el === document){
2557         
2558         if(!YAHOO.ext.Element.cache['__ydocument']){
2559             var docEl = function(){};
2560             docEl.prototype = YAHOO.ext.Element.prototype;
2561             var o = new docEl();
2562             o.dom = document;
2563             YAHOO.ext.Element.cache['__ydocument'] = o;
2564         }
2565         return YAHOO.ext.Element.cache['__ydocument'];
2566     }
2567     var key = el;
2568     if(typeof el != 'string'){ 
2569         if(!el.id && !autoGenerateId){ return null; }
2570         YAHOO.util.Dom.generateId(el, 'elgen-');
2571         key = el.id;
2572     }
2573     var element = YAHOO.ext.Element.cache[key];
2574     if(!element){
2575         element = new YAHOO.ext.Element(key);
2576         if(!element.dom) return null;
2577         YAHOO.ext.Element.cache[key] = element;
2578     }else{
2579         element.dom = YAHOO.util.Dom.get(key);
2580     }
2581     return element;
2582 };
2583
2584
2585 var getEl = YAHOO.ext.Element.get;
2586
2587
2588 YAHOO.util.Event.addListener(window, 'unload', function(){ 
2589     YAHOO.ext.Element.cache = null;
2590 });
2591
2592
2593
2594 YAHOO.ext.CompositeElement = function(els){
2595     this.elements = [];
2596     this.addElements(els);
2597 };
2598 YAHOO.ext.CompositeElement.prototype = {
2599     isComposite: true,
2600     addElements : function(els){
2601         if(!els) return this;
2602         var yels = this.elements;
2603         var index = yels.length-1;
2604         for(var i = 0, len = els.length; i < len; i++) {
2605                 yels[++index] = getEl(els[i], true);
2606         }
2607         return this;
2608     },
2609     invoke : function(fn, args){
2610         var els = this.elements;
2611         for(var i = 0, len = els.length; i < len; i++) {
2612                 YAHOO.ext.Element.prototype[fn].apply(els[i], args);
2613         }
2614         return this;
2615     },
2616     
2617     add : function(els){
2618         if(typeof els == 'string'){
2619             this.addElements(YAHOO.ext.Element.selectorFunction(string));
2620         }else if(els instanceof Array){
2621             this.addElements(els);
2622         }else{
2623             this.addElements([els]);
2624         }
2625         return this;
2626     },
2627     
2628     each : function(fn, scope){
2629         var els = this.elements;
2630         for(var i = 0, len = els.length; i < len; i++){
2631             fn.call(scope || els[i], els[i], this, i);
2632         }
2633         return this;
2634     }
2635 };
2636
2637 YAHOO.ext.CompositeElementLite = function(els){
2638     YAHOO.ext.CompositeElementLite.superclass.constructor.call(this, els);
2639     this.el = YAHOO.ext.Element.get(this.elements[0], true);
2640 };
2641 YAHOO.extendX(YAHOO.ext.CompositeElementLite, YAHOO.ext.CompositeElement, {
2642     addElements : function(els){
2643         if(els){
2644             this.elements = this.elements.concat(els);
2645         }
2646         return this;
2647     },
2648     invoke : function(fn, args){
2649         var els = this.elements;
2650         var el = this.el;
2651         for(var i = 0, len = els.length; i < len; i++) {
2652             el.dom = els[i];
2653                 YAHOO.ext.Element.prototype[fn].apply(el, args);
2654         }
2655         return this;
2656     }
2657 });
2658 YAHOO.ext.CompositeElement.createCall = function(proto, fnName){
2659     if(!proto[fnName]){
2660         proto[fnName] = function(){
2661             return this.invoke(fnName, arguments);  
2662         };
2663     }
2664 };
2665 for(var fnName in YAHOO.ext.Element.prototype){
2666     if(typeof YAHOO.ext.Element.prototype[fnName] == 'function'){
2667         YAHOO.ext.CompositeElement.createCall(YAHOO.ext.CompositeElement.prototype, fnName);
2668     }
2669 }
2670 if(typeof cssQuery == 'function'){
2671     YAHOO.ext.Element.selectorFunction = cssQuery;
2672 }else if(typeof document.getElementsBySelector == 'function'){ 
2673     YAHOO.ext.Element.selectorFunction = document.getElementsBySelector.createDelegate(document);
2674 }
2675
2676 YAHOO.ext.Element.select = function(selector, unique){
2677     var els;
2678     if(typeof selector == 'string'){
2679         els = YAHOO.ext.Element.selectorFunction(selector);
2680     }else if(selector instanceof Array){
2681         els = selector;
2682     }else{
2683         throw 'Invalid selector';
2684     }
2685     if(unique === true){
2686         return new YAHOO.ext.CompositeElement(els);
2687     }else{
2688         return new YAHOO.ext.CompositeElementLite(els);
2689     }
2690 };
2691
2692 var getEls = YAHOO.ext.Element.select;
2693 YAHOO.namespace('ext.state');
2694
2695 YAHOO.ext.state.Provider = function(){
2696     YAHOO.ext.state.Provider.superclass.constructor.call(this);
2697     
2698     this.events = {
2699         'statechange': new YAHOO.util.CustomEvent('statechange')  
2700     };
2701     this.state = {};
2702 };
2703 YAHOO.extendX(YAHOO.ext.state.Provider, YAHOO.ext.util.Observable, {
2704     
2705     get : function(name, defaultValue){
2706         return typeof this.state[name] == 'undefined' ?
2707             defaultValue : this.state[name];
2708     },
2709     
2710     
2711     clear : function(name){
2712         delete this.state[name];
2713         this.fireEvent('statechange', this, name, null);
2714     },
2715     
2716     
2717     set : function(name, value){
2718         this.state[name] = value;
2719         this.fireEvent('statechange', this, name, value);
2720     },
2721     
2722     
2723     decodeValue : function(cookie){
2724         var re = /^(a|n|d|b|s|o)\:(.*)$/;
2725         var matches = re.exec(unescape(cookie));
2726         if(!matches || !matches[1]) return; 
2727         var type = matches[1];
2728         var v = matches[2];
2729         switch(type){
2730             case 'n':
2731                 return parseFloat(v);
2732             case 'd':
2733                 return new Date(Date.parse(v));
2734             case 'b':
2735                 return (v == '1');
2736             case 'a':
2737                 var all = [];
2738                 var values = v.split('^');
2739                 for(var i = 0, len = values.length; i < len; i++){
2740                     all.push(this.decodeValue(values[i]))
2741                 }
2742                 return all;
2743            case 'o':
2744                 var all = {};
2745                 var values = v.split('^');
2746                 for(var i = 0, len = values.length; i < len; i++){
2747                     var kv = values[i].split('=');
2748                     all[kv[0]] = this.decodeValue(kv[1]);
2749                 }
2750                 return all;
2751            default:
2752                 return v;
2753         }
2754     },
2755     
2756     
2757     encodeValue : function(v){
2758         var enc;
2759         if(typeof v == 'number'){
2760             enc = 'n:' + v;
2761         }else if(typeof v == 'boolean'){
2762             enc = 'b:' + (v ? '1' : '0');
2763         }else if(v instanceof Date){
2764             enc = 'd:' + v.toGMTString();
2765         }else if(v instanceof Array){
2766             var flat = '';
2767             for(var i = 0, len = v.length; i < len; i++){
2768                 flat += this.encodeValue(v[i]);
2769                 if(i != len-1) flat += '^';
2770             }
2771             enc = 'a:' + flat;
2772         }else if(typeof v == 'object'){
2773             var flat = '';
2774             for(var key in v){
2775                 if(typeof v[key] != 'function'){
2776                     flat += key + '=' + this.encodeValue(v[key]) + '^';
2777                 }
2778             }
2779             enc = 'o:' + flat.substring(0, flat.length-1);
2780         }else{
2781             enc = 's:' + v;
2782         }
2783         return escape(enc);        
2784     }
2785 });
2786
2787
2788 YAHOO.ext.state.Manager = new function(){
2789     var provider = new YAHOO.ext.state.Provider();
2790     
2791     return {
2792         
2793         setProvider : function(stateProvider){
2794             provider = stateProvider;
2795         },
2796         
2797         
2798         get : function(key, defaultValue){
2799             return provider.get(key, defaultValue);
2800         },
2801         
2802         
2803          set : function(key, value){
2804             provider.set(key, value);
2805         },
2806         
2807         
2808         clear : function(key){
2809             provider.clear(key);
2810         },
2811         
2812         
2813         getProvider : function(){
2814             return provider;
2815         }
2816     };
2817 }();
2818
2819
2820 YAHOO.ext.state.CookieProvider = function(config){
2821     YAHOO.ext.state.CookieProvider.superclass.constructor.call(this);
2822     this.path = '/';
2823     this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
2824     this.domain = null;
2825     this.secure = false;
2826     YAHOO.ext.util.Config.apply(this, config);
2827     this.state = this.readCookies();
2828 };
2829
2830 YAHOO.extendX(YAHOO.ext.state.CookieProvider, YAHOO.ext.state.Provider, {
2831     set : function(name, value){
2832         if(typeof value == 'undefined' || value === null){
2833             this.clear(name);
2834             return;
2835         }
2836         this.setCookie(name, value);
2837         YAHOO.ext.state.CookieProvider.superclass.set.call(this, name, value);
2838     },
2839         
2840     clear : function(name){
2841         this.clearCookie(name);
2842         YAHOO.ext.state.CookieProvider.superclass.clear.call(this, name);
2843     },
2844         
2845     readCookies : function(){
2846         var cookies = {};
2847         var c = document.cookie + ';';
2848         var re = /\s?(.*?)=(.*?);/g;
2849         var matches;
2850         while((matches = re.exec(c)) != null){
2851             var name = matches[1];
2852             var value = matches[2];
2853             if(name && name.substring(0,3) == 'ys-'){
2854                 cookies[name.substr(3)] = this.decodeValue(value);
2855             }
2856         }
2857         return cookies;
2858     },
2859     
2860     setCookie : function(name, value){
2861         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
2862            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
2863            ((this.path == null) ? "" : ("; path=" + this.path)) +
2864            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
2865            ((this.secure == true) ? "; secure" : "");
2866     },
2867     
2868     clearCookie : function(name){
2869         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
2870            ((this.path == null) ? "" : ("; path=" + this.path)) +
2871            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
2872            ((this.secure == true) ? "; secure" : "");
2873     }
2874 });
2875
2876
2877
2878 YAHOO.ext.EventManager = new function(){
2879     var docReadyEvent;
2880     var docReadyProcId;
2881     var docReadyState = false;
2882     this.ieDeferSrc = false;
2883     var resizeEvent;
2884     var resizeTask;
2885     
2886     var fireDocReady = function(){
2887         if(!docReadyState){
2888             docReadyState = true;
2889             if(docReadyProcId){
2890                 clearInterval(docReadyProcId);
2891             }
2892             if(docReadyEvent){
2893                 docReadyEvent.fire();
2894             }
2895         }
2896     };
2897     
2898     var initDocReady = function(){
2899         docReadyEvent = new YAHOO.util.CustomEvent('documentready');
2900         if(document.addEventListener) {
2901             YAHOO.util.Event.on(document, "DOMContentLoaded", fireDocReady);
2902         }else if(YAHOO.ext.util.Browser.isIE){
2903             
2904             document.write('<s'+'cript id="ie-deferred-loader" defer="defer" src="' +
2905                         (YAHOO.ext.EventManager.ieDeferSrc || YAHOO.ext.SSL_SECURE_URL) + '"></s'+'cript>');
2906             YAHOO.util.Event.on('ie-deferred-loader', 'readystatechange', function(){
2907                 if(this.readyState == 'complete'){
2908                     fireDocReady();
2909                 }
2910             });
2911         }else if(YAHOO.ext.util.Browser.isSafari){ 
2912             docReadyProcId = setInterval(function(){
2913                 var rs = document.readyState;
2914                 if(rs == 'loaded' || rs == 'complete') {
2915                     fireDocReady();     
2916                  }
2917             }, 10);
2918         }
2919         
2920         YAHOO.util.Event.on(window, 'load', fireDocReady);
2921     };
2922     
2923     this.wrap = function(fn, scope, override){
2924         var wrappedFn = function(e){
2925             YAHOO.ext.EventObject.setEvent(e);
2926             fn.call(override ? scope || window : window, YAHOO.ext.EventObject, scope);
2927         };
2928         return wrappedFn;
2929     };
2930     
2931     
2932     this.addListener = function(element, eventName, fn, scope, override){
2933         var wrappedFn = this.wrap(fn, scope, override);
2934         YAHOO.util.Event.addListener(element, eventName, wrappedFn);
2935         return wrappedFn;
2936     };
2937     
2938     
2939     this.removeListener = function(element, eventName, wrappedFn){
2940         return YAHOO.util.Event.removeListener(element, eventName, wrappedFn);
2941     };
2942     
2943     
2944     this.on = this.addListener;
2945     
2946     
2947     this.onDocumentReady = function(fn, scope, override){
2948         if(docReadyState){ 
2949             fn.call(override? scope || window : window, scope);
2950             return;
2951         }
2952         if(!docReadyEvent){
2953             initDocReady();
2954         }
2955         docReadyEvent.subscribe(fn, scope, override);
2956     }
2957     
2958     
2959     this.onWindowResize = function(fn, scope, override){
2960         if(!resizeEvent){
2961             resizeEvent = new YAHOO.util.CustomEvent('windowresize');
2962             resizeTask = new YAHOO.ext.util.DelayedTask(function(){
2963                 resizeEvent.fireDirect(YAHOO.util.Dom.getViewportWidth(), YAHOO.util.Dom.getViewportHeight());
2964             });
2965             YAHOO.util.Event.on(window, 'resize', function(){
2966                 resizeTask.delay(50);
2967             });
2968         }
2969         resizeEvent.subscribe(fn, scope, override);
2970     },
2971     
2972     
2973     this.removeResizeListener = function(fn, scope){
2974         if(resizeEvent){
2975             resizeEvent.unsubscribe(fn, scope);
2976         }
2977     }
2978 };
2979
2980
2981 YAHOO.ext.EventObject = new function(){
2982      
2983     this.browserEvent = null;
2984      
2985     this.button = -1;
2986      
2987     this.shiftKey = false;
2988      
2989     this.ctrlKey = false;
2990      
2991     this.altKey = false;
2992     
2993     
2994     this.BACKSPACE = 8;
2995     
2996     this.TAB = 9;
2997     
2998     this.RETURN = 13;
2999     
3000     this.ESC = 27;
3001     
3002     this.SPACE = 32;
3003     
3004     this.PAGEUP = 33;
3005     
3006     this.PAGEDOWN = 34;
3007     
3008     this.END = 35;
3009     
3010     this.HOME = 36;
3011     
3012     this.LEFT = 37;
3013     
3014     this.UP = 38;
3015     
3016     this.RIGHT = 39;
3017     
3018     this.DOWN = 40;
3019     
3020     this.DELETE = 46;
3021     
3022     this.F5 = 116;
3023
3024         
3025     this.setEvent = function(e){
3026         if(e == this){ 
3027             return this;
3028         }
3029         this.browserEvent = e;
3030         if(e){
3031             this.button = e.button;
3032             this.shiftKey = e.shiftKey;
3033             this.ctrlKey = e.ctrlKey;
3034             this.altKey = e.altKey;
3035         }else{
3036             this.button = -1;
3037             this.shiftKey = false;
3038             this.ctrlKey = false;
3039             this.altKey = false;
3040         }
3041         return this;
3042     };
3043     
3044      
3045     this.stopEvent = function(){
3046         if(this.browserEvent){
3047             YAHOO.util.Event.stopEvent(this.browserEvent);
3048         }
3049     };
3050     
3051      
3052     this.preventDefault = function(){
3053         if(this.browserEvent){
3054             YAHOO.util.Event.preventDefault(this.browserEvent);
3055         }
3056     };
3057     
3058     
3059     this.isNavKeyPress = function(){
3060         return (this.browserEvent.keyCode && this.browserEvent.keyCode >= 33 && this.browserEvent.keyCode <= 40);
3061     };
3062     
3063      
3064     this.stopPropagation = function(){
3065         if(this.browserEvent){
3066             YAHOO.util.Event.stopPropagation(this.browserEvent);
3067         }
3068     };
3069     
3070      
3071     this.getCharCode = function(){
3072         if(this.browserEvent){
3073             return YAHOO.util.Event.getCharCode(this.browserEvent);
3074         }
3075         return null;
3076     };
3077     
3078     
3079     this.getKey = function(){
3080         if(this.browserEvent){
3081             return this.browserEvent.keyCode || this.browserEvent.charCode;
3082         }
3083         return null;
3084     };
3085     
3086      
3087     this.getPageX = function(){
3088         if(this.browserEvent){
3089             return YAHOO.util.Event.getPageX(this.browserEvent);
3090         }
3091         return null;
3092     };
3093     
3094      
3095     this.getPageY = function(){
3096         if(this.browserEvent){
3097             return YAHOO.util.Event.getPageY(this.browserEvent);
3098         }
3099         return null;
3100     };
3101     
3102      
3103     this.getTime = function(){
3104         if(this.browserEvent){
3105             return YAHOO.util.Event.getTime(this.browserEvent);
3106         }
3107         return null;
3108     };
3109     
3110      
3111     this.getXY = function(){
3112         if(this.browserEvent){
3113             return YAHOO.util.Event.getXY(this.browserEvent);
3114         }
3115         return [];
3116     };
3117     
3118      
3119     this.getTarget = function(){
3120         if(this.browserEvent){
3121             return YAHOO.util.Event.getTarget(this.browserEvent);
3122         }
3123         return null;
3124     };
3125     
3126      
3127     this.findTarget = function(className, tagName){
3128         if(tagName) tagName = tagName.toLowerCase();
3129         if(this.browserEvent){
3130             function isMatch(el){
3131                if(!el){
3132                    return false;
3133                }
3134                if(className && !YAHOO.util.Dom.hasClass(el, className)){
3135                    return false;
3136                }
3137                if(tagName && el.tagName.toLowerCase() != tagName){
3138                    return false;
3139                }
3140                return true;
3141             };
3142             
3143             var t = this.getTarget();
3144             if(!t || isMatch(t)){
3145                     return t;
3146             }
3147             var p = t.parentNode;
3148             var b = document.body;
3149             while(p && p != b){
3150                 if(isMatch(p)){
3151                         return p;
3152                 }
3153                 p = p.parentNode;
3154             }
3155         }
3156         return null;
3157     };
3158      
3159     this.getRelatedTarget = function(){
3160         if(this.browserEvent){
3161             return YAHOO.util.Event.getRelatedTarget(this.browserEvent);
3162         }
3163         return null;
3164     };
3165     
3166     
3167     this.getWheelDelta = function(){
3168         var e = this.browserEvent;
3169         var delta = 0;
3170         if(e.wheelDelta){ 
3171             delta = e.wheelDelta/120;
3172             
3173             if(window.opera) delta = -delta;
3174         }else if(e.detail){ 
3175             delta = -e.detail/3;
3176         }
3177         return delta;
3178     };
3179     
3180      
3181     this.hasModifier = function(){
3182         return this.ctrlKey || this.altKey || this.shiftKey;
3183     };
3184 }();
3185             
3186     
3187
3188 YAHOO.ext.UpdateManager = function(el, forceNew){
3189     el = YAHOO.ext.Element.get(el);
3190     if(!forceNew && el.updateManager){
3191         return el.updateManager;
3192     }
3193     
3194     this.el = el;
3195     
3196     this.defaultUrl = null;
3197     this.beforeUpdate = new YAHOO.util.CustomEvent('UpdateManager.beforeUpdate');
3198     this.onUpdate = new YAHOO.util.CustomEvent('UpdateManager.onUpdate');
3199     this.onFailure = new YAHOO.util.CustomEvent('UpdateManager.onFailure');
3200     
3201     this.events = {
3202         
3203         'beforeupdate': this.beforeUpdate,
3204         
3205         'update': this.onUpdate,
3206         
3207         'failure': this.onFailure 
3208     };
3209     
3210     
3211     this.sslBlankUrl = YAHOO.ext.UpdateManager.defaults.sslBlankUrl;
3212     
3213     this.disableCaching = YAHOO.ext.UpdateManager.defaults.disableCaching;
3214     
3215     this.indicatorText = YAHOO.ext.UpdateManager.defaults.indicatorText;
3216     
3217     this.showLoadIndicator = YAHOO.ext.UpdateManager.defaults.showLoadIndicator;
3218     
3219     this.timeout = YAHOO.ext.UpdateManager.defaults.timeout;
3220     
3221     
3222     this.loadScripts = YAHOO.ext.UpdateManager.defaults.loadScripts;
3223     
3224     
3225     this.transaction = null;
3226     
3227     
3228     this.autoRefreshProcId = null;
3229     
3230     this.refreshDelegate = this.refresh.createDelegate(this);
3231     
3232     this.updateDelegate = this.update.createDelegate(this);
3233     
3234     this.formUpdateDelegate = this.formUpdate.createDelegate(this);
3235     
3236     this.successDelegate = this.processSuccess.createDelegate(this);
3237     
3238      this.failureDelegate = this.processFailure.createDelegate(this);
3239      
3240      
3241       this.renderer = new YAHOO.ext.UpdateManager.BasicRenderer();
3242 };
3243
3244 YAHOO.ext.UpdateManager.prototype = {
3245     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
3246     on : YAHOO.ext.util.Observable.prototype.on,
3247     addListener : YAHOO.ext.util.Observable.prototype.addListener,
3248     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
3249     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
3250     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
3251     bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
3252     
3253     getEl : function(){
3254         return this.el;
3255     },
3256     
3257     
3258     update : function(url, params, callback, discardUrl){
3259         if(this.beforeUpdate.fireDirect(this.el, url, params) !== false){
3260             if(typeof url == 'object'){ 
3261                 var cfg = url;
3262                 url = cfg.url;
3263                 params = params || cfg.params;
3264                 callback = callback || cfg.callback;
3265                 discardUrl = discardUrl || cfg.discardUrl;
3266                 if(callback && cfg.scope){
3267                     callback = callback.createDelegate(cfg.scope);
3268                 }
3269                 if(typeof cfg.nocache != 'undefined'){this.disableCaching = cfg.nocache};
3270                 if(typeof cfg.text != 'undefined'){this.indicatorText = '<div class="loading-indicator">'+cfg.text+'</div>'};
3271                 if(typeof cfg.scripts != 'undefined'){this.loadScripts = cfg.scripts};
3272                 if(typeof cfg.timeout != 'undefined'){this.timeout = cfg.timeout};
3273             }
3274             this.showLoading();
3275             if(!discardUrl){
3276                 this.defaultUrl = url;
3277             }
3278             if(typeof url == 'function'){
3279                 url = url();
3280             }
3281             if(typeof params == 'function'){
3282                 params = params();
3283             }
3284             if(params && typeof params != 'string'){ 
3285                 var buf = [];
3286                 for(var key in params){
3287                     if(typeof params[key] != 'function'){
3288                         buf.push(encodeURIComponent(key), '=', encodeURIComponent(params[key]), '&');
3289                     }
3290                 }
3291                 delete buf[buf.length-1];
3292                 params = buf.join('');
3293             }
3294             var callback = {
3295                 success: this.successDelegate,
3296                 failure: this.failureDelegate,
3297                 timeout: (this.timeout*1000),
3298                 argument: {'url': url, 'form': null, 'callback': callback, 'params': params}
3299             };
3300             var method = params ? 'POST' : 'GET';
3301             if(method == 'GET'){
3302                 url = this.prepareUrl(url);
3303             }
3304             this.transaction = YAHOO.util.Connect.asyncRequest(method, url, callback, params);
3305         }
3306     },
3307     
3308     
3309     formUpdate : function(form, url, reset, callback){
3310         if(this.beforeUpdate.fireDirect(this.el, form, url) !== false){
3311             this.showLoading();
3312             formEl = YAHOO.util.Dom.get(form);
3313             if(typeof url == 'function'){
3314                 url = url();
3315             }
3316             if(typeof params == 'function'){
3317                 params = params();
3318             }
3319             url = url || formEl.action;
3320             var callback = {
3321                 success: this.successDelegate,
3322                 failure: this.failureDelegate,
3323                 timeout: (this.timeout*1000),
3324                 argument: {'url': url, 'form': form, 'callback': callback, 'reset': reset}
3325             };
3326             var isUpload = false;
3327             var enctype = formEl.getAttribute('enctype');
3328             if(enctype && enctype.toLowerCase() == 'multipart/form-data'){
3329                 isUpload = true;
3330             }
3331             YAHOO.util.Connect.setForm(form, isUpload, this.sslBlankUrl);
3332             this.transaction = YAHOO.util.Connect.asyncRequest('POST', url, callback);
3333         }
3334     },
3335     
3336     
3337     refresh : function(callback){
3338         if(this.defaultUrl == null){
3339             return;
3340         }
3341         this.update(this.defaultUrl, null, callback, true);
3342     },
3343     
3344     
3345     startAutoRefresh : function(interval, url, params, callback, refreshNow){
3346         if(refreshNow){
3347             this.update(url || this.defaultUrl, params, callback, true);
3348         }
3349         if(this.autoRefreshProcId){
3350             clearInterval(this.autoRefreshProcId);
3351         }
3352         this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
3353     },
3354     
3355     
3356      stopAutoRefresh : function(){
3357         if(this.autoRefreshProcId){
3358             clearInterval(this.autoRefreshProcId);
3359         }
3360     },
3361     
3362     
3363     showLoading : function(){
3364         if(this.showLoadIndicator){
3365             this.el.update(this.indicatorText);
3366         }
3367     },
3368     
3369     
3370     prepareUrl : function(url){
3371         if(this.disableCaching){
3372             var append = '_dc=' + (new Date().getTime());
3373             if(url.indexOf('?') !== -1){
3374                 url += '&' + append;
3375             }else{
3376                 url += '?' + append;
3377             }
3378         }
3379         return url;
3380     },
3381     
3382     
3383     processSuccess : function(response){
3384         this.transaction = null;
3385         if(response.argument.form && response.argument.reset){
3386             try{ 
3387                 response.argument.form.reset();
3388             }catch(e){}
3389         }
3390         if(this.loadScripts){
3391             this.renderer.render(this.el, response, this, 
3392                 this.updateComplete.createDelegate(this, [response]));
3393         }else{
3394             this.renderer.render(this.el, response, this);
3395             this.updateComplete(response);
3396         }
3397     },
3398     
3399     updateComplete : function(response){
3400         this.fireEvent('update', this.el, response);
3401         if(typeof response.argument.callback == 'function'){
3402             response.argument.callback(this.el, true);
3403         }
3404     },
3405     
3406     
3407     processFailure : function(response){
3408         this.transaction = null;
3409         this.onFailure.fireDirect(this.el, response);
3410         if(typeof response.argument.callback == 'function'){
3411             response.argument.callback(this.el, false);
3412         }
3413     },
3414     
3415     
3416     setRenderer : function(renderer){
3417         this.renderer = renderer;
3418     },
3419     
3420     getRenderer : function(){
3421        return this.renderer;  
3422     },
3423     
3424     
3425     setDefaultUrl : function(defaultUrl){
3426         this.defaultUrl = defaultUrl;
3427     },
3428     
3429     
3430     abort : function(){
3431         if(this.transaction){
3432             YAHOO.util.Connect.abort(this.transaction);
3433         }
3434     },
3435     
3436     
3437     isUpdating : function(){
3438         if(this.transaction){
3439             return YAHOO.util.Connect.isCallInProgress(this.transaction);
3440         }
3441         return false;
3442     }
3443 };
3444
3445
3446    YAHOO.ext.UpdateManager.defaults = {
3447        
3448          timeout : 30,
3449          
3450          
3451         loadScripts : false,
3452          
3453         
3454         sslBlankUrl : (YAHOO.ext.SSL_SECURE_URL || 'javascript:false'),
3455         
3456         disableCaching : false,
3457         
3458         showLoadIndicator : true,
3459         
3460         indicatorText : '<div class="loading-indicator">Loading...</div>'
3461    };
3462
3463
3464 YAHOO.ext.UpdateManager.updateElement = function(el, url, params, options){
3465     var um = getEl(el, true).getUpdateManager();
3466     YAHOO.ext.util.Config.apply(um, options);
3467     um.update(url, params, options.callback);
3468 }
3469
3470 YAHOO.ext.UpdateManager.update = YAHOO.ext.UpdateManager.updateElement;
3471  
3472 YAHOO.ext.UpdateManager.BasicRenderer = function(){};
3473
3474 YAHOO.ext.UpdateManager.BasicRenderer.prototype = {
3475     
3476      render : function(el, response, updateManager, callback){
3477         el.update(response.responseText, updateManager.loadScripts, callback);
3478     }
3479 };
3480
3481
3482
3483 Date.parseFunctions = {count:0};
3484
3485 Date.parseRegexes = [];
3486
3487 Date.formatFunctions = {count:0};
3488
3489
3490 Date.prototype.dateFormat = function(format) {
3491     if (Date.formatFunctions[format] == null) {
3492         Date.createNewFormat(format);
3493     }
3494     var func = Date.formatFunctions[format];
3495     return this[func]();
3496 };
3497
3498
3499 Date.prototype.format = Date.prototype.dateFormat;
3500
3501
3502 Date.createNewFormat = function(format) {
3503     var funcName = "format" + Date.formatFunctions.count++;
3504     Date.formatFunctions[format] = funcName;
3505     var code = "Date.prototype." + funcName + " = function(){return ";
3506     var special = false;
3507     var ch = '';
3508     for (var i = 0; i < format.length; ++i) {
3509         ch = format.charAt(i);
3510         if (!special && ch == "\\") {
3511             special = true;
3512         }
3513         else if (special) {
3514             special = false;
3515             code += "'" + String.escape(ch) + "' + ";
3516         }
3517         else {
3518             code += Date.getFormatCode(ch);
3519         }
3520     }
3521     eval(code.substring(0, code.length - 3) + ";}");
3522 };
3523
3524
3525 Date.getFormatCode = function(character) {
3526     switch (character) {
3527     case "d":
3528         return "String.leftPad(this.getDate(), 2, '0') + ";
3529     case "D":
3530         return "Date.dayNames[this.getDay()].substring(0, 3) + ";
3531     case "j":
3532         return "this.getDate() + ";
3533     case "l":
3534         return "Date.dayNames[this.getDay()] + ";
3535     case "S":
3536         return "this.getSuffix() + ";
3537     case "w":
3538         return "this.getDay() + ";
3539     case "z":
3540         return "this.getDayOfYear() + ";
3541     case "W":
3542         return "this.getWeekOfYear() + ";
3543     case "F":
3544         return "Date.monthNames[this.getMonth()] + ";
3545     case "m":
3546         return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
3547     case "M":
3548         return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
3549     case "n":
3550         return "(this.getMonth() + 1) + ";
3551     case "t":
3552         return "this.getDaysInMonth() + ";
3553     case "L":
3554         return "(this.isLeapYear() ? 1 : 0) + ";
3555     case "Y":
3556         return "this.getFullYear() + ";
3557     case "y":
3558         return "('' + this.getFullYear()).substring(2, 4) + ";
3559     case "a":
3560         return "(this.getHours() < 12 ? 'am' : 'pm') + ";
3561     case "A":
3562         return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
3563     case "g":
3564         return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
3565     case "G":
3566         return "this.getHours() + ";
3567     case "h":
3568         return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
3569     case "H":
3570         return "String.leftPad(this.getHours(), 2, '0') + ";
3571     case "i":
3572         return "String.leftPad(this.getMinutes(), 2, '0') + ";
3573     case "s":
3574         return "String.leftPad(this.getSeconds(), 2, '0') + ";
3575     case "O":
3576         return "this.getGMTOffset() + ";
3577     case "T":
3578         return "this.getTimezone() + ";
3579     case "Z":
3580         return "(this.getTimezoneOffset() * -60) + ";
3581     default:
3582         return "'" + String.escape(character) + "' + ";
3583     };
3584 };
3585
3586
3587 Date.parseDate = function(input, format) {
3588     if (Date.parseFunctions[format] == null) {
3589         Date.createParser(format);
3590     }
3591     var func = Date.parseFunctions[format];
3592     return Date[func](input);
3593 };
3594
3595
3596 Date.createParser = function(format) {
3597     var funcName = "parse" + Date.parseFunctions.count++;
3598     var regexNum = Date.parseRegexes.length;
3599     var currentGroup = 1;
3600     Date.parseFunctions[format] = funcName;
3601
3602     var code = "Date." + funcName + " = function(input){\n"
3603         + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
3604         + "var d = new Date();\n"
3605         + "y = d.getFullYear();\n"
3606         + "m = d.getMonth();\n"
3607         + "d = d.getDate();\n"
3608         + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
3609         + "if (results && results.length > 0) {"
3610     var regex = "";
3611
3612     var special = false;
3613     var ch = '';
3614     for (var i = 0; i < format.length; ++i) {
3615         ch = format.charAt(i);
3616         if (!special && ch == "\\") {
3617             special = true;
3618         }
3619         else if (special) {
3620             special = false;
3621             regex += String.escape(ch);
3622         }
3623         else {
3624             obj = Date.formatCodeToRegex(ch, currentGroup);
3625             currentGroup += obj.g;
3626             regex += obj.s;
3627             if (obj.g && obj.c) {
3628                 code += obj.c;
3629             }
3630         }
3631     }
3632
3633     code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
3634         + "{return new Date(y, m, d, h, i, s);}\n"
3635         + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
3636         + "{return new Date(y, m, d, h, i);}\n"
3637         + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
3638         + "{return new Date(y, m, d, h);}\n"
3639         + "else if (y > 0 && m >= 0 && d > 0)\n"
3640         + "{return new Date(y, m, d);}\n"
3641         + "else if (y > 0 && m >= 0)\n"
3642         + "{return new Date(y, m);}\n"
3643         + "else if (y > 0)\n"
3644         + "{return new Date(y);}\n"
3645         + "}return null;}";
3646
3647     Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
3648     eval(code);
3649 };
3650
3651
3652 Date.formatCodeToRegex = function(character, currentGroup) {
3653     switch (character) {
3654     case "D":
3655         return {g:0,
3656         c:null,
3657         s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
3658     case "j":
3659     case "d":
3660         return {g:1,
3661             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
3662             s:"(\\d{1,2})"};
3663     case "l":
3664         return {g:0,
3665             c:null,
3666             s:"(?:" + Date.dayNames.join("|") + ")"};
3667     case "S":
3668         return {g:0,
3669             c:null,
3670             s:"(?:st|nd|rd|th)"};
3671     case "w":
3672         return {g:0,
3673             c:null,
3674             s:"\\d"};
3675     case "z":
3676         return {g:0,
3677             c:null,
3678             s:"(?:\\d{1,3})"};
3679     case "W":
3680         return {g:0,
3681             c:null,
3682             s:"(?:\\d{2})"};
3683     case "F":
3684         return {g:1,
3685             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
3686             s:"(" + Date.monthNames.join("|") + ")"};
3687     case "M":
3688         return {g:1,
3689             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
3690             s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
3691     case "n":
3692     case "m":
3693         return {g:1,
3694             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
3695             s:"(\\d{1,2})"};
3696     case "t":
3697         return {g:0,
3698             c:null,
3699             s:"\\d{1,2}"};
3700     case "L":
3701         return {g:0,
3702             c:null,
3703             s:"(?:1|0)"};
3704     case "Y":
3705         return {g:1,
3706             c:"y = parseInt(results[" + currentGroup + "], 10);\n",
3707             s:"(\\d{4})"};
3708     case "y":
3709         return {g:1,
3710             c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
3711                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
3712             s:"(\\d{1,2})"};
3713     case "a":
3714         return {g:1,
3715             c:"if (results[" + currentGroup + "] == 'am') {\n"
3716                 + "if (h == 12) { h = 0; }\n"
3717                 + "} else { if (h < 12) { h += 12; }}",
3718             s:"(am|pm)"};
3719     case "A":
3720         return {g:1,
3721             c:"if (results[" + currentGroup + "] == 'AM') {\n"
3722                 + "if (h == 12) { h = 0; }\n"
3723                 + "} else { if (h < 12) { h += 12; }}",
3724             s:"(AM|PM)"};
3725     case "g":
3726     case "G":
3727     case "h":
3728     case "H":
3729         return {g:1,
3730             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
3731             s:"(\\d{1,2})"};
3732     case "i":
3733         return {g:1,
3734             c:"i = parseInt(results[" + currentGroup + "], 10);\n",
3735             s:"(\\d{2})"};
3736     case "s":
3737         return {g:1,
3738             c:"s = parseInt(results[" + currentGroup + "], 10);\n",
3739             s:"(\\d{2})"};
3740     case "O":
3741         return {g:0,
3742             c:null,
3743             s:"[+-]\\d{4}"};
3744     case "T":
3745         return {g:0,
3746             c:null,
3747             s:"[A-Z]{3}"};
3748     case "Z":
3749         return {g:0,
3750             c:null,
3751             s:"[+-]\\d{1,5}"};
3752     default:
3753         return {g:0,
3754             c:null,
3755             s:String.escape(character)};
3756     }
3757 };
3758
3759 Date.prototype.getTimezone = function() {
3760     return this.toString().replace(
3761         /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
3762         /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
3763 };
3764
3765 Date.prototype.getGMTOffset = function() {
3766     return (this.getTimezoneOffset() > 0 ? "-" : "+")
3767         + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
3768         + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
3769 };
3770
3771 Date.prototype.getDayOfYear = function() {
3772     var num = 0;
3773     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
3774     for (var i = 0; i < this.getMonth(); ++i) {
3775         num += Date.daysInMonth[i];
3776     }
3777     return num + this.getDate() - 1;
3778 };
3779
3780 Date.prototype.getWeekOfYear = function() {
3781     
3782     var now = this.getDayOfYear() + (4 - this.getDay());
3783     
3784     var jan1 = new Date(this.getFullYear(), 0, 1);
3785     var then = (7 - jan1.getDay() + 4);
3786     return String.leftPad(((now - then) / 7) + 1, 2, "0");
3787 };
3788
3789 Date.prototype.isLeapYear = function() {
3790     var year = this.getFullYear();
3791     return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
3792 };
3793
3794 Date.prototype.getFirstDayOfMonth = function() {
3795     var day = (this.getDay() - (this.getDate() - 1)) % 7;
3796     return (day < 0) ? (day + 7) : day;
3797 };
3798
3799 Date.prototype.getLastDayOfMonth = function() {
3800     var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
3801     return (day < 0) ? (day + 7) : day;
3802 };
3803
3804 Date.prototype.getDaysInMonth = function() {
3805     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
3806     return Date.daysInMonth[this.getMonth()];
3807 };
3808
3809
3810 Date.prototype.getSuffix = function() {
3811     switch (this.getDate()) {
3812         case 1:
3813         case 21:
3814         case 31:
3815             return "st";
3816         case 2:
3817         case 22:
3818             return "nd";
3819         case 3:
3820         case 23:
3821             return "rd";
3822         default:
3823             return "th";
3824     }
3825 };
3826
3827
3828 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
3829
3830
3831 Date.monthNames =
3832    ["January",
3833     "February",
3834     "March",
3835     "April",
3836     "May",
3837     "June",
3838     "July",
3839     "August",
3840     "September",
3841     "October",
3842     "November",
3843     "December"];
3844     
3845
3846 Date.dayNames =
3847    ["Sunday",
3848     "Monday",
3849     "Tuesday",
3850     "Wednesday",
3851     "Thursday",
3852     "Friday",
3853     "Saturday"];
3854
3855
3856 Date.y2kYear = 50;
3857
3858
3859 Date.monthNumbers = {
3860     Jan:0,
3861     Feb:1,
3862     Mar:2,
3863     Apr:3,
3864     May:4,
3865     Jun:5,
3866     Jul:6,
3867     Aug:7,
3868     Sep:8,
3869     Oct:9,
3870     Nov:10,
3871     Dec:11};
3872
3873 YAHOO.ext.TabPanel = function(container, config){
3874     
3875     this.el = getEl(container, true);
3876     
3877     this.tabPosition = 'top';
3878     this.currentTabWidth = 0;
3879     
3880     this.minTabWidth = 40;
3881     
3882     this.maxTabWidth = 250;
3883     
3884     this.preferredTabWidth = 175;
3885     
3886     this.resizeTabs = false;
3887     
3888     this.monitorResize = true;
3889     
3890     if(config){
3891         if(typeof config == 'boolean'){
3892             this.tabPosition = config ? 'bottom' : 'top';
3893         }else{
3894             YAHOO.ext.util.Config.apply(this, config);
3895         }
3896     }
3897     if(this.tabPosition == 'bottom'){
3898         this.bodyEl = getEl(this.createBody(this.el.dom));
3899         this.el.addClass('ytabs-bottom');
3900     }
3901     this.stripWrap = getEl(this.createStrip(this.el.dom), true);
3902     this.stripEl = getEl(this.createStripList(this.stripWrap.dom), true);
3903     this.stripBody = getEl(this.stripWrap.dom.firstChild.firstChild, true);
3904     if(YAHOO.ext.util.Browser.isIE){
3905         YAHOO.util.Dom.setStyle(this.stripWrap.dom.firstChild, 'overflow-x', 'hidden');
3906     }
3907     if(this.tabPosition != 'bottom'){
3908     
3909       this.bodyEl = getEl(this.createBody(this.el.dom));
3910       this.el.addClass('ytabs-top');
3911     }
3912     this.items = [];
3913     
3914     this.bodyEl.setStyle('position', 'relative');
3915     
3916     
3917     if(!this.items.indexOf){
3918         this.items.indexOf = function(o){
3919             for(var i = 0, len = this.length; i < len; i++){
3920                 if(this[i] == o) return i;
3921             }
3922             return -1;
3923         }
3924     }
3925     this.active = null;
3926     this.onTabChange = new YAHOO.util.CustomEvent('TabItem.onTabChange');
3927     this.activateDelegate = this.activate.createDelegate(this);
3928     
3929     this.events = {
3930         
3931         'tabchange': this.onTabChange,
3932         
3933         'beforetabchange' : new YAHOO.util.CustomEvent('beforechange')
3934     };
3935     
3936     YAHOO.ext.EventManager.onWindowResize(this.onResize, this, true);
3937     this.cpad = this.el.getPadding('lr');
3938     this.hiddenCount = 0;
3939 }
3940
3941 YAHOO.ext.TabPanel.prototype = {
3942     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
3943     on : YAHOO.ext.util.Observable.prototype.on,
3944     addListener : YAHOO.ext.util.Observable.prototype.addListener,
3945     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
3946     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
3947     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
3948     
3949     addTab : function(id, text, content, closable){
3950         var item = new YAHOO.ext.TabPanelItem(this, id, text, closable);
3951         this.addTabItem(item);
3952         if(content){
3953             item.setContent(content);
3954         }
3955         return item;
3956     },
3957     
3958     
3959     getTab : function(id){
3960         return this.items[id];
3961     },
3962     
3963     
3964     hideTab : function(id){
3965         var t = this.items[id];
3966         if(!t.isHidden()){
3967            t.setHidden(true);
3968            this.hiddenCount++;
3969            this.autoSizeTabs();
3970         }
3971     },
3972     
3973     
3974     unhideTab : function(id){
3975         var t = this.items[id];
3976         if(t.isHidden()){
3977            t.setHidden(false);
3978            this.hiddenCount--;
3979            this.autoSizeTabs();
3980         }
3981     },
3982     
3983     
3984     addTabItem : function(item){
3985         this.items[item.id] = item;
3986         this.items.push(item);
3987         if(this.resizeTabs){
3988            item.setWidth(this.currentTabWidth || this.preferredTabWidth)
3989            this.autoSizeTabs();
3990         }else{
3991             item.autoSize();
3992         }
3993     },
3994         
3995     
3996     removeTab : function(id){
3997         var items = this.items;
3998         var tab = items[id];
3999         if(!tab) return;
4000         var index = items.indexOf(tab);
4001         if(this.active == tab && items.length > 1){
4002             var newTab = this.getNextAvailable(index);
4003             if(newTab)newTab.activate();
4004         }
4005         this.stripEl.dom.removeChild(tab.pnode.dom);
4006         if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ 
4007             this.bodyEl.dom.removeChild(tab.bodyEl.dom);
4008         }
4009         items.splice(index, 1);
4010         delete this.items[tab.id];
4011         tab.fireEvent('close', tab);
4012         tab.purgeListeners();
4013         this.autoSizeTabs();
4014     },
4015     
4016     getNextAvailable : function(start){
4017         var items = this.items;
4018         var index = start;
4019         
4020         
4021         while(index < items.length){
4022             var item = items[++index];
4023             if(item && !item.isHidden()){
4024                 return item;
4025             }
4026         }
4027         
4028         var index = start;
4029         while(index >= 0){
4030             var item = items[--index];
4031             if(item && !item.isHidden()){
4032                 return item;
4033             }
4034         }
4035         return null;
4036     },
4037     
4038     
4039     disableTab : function(id){
4040         var tab = this.items[id];
4041         if(tab && this.active != tab){
4042             tab.disable();
4043         }
4044     },
4045     
4046     
4047     enableTab : function(id){
4048         var tab = this.items[id];
4049         tab.enable();
4050     },
4051     
4052     
4053     activate : function(id){
4054         var tab = this.items[id];
4055         if(tab == this.active){
4056             return tab;
4057         } 
4058         var e = {};
4059         this.fireEvent('beforetabchange', this, e, tab);
4060         if(e.cancel !== true && !tab.disabled){
4061             if(this.active){
4062                 this.active.hide();
4063             }
4064             this.active = this.items[id];
4065             this.active.show();
4066             this.onTabChange.fireDirect(this, this.active);
4067         }
4068         return tab;
4069     },
4070     
4071     
4072     getActiveTab : function(){
4073         return this.active;
4074     },
4075     
4076     
4077     syncHeight : function(targetHeight){
4078         var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth('tb')-this.el.getPadding('tb');
4079         var bm = this.bodyEl.getMargins();
4080         var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
4081         this.bodyEl.setHeight(newHeight);
4082         return newHeight; 
4083     },
4084     
4085     onResize : function(){
4086         if(this.monitorResize){
4087             this.autoSizeTabs();
4088         }
4089     },
4090
4091     
4092     beginUpdate : function(){
4093         this.updating = true;    
4094     },
4095     
4096     
4097     endUpdate : function(){
4098         this.updating = false;
4099         this.autoSizeTabs();  
4100     },
4101     
4102     
4103     autoSizeTabs : function(){
4104         var count = this.items.length;
4105         var vcount = count - this.hiddenCount;
4106         if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) return;
4107         var w = Math.max(this.el.getWidth() - this.cpad, 10);
4108         var availWidth = Math.floor(w / vcount);
4109         var b = this.stripBody;
4110         if(b.getWidth() > w){
4111             var tabs = this.items;
4112             this.setTabWidth(Math.max(availWidth, this.minTabWidth));
4113             if(availWidth < this.minTabWidth){
4114                 
4115             }
4116         }else{
4117             if(this.currentTabWidth < this.preferredTabWidth){
4118                 this.setTabWidth(Math.min(availWidth, this.preferredTabWidth));
4119             }
4120         }
4121     },
4122     
4123     
4124      getCount : function(){
4125          return this.items.length;  
4126      },
4127     
4128     
4129     setTabWidth : function(width){
4130         this.currentTabWidth = width;
4131         for(var i = 0, len = this.items.length; i < len; i++) {
4132                 if(!this.items[i].isHidden())this.items[i].setWidth(width);
4133         }
4134     },
4135     
4136     
4137     destroy : function(removeEl){
4138         YAHOO.ext.EventManager.removeResizeListener(this.onResize, this);
4139         for(var i = 0, len = this.items.length; i < len; i++){
4140             this.items[i].purgeListeners();
4141         }
4142         if(removeEl === true){
4143             this.el.update('');
4144             this.el.remove();
4145         }
4146     }
4147 };
4148
4149  
4150 YAHOO.ext.TabPanelItem = function(tabPanel, id, text, closable){
4151     
4152     this.tabPanel = tabPanel;
4153     
4154     this.id = id;
4155     
4156     this.disabled = false;
4157     
4158     this.text = text;
4159     
4160     this.loaded = false;
4161     this.closable = closable;
4162     
4163     
4164     this.bodyEl = getEl(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
4165     this.bodyEl.setVisibilityMode(YAHOO.ext.Element.VISIBILITY);
4166     this.bodyEl.setStyle('display', 'block');
4167     this.bodyEl.setStyle('zoom', '1');
4168     this.hideAction();
4169     
4170     var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
4171     
4172     this.el = getEl(els.el, true);
4173     this.inner = getEl(els.inner, true);
4174     this.textEl = getEl(this.el.dom.firstChild.firstChild.firstChild, true);
4175     this.pnode = getEl(els.el.parentNode, true);
4176     this.el.mon('click', this.onTabClick, this, true);
4177     
4178     if(closable){
4179         var c = getEl(els.close, true);
4180         c.dom.title = this.closeText;
4181         c.addClassOnOver('close-over');
4182         c.mon('click', this.closeClick, this, true);
4183      }
4184     
4185     
4186     this.onActivate = new YAHOO.util.CustomEvent('TabItem.onActivate');
4187     this.onDeactivate = new YAHOO.util.CustomEvent('TabItem.onDeactivate');
4188     
4189     this.events = {
4190          
4191         'activate': this.onActivate,
4192         
4193         'beforeclose': new YAHOO.util.CustomEvent('beforeclose'),
4194         
4195          'close': new YAHOO.util.CustomEvent('close'),
4196         
4197          'deactivate' : this.onDeactivate  
4198     };
4199     this.hidden = false;
4200 };
4201
4202 YAHOO.ext.TabPanelItem.prototype = {
4203     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
4204     on : YAHOO.ext.util.Observable.prototype.on,
4205     addListener : YAHOO.ext.util.Observable.prototype.addListener,
4206     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
4207     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
4208     purgeListeners : function(){
4209        YAHOO.ext.util.Observable.prototype.purgeListeners.call(this);
4210        this.el.removeAllListeners(); 
4211     },
4212     
4213     show : function(){
4214         this.pnode.addClass('on');
4215         this.showAction();
4216         if(YAHOO.ext.util.Browser.isOpera){
4217             this.tabPanel.stripWrap.repaint();
4218         }
4219         this.onActivate.fireDirect(this.tabPanel, this); 
4220     },
4221     
4222     
4223     isActive : function(){
4224         return this.tabPanel.getActiveTab() == this;  
4225     },
4226     
4227     
4228     hide : function(){
4229         this.pnode.removeClass('on');
4230         this.hideAction();
4231         this.onDeactivate.fireDirect(this.tabPanel, this); 
4232     },
4233     
4234     hideAction : function(){
4235         this.bodyEl.setStyle('position', 'absolute');
4236         this.bodyEl.setLeft('-20000px');
4237         this.bodyEl.setTop('-20000px');
4238         this.bodyEl.hide();
4239     },
4240     
4241     showAction : function(){
4242         this.bodyEl.setStyle('position', 'relative');
4243         this.bodyEl.setTop('');
4244         this.bodyEl.setLeft('');
4245         this.bodyEl.show();
4246         this.tabPanel.el.repaint.defer(1);
4247     },
4248     
4249     
4250     setTooltip : function(text){
4251         this.textEl.dom.title = text;
4252     },
4253     
4254     onTabClick : function(e){
4255         e.preventDefault();
4256         this.tabPanel.activate(this.id);
4257     },
4258     
4259     getWidth : function(){
4260         return this.inner.getWidth();  
4261     },
4262     
4263     setWidth : function(width){
4264         var iwidth = width - this.pnode.getPadding("lr");
4265         this.inner.setWidth(iwidth);
4266         this.textEl.setWidth(iwidth-this.inner.getPadding('lr'));
4267         this.pnode.setWidth(width);
4268     },
4269     
4270     setHidden : function(hidden){
4271         this.hidden = hidden;
4272         this.pnode.setStyle('display', hidden ? 'none' : '');  
4273     },
4274     
4275     
4276     isHidden : function(){
4277         return this.hidden;  
4278     },
4279     
4280     
4281     getText : function(){
4282         return this.text;
4283     },
4284     
4285     autoSize : function(){
4286         this.el.beginMeasure();
4287         this.textEl.setWidth(1);
4288         this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding('lr'));
4289         this.el.endMeasure();
4290     },
4291     
4292     
4293     setText : function(text){
4294         this.text = text;
4295         this.textEl.update(text);
4296         this.textEl.dom.title = text;
4297         if(!this.tabPanel.resizeTabs){
4298             this.autoSize();
4299         }
4300     },
4301     
4302     activate : function(){
4303         this.tabPanel.activate(this.id);
4304     },
4305     
4306     
4307     disable : function(){
4308         if(this.tabPanel.active != this){
4309             this.disabled = true;
4310             this.pnode.addClass('disabled');
4311         }
4312     },
4313     
4314     
4315     enable : function(){
4316         this.disabled = false;
4317         this.pnode.removeClass('disabled');
4318     },
4319     
4320     
4321     setContent : function(content, loadScripts){
4322         this.bodyEl.update(content, loadScripts);
4323     },
4324     
4325     
4326     getUpdateManager : function(){
4327         return this.bodyEl.getUpdateManager();
4328     },
4329     
4330     
4331     setUrl : function(url, params, loadOnce){
4332         if(this.refreshDelegate){
4333             this.onActivate.unsubscribe(this.refreshDelegate);
4334         }
4335         this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
4336         this.onActivate.subscribe(this.refreshDelegate);
4337         return this.bodyEl.getUpdateManager();
4338     },
4339     
4340     
4341     _handleRefresh : function(url, params, loadOnce){
4342         if(!loadOnce || !this.loaded){
4343             var updater = this.bodyEl.getUpdateManager();
4344             updater.update(url, params, this._setLoaded.createDelegate(this));
4345         }
4346     },
4347     
4348     
4349     refresh : function(){
4350         if(this.refreshDelegate){
4351            this.loaded = false;
4352            this.refreshDelegate();
4353         }
4354     }, 
4355     
4356     
4357     _setLoaded : function(){
4358         this.loaded = true;
4359     },
4360     
4361     
4362     closeClick : function(e){
4363         var e = {};
4364         this.fireEvent('beforeclose', this, e);
4365         if(e.cancel !== true){
4366             this.tabPanel.removeTab(this.id);
4367         }
4368     },
4369     
4370     closeText : 'Close this tab'
4371 };
4372
4373
4374 YAHOO.ext.TabPanel.prototype.createStrip = function(container){
4375     var strip = document.createElement('div');
4376     strip.className = 'ytab-wrap';
4377     container.appendChild(strip);
4378     return strip;
4379 };
4380
4381 YAHOO.ext.TabPanel.prototype.createStripList = function(strip){
4382     
4383     strip.innerHTML = '<div class="ytab-strip-wrap"><table class="ytab-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr></tr></tbody></table></div>';
4384     return strip.firstChild.firstChild.firstChild.firstChild;
4385 };
4386
4387 YAHOO.ext.TabPanel.prototype.createBody = function(container){
4388     var body = document.createElement('div');
4389     YAHOO.util.Dom.generateId(body, 'tab-body');
4390     YAHOO.util.Dom.addClass(body, 'yui-ext-tabbody');
4391     container.appendChild(body);
4392     return body;
4393 };
4394
4395 YAHOO.ext.TabPanel.prototype.createItemBody = function(bodyEl, id){
4396     var body = YAHOO.util.Dom.get(id);
4397     if(!body){
4398         body = document.createElement('div');
4399         body.id = id;
4400     }
4401     YAHOO.util.Dom.addClass(body, 'yui-ext-tabitembody');
4402     bodyEl.insertBefore(body, bodyEl.firstChild);
4403     return body;
4404 };
4405
4406 YAHOO.ext.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
4407     var td = document.createElement('td');
4408     stripEl.appendChild(td);
4409     if(closable){
4410         td.className = "ytab-closable";
4411         if(!this.closeTpl){
4412             this.closeTpl = new YAHOO.ext.Template(
4413                '<a href="#" class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
4414                '<span unselectable="on" title="{text}" class="ytab-text">{text}</span>' +
4415                '<div unselectable="on" class="close-icon">&#160;</div></em></span></a>'
4416             );
4417         }
4418         var el = this.closeTpl.overwrite(td, {'text': text});
4419         var close = el.getElementsByTagName('div')[0];
4420         var inner = el.getElementsByTagName('em')[0];
4421         return {'el': el, 'close': close, 'inner': inner};
4422     } else {
4423         if(!this.tabTpl){
4424             this.tabTpl = new YAHOO.ext.Template(
4425                '<a href="#" class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
4426                '<span unselectable="on" title="{text}" class="ytab-text">{text}</span></em></span></a>'
4427             );
4428         }
4429         var el = this.tabTpl.overwrite(td, {'text': text});
4430         var inner = el.getElementsByTagName('em')[0];
4431         return {'el': el, 'inner': inner};
4432     }
4433 };
4434
4435
4436 YAHOO.ext.Actor = function(element, animator, selfCapture){
4437     this.el = YAHOO.ext.Element.get(element, true); 
4438     YAHOO.ext.Actor.superclass.constructor.call(this, element, true);
4439     this.onCapture = new YAHOO.util.CustomEvent('Actor.onCapture');
4440     if(animator){
4441         
4442         animator.addActor(this);
4443     }
4444     
4445     this.capturing = selfCapture;
4446     this.playlist = selfCapture ? new YAHOO.ext.Animator.AnimSequence() : null;
4447 };
4448
4449 YAHOO.extendX(YAHOO.ext.Actor, YAHOO.ext.Element);
4450
4451
4452 YAHOO.ext.Actor.prototype.capture = function(action){
4453     if(this.playlist != null){
4454         this.playlist.add(action);
4455     }
4456     this.onCapture.fireDirect(this, action);
4457     return action;
4458 };
4459
4460
4461 YAHOO.ext.Actor.overrideAnimation = function(method, animParam, onParam){
4462     return function(){
4463         if(!this.capturing){
4464             return method.apply(this, arguments);
4465         }
4466         var args = Array.prototype.slice.call(arguments, 0);
4467         if(args[animParam] === true){
4468             return this.capture(new YAHOO.ext.Actor.AsyncAction(this, method, args, onParam));
4469         }else{
4470             return this.capture(new YAHOO.ext.Actor.Action(this, method, args));
4471         }
4472     };
4473 }
4474
4475
4476 YAHOO.ext.Actor.overrideBasic = function(method){
4477     return function(){
4478         if(!this.capturing){
4479             return method.apply(this, arguments);
4480         }
4481         var args = Array.prototype.slice.call(arguments, 0);
4482         return this.capture(new YAHOO.ext.Actor.Action(this, method, args));
4483     };
4484 }
4485
4486
4487
4488 YAHOO.ext.Actor.prototype.setVisibilityMode = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setVisibilityMode);
4489
4490 YAHOO.ext.Actor.prototype.enableDisplayMode = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.enableDisplayMode);
4491
4492 YAHOO.ext.Actor.prototype.focus = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.focus);
4493
4494 YAHOO.ext.Actor.prototype.addClass = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.addClass);
4495
4496 YAHOO.ext.Actor.prototype.removeClass = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.removeClass);
4497
4498 YAHOO.ext.Actor.prototype.replaceClass = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.replaceClass);
4499
4500 YAHOO.ext.Actor.prototype.setStyle = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setStyle);
4501
4502 YAHOO.ext.Actor.prototype.setLeft = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setLeft);
4503
4504 YAHOO.ext.Actor.prototype.setTop = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setTop);
4505
4506 YAHOO.ext.Actor.prototype.setAbsolutePositioned = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setAbsolutePositioned);
4507
4508 YAHOO.ext.Actor.prototype.setRelativePositioned = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setRelativePositioned);
4509
4510 YAHOO.ext.Actor.prototype.clearPositioning = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.clearPositioning);
4511
4512 YAHOO.ext.Actor.prototype.setPositioning = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.setPositioning);
4513
4514 YAHOO.ext.Actor.prototype.clip = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.clip);
4515
4516 YAHOO.ext.Actor.prototype.unclip = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.unclip);
4517
4518 YAHOO.ext.Actor.prototype.clearOpacity = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.clearOpacity);
4519
4520 YAHOO.ext.Actor.prototype.update = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.update);
4521
4522 YAHOO.ext.Actor.prototype.remove = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.remove);
4523 YAHOO.ext.Actor.prototype.fitToParent = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.fitToParent);
4524 YAHOO.ext.Actor.prototype.appendChild = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.appendChild);
4525 YAHOO.ext.Actor.prototype.createChild = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.createChild);
4526 YAHOO.ext.Actor.prototype.appendTo = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.appendTo);
4527 YAHOO.ext.Actor.prototype.insertBefore = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.insertBefore);
4528 YAHOO.ext.Actor.prototype.insertAfter = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.insertAfter);
4529 YAHOO.ext.Actor.prototype.wrap = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.wrap);
4530 YAHOO.ext.Actor.prototype.replace = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.replace);
4531 YAHOO.ext.Actor.prototype.insertHtml = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.insertHtml);
4532 YAHOO.ext.Actor.prototype.set = YAHOO.ext.Actor.overrideBasic(YAHOO.ext.Actor.superclass.set);
4533
4534
4535 YAHOO.ext.Actor.prototype.load = function(){
4536    if(!this.capturing){
4537         return YAHOO.ext.Actor.superclass.load.apply(this, arguments);
4538    }
4539    var args = Array.prototype.slice.call(arguments, 0);
4540    return this.capture(new YAHOO.ext.Actor.AsyncAction(this, YAHOO.ext.Actor.superclass.load, 
4541         args, 2));
4542 };
4543
4544
4545 YAHOO.ext.Actor.prototype.animate = function(args, duration, onComplete, easing, animType){
4546     if(!this.capturing){
4547         return YAHOO.ext.Actor.superclass.animate.apply(this, arguments);
4548     }
4549     return this.capture(new YAHOO.ext.Actor.AsyncAction(this, YAHOO.ext.Actor.superclass.animate, 
4550         [args, duration, onComplete, easing, animType], 2));
4551 };
4552
4553
4554 YAHOO.ext.Actor.prototype.setVisible = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setVisible, 1, 3);
4555
4556 YAHOO.ext.Actor.prototype.toggle = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.toggle, 0, 2);
4557
4558 YAHOO.ext.Actor.prototype.setXY = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setXY, 1, 3);
4559
4560 YAHOO.ext.Actor.prototype.setLocation = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setLocation, 2, 4);
4561
4562 YAHOO.ext.Actor.prototype.setWidth = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setWidth, 1, 3);
4563
4564 YAHOO.ext.Actor.prototype.setHeight = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setHeight, 1, 3);
4565
4566 YAHOO.ext.Actor.prototype.setSize = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setSize, 2, 4);
4567
4568 YAHOO.ext.Actor.prototype.setBounds = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setBounds, 4, 6);
4569
4570 YAHOO.ext.Actor.prototype.setOpacity = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setOpacity, 1, 3);
4571
4572 YAHOO.ext.Actor.prototype.moveTo = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.moveTo, 2, 4);
4573
4574 YAHOO.ext.Actor.prototype.move = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.move, 2, 4);
4575
4576 YAHOO.ext.Actor.prototype.alignTo = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.alignTo, 3, 5);
4577
4578 YAHOO.ext.Actor.prototype.hide = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.hide, 0, 2);
4579
4580 YAHOO.ext.Actor.prototype.show = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.show, 0, 2);
4581
4582
4583 YAHOO.ext.Actor.prototype.setBox = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setBox, 2, 4);
4584
4585
4586 YAHOO.ext.Actor.prototype.autoHeight = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.autoHeight, 0, 2);
4587
4588 YAHOO.ext.Actor.prototype.setX = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setX, 1, 3);
4589
4590 YAHOO.ext.Actor.prototype.setY = YAHOO.ext.Actor.overrideAnimation(YAHOO.ext.Actor.superclass.setY, 1, 3);
4591
4592
4593 YAHOO.ext.Actor.prototype.startCapture = function(){
4594     this.capturing = true;
4595     this.playlist = new YAHOO.ext.Animator.AnimSequence();
4596  };
4597  
4598  
4599  YAHOO.ext.Actor.prototype.stopCapture = function(){
4600      this.capturing = false;
4601  };
4602
4603
4604 YAHOO.ext.Actor.prototype.clear = function(){
4605     this.playlist = new YAHOO.ext.Animator.AnimSequence();
4606 };
4607
4608
4609 YAHOO.ext.Actor.prototype.play = function(oncomplete){
4610     this.capturing = false;
4611     if(this.playlist){
4612         this.playlist.play(oncomplete);
4613     }
4614  };
4615
4616
4617 YAHOO.ext.Actor.prototype.addCall = function(fcn, args, scope){
4618     if(!this.capturing){
4619         fcn.apply(scope || this, args || []);
4620     }else{
4621         this.capture(new YAHOO.ext.Actor.Action(scope, fcn, args || []));
4622     }
4623 };
4624
4625
4626 YAHOO.ext.Actor.prototype.addAsyncCall = function(fcn, callbackIndex, args, scope){
4627     if(!this.capturing){
4628         fcn.apply(scope || this, args || []);
4629     }else{
4630        this.capture(new YAHOO.ext.Actor.AsyncAction(scope, fcn, args || [], callbackIndex));
4631     }
4632  },
4633  
4634
4635 YAHOO.ext.Actor.prototype.pause = function(seconds){
4636     this.capture(new YAHOO.ext.Actor.PauseAction(seconds));
4637  };
4638  
4639
4640 YAHOO.ext.Actor.prototype.shake = function(){
4641     this.move('left', 20, true, .05);
4642     this.move('right', 40, true, .05);
4643     this.move('left', 40, true, .05);
4644     this.move('right', 20, true, .05);
4645 };
4646
4647
4648 YAHOO.ext.Actor.prototype.bounce = function(){
4649     this.move('up', 20, true, .05);
4650     this.move('down', 40, true, .05);
4651     this.move('up', 40, true, .05);
4652     this.move('down', 20, true, .05);
4653 };
4654
4655
4656 YAHOO.ext.Actor.prototype.blindShow = function(anchor, newSize, duration, easing){
4657     var size = newSize || this.getSize();
4658     this.clip();
4659     this.setVisible(true);
4660     anchor = anchor.toLowerCase();
4661     switch(anchor){
4662         case 't':
4663         case 'top':
4664             this.setHeight(1);
4665             this.setHeight(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4666         break;
4667         case 'l':
4668         case 'left':
4669             this.setWidth(1);
4670             this.setWidth(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4671         break;
4672     }
4673     this.unclip();
4674     return size;
4675 };
4676
4677
4678 YAHOO.ext.Actor.prototype.blindHide = function(anchor, duration, easing){
4679     var size = this.getSize();
4680     this.clip();
4681     anchor = anchor.toLowerCase();
4682     switch(anchor){
4683         case 't':
4684         case 'top':
4685             this.setSize(size.width, 1, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4686             this.setVisible(false);
4687         break;
4688         case 'l':
4689         case 'left':
4690             this.setSize(1, size.height, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4691             this.setVisible(false);
4692         break;
4693         case 'r':
4694         case 'right':
4695             this.animate({width: {to: 1}, points: {by: [this.getWidth(), 0]}}, 
4696             duration || .5, null, YAHOO.util.Easing.easeIn, YAHOO.util.Motion);
4697             this.setVisible(false);
4698         break;
4699         case 'b':
4700         case 'bottom':
4701             this.animate({height: {to: 1}, points: {by: [0, this.getHeight()]}}, 
4702             duration || .5, null, YAHOO.util.Easing.easeIn, YAHOO.util.Motion);
4703             this.setVisible(false);
4704         break;
4705     }
4706     return size;
4707 };
4708
4709
4710 YAHOO.ext.Actor.prototype.slideShow = function(anchor, newSize, duration, easing, clearPositioning){
4711     var size = newSize || this.getSize();
4712     this.clip();
4713     var firstChild = this.dom.firstChild;
4714     if(!firstChild || (firstChild.nodeName && "#TEXT" == firstChild.nodeName.toUpperCase())) { 
4715         this.blindShow(anchor, newSize, duration, easing);
4716         return;
4717     }
4718     var child = YAHOO.ext.Element.get(firstChild, true);
4719     var pos = child.getPositioning();
4720     this.addCall(child.setAbsolutePositioned, null, child);
4721     this.setVisible(true);
4722     anchor = anchor.toLowerCase();
4723     switch(anchor){
4724         case 't':
4725         case 'top':
4726             this.addCall(child.setStyle, ['right', ''], child);
4727             this.addCall(child.setStyle, ['top', ''], child);
4728             this.addCall(child.setStyle, ['left', '0px'], child);
4729             this.addCall(child.setStyle, ['bottom', '0px'], child);
4730             this.setHeight(1);
4731             this.setHeight(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4732         break;
4733         case 'l':
4734         case 'left':
4735             this.addCall(child.setStyle, ['left', ''], child);
4736             this.addCall(child.setStyle, ['bottom', ''], child);
4737             this.addCall(child.setStyle, ['right', '0px'], child);
4738             this.addCall(child.setStyle, ['top', '0px'], child);
4739             this.setWidth(1);
4740             this.setWidth(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4741         break;
4742         case 'r':
4743         case 'right':
4744             this.addCall(child.setStyle, ['left', '0px'], child);
4745             this.addCall(child.setStyle, ['top', '0px'], child);
4746             this.addCall(child.setStyle, ['right', ''], child);
4747             this.addCall(child.setStyle, ['bottom', ''], child);
4748             this.setWidth(1);
4749             this.setWidth(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4750         break;
4751         case 'b':
4752         case 'bottom':
4753             this.addCall(child.setStyle, ['right', ''], child);
4754             this.addCall(child.setStyle, ['top', '0px'], child);
4755             this.addCall(child.setStyle, ['left', '0px'], child);
4756             this.addCall(child.setStyle, ['bottom', ''], child);
4757             this.setHeight(1);
4758             this.setHeight(newSize, true, duration || .5, null, easing || YAHOO.util.Easing.easeOut);
4759         break;
4760     }
4761     if(clearPositioning !== false){
4762       this.addCall(child.setPositioning, [pos], child);
4763     }
4764     this.unclip();
4765     return size;
4766 };
4767
4768
4769 YAHOO.ext.Actor.prototype.slideHide = function(anchor, duration, easing){
4770     var size = this.getSize();
4771     this.clip();
4772     var firstChild = this.dom.firstChild;
4773     if(!firstChild || (firstChild.nodeName && "#TEXT" == firstChild.nodeName.toUpperCase())) { 
4774         this.blindHide(anchor, duration, easing);
4775         return;
4776     }
4777     var child = YAHOO.ext.Element.get(firstChild, true);
4778     var pos = child.getPositioning();
4779     this.addCall(child.setAbsolutePositioned, null, child);
4780     anchor = anchor.toLowerCase();
4781     switch(anchor){
4782         case 't':
4783         case 'top':
4784             this.addCall(child.setStyle, ['right', ''], child);
4785             this.addCall(child.setStyle, ['top', ''], child);
4786             this.addCall(child.setStyle, ['left', '0px'], child);
4787             this.addCall(child.setStyle, ['bottom', '0px'], child);
4788             this.setSize(size.width, 1, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4789             this.setVisible(false);
4790         break;
4791         case 'l':
4792         case 'left':
4793             this.addCall(child.setStyle, ['left', ''], child);
4794             this.addCall(child.setStyle, ['bottom', ''], child);
4795             this.addCall(child.setStyle, ['right', '0px'], child);
4796             this.addCall(child.setStyle, ['top', '0px'], child);
4797             this.setSize(1, size.height, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4798             this.setVisible(false);
4799         break;
4800         case 'r':
4801         case 'right':
4802             this.addCall(child.setStyle, ['right', ''], child);
4803             this.addCall(child.setStyle, ['bottom', ''], child);
4804             this.addCall(child.setStyle, ['left', '0px'], child);
4805             this.addCall(child.setStyle, ['top', '0px'], child);
4806             this.setSize(1, size.height, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4807             this.setVisible(false);
4808         break;
4809         case 'b':
4810         case 'bottom':
4811             this.addCall(child.setStyle, ['right', ''], child);
4812             this.addCall(child.setStyle, ['top', '0px'], child);
4813             this.addCall(child.setStyle, ['left', '0px'], child);
4814             this.addCall(child.setStyle, ['bottom', ''], child);
4815             this.setSize(size.width, 1, true, duration || .5, null, easing || YAHOO.util.Easing.easeIn);
4816             this.setVisible(false);
4817         break;
4818     }
4819     this.addCall(child.setPositioning, [pos], child);
4820     return size;
4821 };
4822
4823
4824 YAHOO.ext.Actor.prototype.squish = function(duration){
4825     var size = this.getSize();
4826     this.clip();
4827     this.setSize(1, 1, true, duration || .5);
4828     this.setVisible(false);
4829     return size;
4830 };
4831
4832
4833 YAHOO.ext.Actor.prototype.appear = function(duration){
4834     this.setVisible(true, true, duration);
4835 };
4836
4837
4838 YAHOO.ext.Actor.prototype.fade = function(duration){
4839     this.setVisible(false, true, duration);
4840 };
4841
4842
4843 YAHOO.ext.Actor.prototype.switchOff = function(duration){
4844     this.clip();
4845     this.setVisible(false, true, .1);
4846     this.clearOpacity();
4847     this.setVisible(true);
4848     this.animate({height: {to: 1}, points: {by: [0, this.getHeight()/2]}}, 
4849             duration || .5, null, YAHOO.util.Easing.easeOut, YAHOO.util.Motion);
4850     this.setVisible(false);
4851 };
4852
4853
4854 YAHOO.ext.Actor.prototype.highlight = function(color, fromColor, duration, attribute){
4855     attribute = attribute || 'background-color';
4856     var original = this.getStyle(attribute);
4857     fromColor = fromColor || ((original && original != '' && original != 'transparent') ? original : '#FFFFFF');
4858     var cfg = {};
4859     cfg[attribute] = {to: color, from: fromColor};
4860     this.setVisible(true);
4861     this.animate(cfg, duration || .5, null, YAHOO.util.Easing.bounceOut, YAHOO.util.ColorAnim);
4862     this.setStyle(attribute, original);
4863 };
4864
4865
4866 YAHOO.ext.Actor.prototype.pulsate = function(count, duration){
4867     count = count || 3;
4868     for(var i = 0; i < count; i++){
4869         this.toggle(true, duration || .25);
4870         this.toggle(true, duration || .25);
4871     }
4872 };
4873
4874
4875 YAHOO.ext.Actor.prototype.dropOut = function(duration){
4876     this.animate({opacity: {to: 0}, points: {by: [0, this.getHeight()]}}, 
4877             duration || .5, null, YAHOO.util.Easing.easeIn, YAHOO.util.Motion);
4878     this.setVisible(false);
4879 };
4880
4881
4882 YAHOO.ext.Actor.prototype.moveOut = function(anchor, duration, easing){
4883     var Y = YAHOO.util;
4884     var vw = Y.Dom.getViewportWidth();
4885     var vh = Y.Dom.getViewportHeight();
4886     var cpoints = this.getCenterXY()
4887     var centerX = cpoints[0];
4888     var centerY = cpoints[1];
4889     var anchor = anchor.toLowerCase();
4890     var p;
4891     switch(anchor){
4892         case 't':
4893         case 'top':
4894             p = [centerX, -this.getHeight()];
4895         break;
4896         case 'l':
4897         case 'left':
4898             p = [-this.getWidth(), centerY];
4899         break;
4900         case 'r':
4901         case 'right':
4902             p = [vw+this.getWidth(), centerY];
4903         break;
4904         case 'b':
4905         case 'bottom':
4906             p = [centerX, vh+this.getHeight()];
4907         break;
4908         case 'tl':
4909         case 'top-left':
4910             p = [-this.getWidth(), -this.getHeight()];
4911         break;
4912         case 'bl':
4913         case 'bottom':
4914             p = [-this.getWidth(), vh+this.getHeight()];
4915         break;
4916         case 'br':
4917         case 'bottom-right':
4918             p = [vw+this.getWidth(), vh+this.getHeight()];
4919         break;
4920         case 'tr':
4921         case 'top-right':
4922             p = [vw+this.getWidth(), -this.getHeight()];
4923         break;
4924     }
4925     this.moveTo(p[0], p[1], true, duration || .35, null, easing || Y.Easing.easeIn);
4926     this.setVisible(false);
4927 };
4928
4929
4930 YAHOO.ext.Actor.prototype.moveIn = function(anchor, to, duration, easing){
4931     to = to || this.getCenterXY();
4932     this.moveOut(anchor, .01);
4933     this.setVisible(true);
4934     this.setXY(to, true, duration || .35, null, easing || YAHOO.util.Easing.easeOut);
4935 };
4936
4937 YAHOO.ext.Actor.prototype.frame = function(color, count, duration){
4938     color = color || "red";
4939     count = count || 3;
4940     duration = duration || .5;
4941     var frameFn = function(callback){
4942         var box = this.getBox();
4943         var animFn = function(){ 
4944             var proxy = this.createProxy({
4945                  tag:"div",
4946                  style:{
4947                     visbility:"hidden",
4948                     position:"absolute",
4949                     zIndex:this.getStyle("zIndex"),
4950                     border:"0px solid " + color
4951                  }
4952               });
4953             var scale = proxy.isBorderBox() ? 2 : 1;
4954             proxy.animate({
4955                 top:{from:box.y, to:box.y - 20},
4956                 left:{from:box.x, to:box.x - 20},
4957                 borderWidth:{from:0, to:10},
4958                 opacity:{from:1, to:0},
4959                 height:{from:box.height, to:(box.height + (20*scale))},
4960                 width:{from:box.width, to:(box.width + (20*scale))}
4961             }, duration, function(){
4962                 proxy.remove();
4963             });
4964             if(--count > 0){
4965                  animFn.defer((duration/2)*1000, this);
4966             }else{
4967                 if(typeof callback == 'function'){
4968                     callback();
4969                 }
4970             }
4971        }
4972        animFn.call(this);
4973    }
4974    this.addAsyncCall(frameFn, 0, null, this);
4975 };
4976
4977 YAHOO.ext.Actor.Action = function(actor, method, args){
4978       this.actor = actor;
4979       this.method = method;
4980       this.args = args;
4981   }
4982   
4983 YAHOO.ext.Actor.Action.prototype = {
4984     play : function(onComplete){
4985         this.method.apply(this.actor || window, this.args);
4986         onComplete();
4987     }  
4988 };
4989
4990
4991 YAHOO.ext.Actor.AsyncAction = function(actor, method, args, onIndex){
4992     YAHOO.ext.Actor.AsyncAction.superclass.constructor.call(this, actor, method, args);
4993     this.onIndex = onIndex;
4994     this.originalCallback = this.args[onIndex];
4995 }
4996 YAHOO.extendX(YAHOO.ext.Actor.AsyncAction, YAHOO.ext.Actor.Action);
4997
4998 YAHOO.ext.Actor.AsyncAction.prototype.play = function(onComplete){
4999     var callbackArg = this.originalCallback ? 
5000                         this.originalCallback.createSequence(onComplete) : onComplete;
5001     this.args[this.onIndex] = callbackArg;
5002     this.method.apply(this.actor, this.args);
5003 };
5004
5005
5006 YAHOO.ext.Actor.PauseAction = function(seconds){
5007     this.seconds = seconds;
5008 };
5009 YAHOO.ext.Actor.PauseAction.prototype = {
5010     play : function(onComplete){
5011         setTimeout(onComplete, this.seconds * 1000);
5012     }
5013 };
5014  
5015  YAHOO.ext.Animator = function(){
5016     this.actors = [];
5017     this.playlist = new YAHOO.ext.Animator.AnimSequence();
5018     this.captureDelegate = this.capture.createDelegate(this);
5019     this.playDelegate = this.play.createDelegate(this);
5020     this.syncing = false;
5021     this.stopping = false;
5022     this.playing = false;
5023     for(var i = 0; i < arguments.length; i++){
5024         this.addActor(arguments[i]);
5025     }
5026  };
5027  
5028  YAHOO.ext.Animator.prototype = {
5029  
5030      capture : function(actor, action){
5031         if(this.syncing){
5032             if(!this.syncMap[actor.id]){
5033                 this.syncMap[actor.id] = new YAHOO.ext.Animator.AnimSequence();
5034             }
5035             this.syncMap[actor.id].add(action);
5036         }else{
5037             this.playlist.add(action);
5038         }
5039     },
5040     
5041     
5042      addActor : function(actor){
5043         actor.onCapture.subscribe(this.captureDelegate);
5044         this.actors.push(actor);
5045     },
5046     
5047     
5048     
5049      startCapture : function(clearPlaylist){
5050         for(var i = 0; i < this.actors.length; i++){
5051             var a = this.actors[i];
5052             if(!this.isCapturing(a)){
5053                 a.onCapture.subscribe(this.captureDelegate);
5054             }
5055             a.capturing = true;
5056         }
5057         if(clearPlaylist){
5058             this.playlist = new YAHOO.ext.Animator.AnimSequence();
5059         }
5060      },
5061      
5062      
5063      isCapturing : function(actor){
5064         var subscribers = actor.onCapture.subscribers;
5065         if(subscribers){
5066             for(var i = 0; i < subscribers.length; i++){
5067                 if(subscribers[i] && subscribers[i].contains(this.captureDelegate)){
5068                     return true;
5069                 }
5070             }
5071         }
5072         return false;
5073      },
5074      
5075      
5076      stopCapture : function(){
5077          for(var i = 0; i < this.actors.length; i++){
5078             var a = this.actors[i];
5079             a.onCapture.unsubscribe(this.captureDelegate);
5080             a.capturing = false;
5081          }
5082      },
5083      
5084      
5085     beginSync : function(){
5086         this.syncing = true;
5087         this.syncMap = {};
5088      },
5089      
5090      
5091     endSync : function(){
5092          this.syncing = false;
5093          var composite = new YAHOO.ext.Animator.CompositeSequence();
5094          for(key in this.syncMap){
5095              if(typeof this.syncMap[key] != 'function'){
5096                 composite.add(this.syncMap[key]);
5097              }
5098          }
5099          this.playlist.add(composite);
5100          this.syncMap = null;
5101      },
5102      
5103     
5104     play : function(oncomplete){
5105         if(this.playing) return; 
5106         this.stopCapture();
5107         this.playlist.play(oncomplete);
5108     },
5109     
5110     
5111     stop : function(){
5112         this.playlist.stop();
5113     },
5114     
5115     
5116     isPlaying : function(){
5117         return this.playlist.isPlaying();
5118     },
5119     
5120     clear : function(){
5121         this.playlist = new YAHOO.ext.Animator.AnimSequence();
5122      },
5123      
5124     
5125      addCall : function(fcn, args, scope){
5126         this.playlist.add(new YAHOO.ext.Actor.Action(scope, fcn, args || []));
5127      },
5128      
5129      
5130     addAsyncCall : function(fcn, callbackIndex, args, scope){
5131         this.playlist.add(new YAHOO.ext.Actor.AsyncAction(scope, fcn, args || [], callbackIndex));
5132      },
5133      
5134      
5135     pause : function(seconds){
5136         this.playlist.add(new YAHOO.ext.Actor.PauseAction(seconds));
5137      }
5138      
5139   };
5140
5141 YAHOO.ext.Animator.select = function(selector){
5142     var els;
5143     if(typeof selector == 'string'){
5144         els = YAHOO.ext.Element.selectorFunction(selector);
5145     }else if(selector instanceof Array){
5146         els = selector;
5147     }else{
5148         throw 'Invalid selector';
5149     }
5150     return new YAHOO.ext.AnimatorComposite(els);
5151 };
5152 var getActors = YAHOO.ext.Animator.select;
5153
5154
5155 YAHOO.ext.AnimatorComposite = function(els){
5156     this.animator = new YAHOO.ext.Animator();
5157     this.addElements(els);
5158     this.syncAnims = true;
5159 };
5160 YAHOO.ext.AnimatorComposite.prototype = {
5161     isComposite: true,
5162     
5163     addElements : function(els){
5164         if(!els) return this;
5165         var anim = this.animator;
5166         for(var i = 0, len = els.length; i < len; i++) {
5167                 anim.addActor(new YAHOO.ext.Actor(els[i]));
5168         }
5169         anim.startCapture();
5170         return this;
5171     },
5172     
5173     sequence : function(){
5174         this.syncAnims = false;
5175         return this;
5176     },
5177     
5178     sync : function(){
5179         this.syncAnims = true;
5180         return this;
5181     },
5182     invoke : function(fn, args){
5183         var els = this.animator.actors;
5184         if(this.syncAnims) this.animator.beginSync();
5185         for(var i = 0, len = els.length; i < len; i++) {
5186             YAHOO.ext.Actor.prototype[fn].apply(els[i], args);
5187         }
5188         if(this.syncAnims) this.animator.endSync();
5189         return this;
5190     },
5191     
5192     play : function(callback){
5193         this.animator.play(callback);
5194         return this;
5195     },
5196     
5197     reset : function(callback){
5198         this.animator.startCapture(true);
5199         return this;
5200     },
5201     
5202     pause : function(seconds){
5203         this.animator.pause(seconds);
5204         return this;
5205     },
5206     
5207     getAnimator : function(){
5208         return this.animator;
5209     },
5210     
5211     each : function(fn, scope){
5212         var els = this.animator.actors;
5213         if(this.syncAnims) this.animator.beginSync();
5214         for(var i = 0, len = els.length; i < len; i++){
5215             fn.call(scope || els[i], els[i], this, i);
5216         }
5217         if(this.syncAnims) this.animator.endSync();
5218         return this;
5219     },
5220     
5221      addCall : function(fcn, args, scope){
5222         this.animator.addCall(fcn, args, scope);
5223         return this;
5224     },
5225     
5226     addAsyncCall : function(fcn, callbackIndex, args, scope){
5227         this.animator.addAsyncCall(fcn, callbackIndex, args, scope);
5228         return this;
5229     }
5230 };
5231 for(var fnName in YAHOO.ext.Actor.prototype){
5232     if(typeof YAHOO.ext.Actor.prototype[fnName] == 'function'){
5233         YAHOO.ext.CompositeElement.createCall(YAHOO.ext.AnimatorComposite.prototype, fnName);
5234     }
5235 }
5236
5237
5238 YAHOO.ext.Animator.AnimSequence = function(){
5239     this.actions = [];
5240     this.nextDelegate = this.next.createDelegate(this);
5241     this.playDelegate = this.play.createDelegate(this);
5242     this.oncomplete = null;
5243     this.playing = false;
5244     this.stopping = false;
5245     this.actionIndex = -1;
5246  };
5247  
5248  YAHOO.ext.Animator.AnimSequence.prototype = {
5249  
5250     add : function(action){
5251         this.actions.push(action);
5252     },
5253     
5254     next : function(){
5255         if(this.stopping){
5256             this.playing = false;
5257             if(this.oncomplete){
5258                 this.oncomplete(this, false);
5259             }
5260             return;
5261         }
5262         var nextAction = this.actions[++this.actionIndex];
5263         if(nextAction){
5264             nextAction.play(this.nextDelegate);
5265         }else{
5266             this.playing = false;
5267             if(this.oncomplete){
5268                 this.oncomplete(this, true);
5269             }
5270         }
5271     },
5272     
5273     play : function(oncomplete){
5274         if(this.playing) return; 
5275         this.oncomplete = oncomplete;
5276         this.stopping = false;
5277         this.playing = true;
5278         this.actionIndex = -1;
5279         this.next();
5280     },
5281     
5282     stop : function(){
5283         this.stopping = true;
5284     },
5285     
5286     isPlaying : function(){
5287         return this.playing;
5288     },
5289     
5290     clear : function(){
5291         this.actions = [];
5292     },
5293      
5294     addCall : function(fcn, args, scope){
5295         this.actions.push(new YAHOO.ext.Actor.Action(scope, fcn, args || []));
5296      },
5297      
5298      addAsyncCall : function(fcn, callbackIndex, args, scope){
5299         this.actions.push(new YAHOO.ext.Actor.AsyncAction(scope, fcn, args || [], callbackIndex));
5300      },
5301      
5302      pause : function(seconds){
5303         this.actions.push(new YAHOO.ext.Actor.PauseAction(seconds));
5304      }
5305      
5306   };
5307
5308 YAHOO.ext.Animator.CompositeSequence = function(){
5309     this.sequences = [];
5310     this.completed = 0;
5311     this.trackDelegate = this.trackCompletion.createDelegate(this);
5312 }
5313
5314 YAHOO.ext.Animator.CompositeSequence.prototype = {
5315     add : function(sequence){
5316         this.sequences.push(sequence);
5317     },
5318     
5319     play : function(onComplete){
5320         this.completed = 0;
5321         if(this.sequences.length < 1){
5322             if(onComplete)onComplete();
5323             return;
5324         }
5325         this.onComplete = onComplete;
5326         for(var i = 0; i < this.sequences.length; i++){
5327             this.sequences[i].play(this.trackDelegate);
5328         }
5329     },
5330     
5331     trackCompletion : function(){
5332         ++this.completed;
5333         if(this.completed >= this.sequences.length && this.onComplete){
5334             this.onComplete();
5335         }
5336     },
5337     
5338     stop : function(){
5339         for(var i = 0; i < this.sequences.length; i++){
5340             this.sequences[i].stop();
5341         }
5342     },
5343     
5344     isPlaying : function(){
5345         for(var i = 0; i < this.sequences.length; i++){
5346             if(this.sequences[i].isPlaying()){
5347                 return true;
5348             }
5349         }
5350         return false;
5351     }
5352 };
5353
5354
5355
5356  
5357  YAHOO.ext.Toolbar = function(container, buttons){
5358     this.el = getEl(container, true);
5359     var div = document.createElement('div');
5360     div.className = 'ytoolbar';
5361     var tb = document.createElement('table');
5362     tb.border = 0;
5363     tb.cellPadding = 0; 
5364     tb.cellSpacing = 0;
5365     div.appendChild(tb);
5366     var tbody = document.createElement('tbody');
5367     tb.appendChild(tbody);
5368     var tr = document.createElement('tr');
5369     tbody.appendChild(tr);
5370     this.el.dom.appendChild(div);
5371     this.tr = tr;
5372     if(buttons){
5373         this.add.apply(this, buttons);
5374     }
5375 };
5376
5377 YAHOO.ext.Toolbar.prototype = {
5378     
5379     add : function(){
5380         for(var i = 0; i < arguments.length; i++){
5381             var el = arguments[i];
5382             var td = document.createElement('td');
5383             this.tr.appendChild(td);
5384             if(el instanceof YAHOO.ext.ToolbarButton){
5385                 el.init(td);
5386             }else if(el instanceof Array){
5387                 this.addButton(el);
5388             }else if(typeof el == 'string'){
5389                 var span = document.createElement('span');
5390                 if(el == 'separator'){
5391                     span.className = 'ytb-sep';
5392                 }else{
5393                     span.innerHTML = el;
5394                     span.className = 'ytb-text';
5395                 }
5396                 td.appendChild(span);
5397             }else if(typeof el == 'object' && el.nodeType){ 
5398                 td.appendChild(el);
5399             }else if(typeof el == 'object'){ 
5400                 this.addButton(el);
5401             }
5402         }
5403     },
5404     
5405     
5406     getEl : function(){
5407         return this.el;  
5408     },
5409     
5410     
5411     addSeparator : function(){
5412         var td = document.createElement('td');
5413         this.tr.appendChild(td);
5414         var span = document.createElement('span');
5415         span.className = 'ytb-sep';
5416         td.appendChild(span);
5417     },
5418     
5419     
5420     addButton : function(config){
5421         if(config instanceof Array){
5422             var buttons = [];
5423             for(var i = 0, len = config.length; i < len; i++) {
5424                 buttons.push(this.addButton(config[i]));
5425             }
5426             return buttons;
5427         }
5428         var b = config;
5429         if(!(config instanceof YAHOO.ext.ToolbarButton)){
5430              b = new YAHOO.ext.ToolbarButton(config);
5431         }
5432         this.add(b);
5433         return b;
5434     },
5435     
5436     
5437     addText : function(text){
5438         var td = document.createElement('td');
5439         this.tr.appendChild(td);
5440         var span = document.createElement('span');
5441         span.className = 'ytb-text';
5442         span.innerHTML = text;
5443         td.appendChild(span);
5444         return span;
5445     },
5446     
5447     
5448     insertButton : function(index, config){
5449         if(config instanceof Array){
5450             var buttons = [];
5451             for(var i = 0, len = config.length; i < len; i++) {
5452                buttons.push(this.insertButton(index + i, config[i]));
5453             }
5454             return buttons;
5455         }
5456         var b = new YAHOO.ext.ToolbarButton(config);
5457         var td = document.createElement('td');
5458         var nextSibling = this.tr.childNodes[index];
5459         if (nextSibling)
5460            this.tr.insertBefore(td, nextSibling);
5461        else
5462            this.tr.appendChild(td);
5463         b.init(td);
5464         return b;
5465     }
5466 };
5467
5468
5469 YAHOO.ext.ToolbarButton = function(config){
5470     YAHOO.ext.util.Config.apply(this, config);
5471 };
5472
5473 YAHOO.ext.ToolbarButton.prototype = {
5474     
5475     init : function(appendTo){
5476         var element = document.createElement('span');
5477         element.className = 'ytb-button';
5478         if(this.id){
5479             element.id = this.id;
5480         }
5481         this.setDisabled(this.disabled === true);
5482         var inner = document.createElement('span');
5483         inner.className = 'ytb-button-inner ' + this.className;
5484         inner.unselectable = 'on';
5485         if(this.tooltip){
5486             element.setAttribute('title', this.tooltip);
5487         }
5488         if(this.style){
5489            YAHOO.ext.DomHelper.applyStyles(inner, this.style);
5490         } 
5491         element.appendChild(inner);
5492         appendTo.appendChild(element);
5493         this.el = getEl(element, true);
5494         this.el.unselectable();
5495         inner.innerHTML = (this.text ? this.text : '&#160;');
5496         this.inner = inner;
5497         this.el.mon('click', this.onClick, this, true);    
5498         this.el.mon('mouseover', this.onMouseOver, this, true);    
5499         this.el.mon('mouseout', this.onMouseOut, this, true);
5500     },
5501     
5502     
5503     setHandler : function(click, scope){
5504         this.click = click;
5505         this.scope = scope;  
5506     },
5507     
5508     
5509     setText : function(text){
5510         this.inner.innerHTML = text;    
5511     },
5512     
5513     
5514     setTooltip : function(text){
5515         this.el.dom.title = text;    
5516     },
5517     
5518     
5519     show: function(){
5520         this.el.dom.parentNode.style.display = '';
5521     },
5522     
5523     
5524     hide: function(){
5525         this.el.dom.parentNode.style.display = 'none';  
5526     },
5527     
5528     
5529     disable : function(){
5530         this.disabled = true;
5531         if(this.el){
5532             this.el.addClass('ytb-button-disabled');
5533         }
5534     },
5535     
5536     
5537     enable : function(){
5538         this.disabled = false;
5539         if(this.el){
5540             this.el.removeClass('ytb-button-disabled');
5541         }
5542     },
5543     
5544     
5545     isDisabled : function(){
5546         return this.disabled === true;
5547     },
5548     
5549     setDisabled : function(disabled){
5550         if(disabled){
5551             this.disable();
5552         }else{
5553             this.enable();
5554         }
5555     },
5556     
5557     
5558     onClick : function(){
5559         if(!this.disabled && this.click){
5560             this.click.call(this.scope || window, this);
5561         }
5562     },
5563     
5564     
5565     onMouseOver : function(){
5566         if(!this.disabled){
5567             this.el.addClass('ytb-button-over');
5568             if(this.mouseover){
5569                 this.mouseover.call(this.scope || window, this);
5570             }
5571         }
5572     },
5573     
5574     
5575     onMouseOut : function(){
5576         this.el.removeClass('ytb-button-over');
5577         if(!this.disabled){
5578             if(this.mouseout){
5579                 this.mouseout.call(this.scope || window, this);
5580             }
5581         }
5582     }
5583 };
5584
5585 YAHOO.ext.Resizable = function(el, config){
5586     this.el = getEl(el);
5587     
5588     if(config && config.wrap){
5589         config.resizeChild = this.el;
5590         this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : null);
5591         this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
5592         this.el.setStyle('overflow', 'hidden');
5593         this.el.setPositioning(config.resizeChild.getPositioning());
5594         config.resizeChild.clearPositioning();
5595         if(!config.width || !config.height){
5596             var csize = config.resizeChild.getSize();
5597             
5598             
5599             this.el.setSize(csize.width, csize.height);
5600         }
5601         if(config.pinned && !config.adjustments){
5602             config.adjustments = 'auto';
5603         }
5604     }
5605     
5606     this.proxy = this.el.createProxy({tag: 'div', cls: 'yresizable-proxy', id: this.el.id + '-rzproxy'})
5607     this.proxy.unselectable();
5608     
5609     
5610     this.overlay = this.el.createProxy({tag: 'div', cls: 'yresizable-overlay', html: '&#160;'});
5611     this.overlay.unselectable();
5612     this.overlay.enableDisplayMode('block');
5613     this.overlay.mon('mousemove', this.onMouseMove, this, true);
5614     this.overlay.mon('mouseup', this.onMouseUp, this, true);
5615     
5616     YAHOO.ext.util.Config.apply(this, config, {
5617         
5618         resizeChild : false,
5619         
5620         adjustments : [0, 0],
5621         
5622         minWidth : 5,
5623         
5624         minHeight : 5,
5625         
5626         maxWidth : 10000,
5627         
5628         maxHeight : 10000,
5629         
5630         enabled : true,
5631         
5632         animate : false,
5633         
5634         duration : .35,
5635         
5636         dynamic : false,
5637         
5638         
5639         handles : false,
5640         multiDirectional : false,
5641         
5642         disableTrackOver : false,
5643         
5644         easing : YAHOO.util.Easing ? YAHOO.util.Easing.easeOutStrong : null,
5645         
5646         widthIncrement : 0,
5647         
5648         heightIncrement : 0,
5649         
5650         pinned : false,
5651         
5652         width : null,
5653         
5654         height : null,
5655         
5656         preserveRatio : false,
5657         
5658         transparent: false,
5659         
5660         minX: 0,
5661         
5662         minY: 0,
5663         
5664         draggable: false
5665     });
5666     
5667     if(this.pinned){
5668         this.disableTrackOver = true;
5669         this.el.addClass('yresizable-pinned');    
5670     }
5671     
5672     var position = this.el.getStyle('position');
5673     if(position != 'absolute' && position != 'fixed'){
5674         this.el.setStyle('position', 'relative');
5675     }
5676     if(!this.handles){ 
5677         this.handles = 's,e,se';
5678         if(this.multiDirectional){
5679             this.handles += ',n,w';
5680         }
5681     }
5682     if(this.handles == 'all'){
5683         this.handles = 'n s e w ne nw se sw';
5684     }
5685     var hs = this.handles.split(/\s*?[,;]\s*?| /);
5686     var ps = YAHOO.ext.Resizable.positions;
5687     for(var i = 0, len = hs.length; i < len; i++){
5688         if(hs[i] && ps[hs[i]]){
5689             var pos = ps[hs[i]];
5690             this[pos] = new YAHOO.ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
5691         }
5692     }
5693     
5694     this.corner = this.southeast;
5695     
5696     this.activeHandle = null;
5697     
5698     if(this.resizeChild){
5699         if(typeof this.resizeChild == 'boolean'){
5700             this.resizeChild = YAHOO.ext.Element.get(this.el.dom.firstChild, true);
5701         }else{
5702             this.resizeChild = YAHOO.ext.Element.get(this.resizeChild, true);
5703         }
5704     }
5705     
5706     if(this.adjustments == 'auto'){
5707         var rc = this.resizeChild;
5708         var hw = this.west, he = this.east, hn = this.north, hs = this.south;
5709         if(rc && (hw || hn)){
5710             rc.setRelativePositioned();
5711             rc.setLeft(hw ? hw.el.getWidth() : 0);
5712             rc.setTop(hn ? hn.el.getHeight() : 0);
5713         }
5714         this.adjustments = [
5715             (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
5716             (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 
5717         ];
5718     }
5719     
5720     if(this.draggable){
5721         this.dd = this.dynamic ? 
5722             this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
5723         this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
5724     }
5725     
5726     
5727     this.events = {
5728         
5729         'beforeresize' : new YAHOO.util.CustomEvent(),
5730         
5731         'resize' : new YAHOO.util.CustomEvent()
5732     };
5733     
5734     if(this.width !== null && this.height !== null){
5735         this.resizeTo(this.width, this.height);
5736     }else{
5737         this.updateChildSize();
5738     }
5739 };
5740
5741 YAHOO.extendX(YAHOO.ext.Resizable, YAHOO.ext.util.Observable, {
5742     
5743     resizeTo : function(width, height){
5744         this.el.setSize(width, height);
5745         this.updateChildSize();
5746         this.fireEvent('resize', this, width, height, null);
5747     },
5748     
5749     startSizing : function(e){
5750         this.fireEvent('beforeresize', this, e);
5751         if(this.enabled){ 
5752             this.resizing = true;
5753             this.startBox = this.el.getBox();
5754             this.startPoint = e.getXY();
5755             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
5756                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
5757             this.proxy.setBox(this.startBox);
5758             
5759             this.overlay.setSize(YAHOO.util.Dom.getDocumentWidth(), YAHOO.util.Dom.getDocumentHeight());
5760             this.overlay.show();
5761             
5762             if(!this.dynamic){
5763                 this.proxy.show();
5764             }
5765         }
5766     },
5767     
5768     onMouseDown : function(handle, e){
5769         if(this.enabled){
5770             e.stopEvent();
5771             this.activeHandle = handle;
5772             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
5773             this.startSizing(e);
5774         }          
5775     },
5776     
5777     onMouseUp : function(e){
5778         var size = this.resizeElement();
5779         this.resizing = false;
5780         this.handleOut();
5781         this.overlay.hide();
5782         this.fireEvent('resize', this, size.width, size.height, e);
5783     },
5784     
5785     updateChildSize : function(){
5786         if(this.resizeChild){
5787             var el = this.el;
5788             var child = this.resizeChild;
5789             var adj = this.adjustments;
5790             if(el.dom.offsetWidth){
5791                 var b = el.getSize(true);
5792                 child.setSize(b.width+adj[0], b.height+adj[1]);
5793             }
5794             
5795             
5796             
5797             
5798             if(YAHOO.ext.util.Browser.isIE){
5799                 setTimeout(function(){
5800                     if(el.dom.offsetWidth){
5801                         var b = el.getSize(true);
5802                         child.setSize(b.width+adj[0], b.height+adj[1]);
5803                     }
5804                 }, 10);
5805             }
5806         }
5807     },
5808     
5809     snap : function(value, inc, min){
5810         if(!inc || !value) return value;
5811         var newValue = value;
5812         var m = value % inc;
5813         if(m > 0){
5814             if(m > (inc/2)){
5815                 newValue = value + (inc-m);
5816             }else{
5817                 newValue = value - m;
5818             }
5819         }
5820         return Math.max(min, newValue);
5821     },
5822     
5823     resizeElement : function(){
5824         var box = this.proxy.getBox();
5825         
5826         
5827         
5828             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
5829         
5830         
5831         
5832         this.updateChildSize();
5833         this.proxy.hide();
5834         return box;
5835     },
5836     
5837     constrain : function(v, diff, m, mx){
5838         if(v - diff < m){
5839             diff = v - m;    
5840         }else if(v - diff > mx){
5841             diff = mx - v; 
5842         }
5843         return diff;                
5844     },
5845     
5846     onMouseMove : function(e){
5847         if(this.enabled){
5848             try{
5849             
5850             
5851             var curSize = this.curSize || this.startBox;
5852             var x = this.startBox.x, y = this.startBox.y;
5853             var ox = x, oy = y;
5854             var w = curSize.width, h = curSize.height;
5855             var ow = w, oh = h;
5856             var mw = this.minWidth, mh = this.minHeight;
5857             var mxw = this.maxWidth, mxh = this.maxHeight;
5858             var wi = this.widthIncrement;
5859             var hi = this.heightIncrement;
5860             
5861             var eventXY = e.getXY();
5862             var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
5863             var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
5864             
5865             var pos = this.activeHandle.position;
5866             
5867             switch(pos){
5868                 case 'east':
5869                     w += diffX; 
5870                     w = Math.min(Math.max(mw, w), mxw);
5871                     break;
5872                 case 'south':
5873                     h += diffY;
5874                     h = Math.min(Math.max(mh, h), mxh);
5875                     break;
5876                 case 'southeast':
5877                     w += diffX; 
5878                     h += diffY;
5879                     w = Math.min(Math.max(mw, w), mxw);
5880                     h = Math.min(Math.max(mh, h), mxh);
5881                     break;
5882                 case 'north':
5883                     diffY = this.constrain(h, diffY, mh, mxh);
5884                     y += diffY;
5885                     h -= diffY;
5886                     break;
5887                 case 'west':
5888                     diffX = this.constrain(w, diffX, mw, mxw);
5889                     x += diffX;
5890                     w -= diffX;
5891                     break;
5892                 case 'northeast':
5893                     w += diffX; 
5894                     w = Math.min(Math.max(mw, w), mxw);
5895                     diffY = this.constrain(h, diffY, mh, mxh);
5896                     y += diffY;
5897                     h -= diffY;
5898                     break;
5899                 case 'northwest':
5900                     diffX = this.constrain(w, diffX, mw, mxw);
5901                     diffY = this.constrain(h, diffY, mh, mxh);
5902                     y += diffY;
5903                     h -= diffY;
5904                     x += diffX;
5905                     w -= diffX;
5906                     break;
5907                case 'southwest':
5908                     diffX = this.constrain(w, diffX, mw, mxw);
5909                     h += diffY;
5910                     h = Math.min(Math.max(mh, h), mxh);
5911                     x += diffX;
5912                     w -= diffX;
5913                     break;
5914             }
5915             
5916             var sw = this.snap(w, wi, mw);
5917             var sh = this.snap(h, hi, mh);
5918             if(sw != w || sh != h){
5919                 switch(pos){
5920                     case 'northeast':
5921                         y -= sh - h;
5922                     break;
5923                     case 'north':
5924                         y -= sh - h;
5925                         break;
5926                     case 'southwest':
5927                         x -= sw - w;
5928                     break;
5929                     case 'west':
5930                         x -= sw - w;
5931                         break;
5932                     case 'northwest':
5933                         x -= sw - w;
5934                         y -= sh - h;
5935                     break;
5936                 }
5937                 w = sw;
5938                 h = sh;
5939             }
5940             
5941             if(this.preserveRatio){
5942                 switch(pos){
5943                     case 'southeast':
5944                     case 'east':
5945                         h = oh * (w/ow);
5946                         h = Math.min(Math.max(mh, h), mxh);
5947                         w = ow * (h/oh);
5948                        break;
5949                     case 'south':
5950                         w = ow * (h/oh);
5951                         w = Math.min(Math.max(mw, w), mxw);
5952                         h = oh * (w/ow);
5953                         break;
5954                     case 'northeast':
5955                         w = ow * (h/oh);
5956                         w = Math.min(Math.max(mw, w), mxw);
5957                         h = oh * (w/ow);
5958                     break;
5959                     case 'north':
5960                         var tw = w;
5961                         w = ow * (h/oh);
5962                         w = Math.min(Math.max(mw, w), mxw);
5963                         h = oh * (w/ow);
5964                         x += (tw - w) / 2;
5965                         break;
5966                     case 'southwest':
5967                         h = oh * (w/ow);
5968                         h = Math.min(Math.max(mh, h), mxh);
5969                         var tw = w;
5970                         w = ow * (h/oh);
5971                         x += tw - w;
5972                         break;
5973                     case 'west':
5974                         var th = h;
5975                         h = oh * (w/ow);
5976                         h = Math.min(Math.max(mh, h), mxh);
5977                         y += (th - h) / 2;
5978                         var tw = w;
5979                         w = ow * (h/oh);
5980                         x += tw - w;
5981                        break;
5982                     case 'northwest':
5983                         var tw = w;
5984                         var th = h;
5985                         h = oh * (w/ow);
5986                         h = Math.min(Math.max(mh, h), mxh);
5987                         w = ow * (h/oh);
5988                         y += th - h;
5989                          x += tw - w;
5990                        break;
5991                         
5992                 }
5993             }
5994             this.proxy.setBounds(x, y, w, h);
5995             if(this.dynamic){
5996                 this.resizeElement();
5997             }
5998             }catch(e){}
5999         }
6000     },
6001     
6002     handleOver : function(){
6003         if(this.enabled){
6004             this.el.addClass('yresizable-over');
6005         }
6006     },
6007     
6008     handleOut : function(){
6009         if(!this.resizing){
6010             this.el.removeClass('yresizable-over');
6011         }
6012     },
6013     
6014     
6015     getEl : function(){
6016         return this.el;
6017     },
6018     
6019     
6020     getResizeChild : function(){
6021         return this.resizeChild;
6022     }
6023 });
6024
6025
6026 YAHOO.ext.Resizable.positions = {
6027     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast' 
6028 };
6029
6030
6031 YAHOO.ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
6032     if(!this.tpl){
6033         
6034         var tpl = YAHOO.ext.DomHelper.createTemplate(
6035             {tag: 'div', cls: 'yresizable-handle yresizable-handle-{0}', html: '&#160;'}
6036         );
6037         tpl.compile();
6038         YAHOO.ext.Resizable.Handle.prototype.tpl = tpl;
6039     }
6040     this.position = pos;
6041     this.rz = rz;
6042     this.el = this.tpl.append(rz.el.dom, [this.position], true);
6043     this.el.unselectable();
6044     if(transparent){
6045         this.el.setOpacity(0);
6046     }
6047     this.el.mon('mousedown', this.onMouseDown, this, true);
6048     if(!disableTrackOver){
6049         this.el.mon('mouseover', this.onMouseOver, this, true);
6050         this.el.mon('mouseout', this.onMouseOut, this, true);
6051     }
6052 };
6053
6054 YAHOO.ext.Resizable.Handle.prototype = {
6055     afterResize : function(rz){
6056         
6057     },
6058     
6059     onMouseDown : function(e){
6060         this.rz.onMouseDown(this, e);
6061     },
6062     
6063     onMouseOver : function(e){
6064         this.rz.handleOver(this, e);
6065     },
6066     
6067     onMouseOut : function(e){
6068         this.rz.handleOut(this, e);
6069     }  
6070 };
6071
6072
6073
6074
6075 if(YAHOO.util.DragDropMgr){
6076   YAHOO.util.DragDropMgr.clickTimeThresh = 350;
6077 }
6078
6079 YAHOO.ext.SplitBar = function(dragElement, resizingElement, orientation, placement){
6080     
6081     
6082     this.el = YAHOO.ext.Element.get(dragElement, true);
6083     this.el.dom.unselectable = 'on';
6084     
6085     this.resizingEl = YAHOO.ext.Element.get(resizingElement, true);
6086     
6087     
6088     this.orientation = orientation || YAHOO.ext.SplitBar.HORIZONTAL;
6089     
6090     
6091     this.minSize = 0;
6092     
6093     
6094     this.maxSize = 2000;
6095     
6096     this.onMoved = new YAHOO.util.CustomEvent("SplitBarMoved", this);
6097     
6098     
6099     this.animate = false;
6100     
6101     
6102     this.useShim = false;
6103     
6104     
6105     this.shim = null;
6106     
6107     
6108     this.proxy = YAHOO.ext.SplitBar.createProxy(this.orientation);
6109     
6110     
6111     this.dd = new YAHOO.util.DDProxy(this.el.dom.id, "SplitBars", {dragElId : this.proxy.id});
6112     
6113     
6114     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
6115     
6116     
6117     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
6118     
6119     
6120     this.dragSpecs = {};
6121     
6122     
6123     this.adapter = new YAHOO.ext.SplitBar.BasicLayoutAdapter();
6124     this.adapter.init(this);
6125     
6126     if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6127         
6128         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? YAHOO.ext.SplitBar.LEFT : YAHOO.ext.SplitBar.RIGHT);
6129         this.el.setStyle('cursor', 'e-resize');
6130     }else{
6131         
6132         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? YAHOO.ext.SplitBar.TOP : YAHOO.ext.SplitBar.BOTTOM);
6133         this.el.setStyle('cursor', 'n-resize');
6134     }
6135     
6136     this.events = {
6137         
6138         'resize' : this.onMoved,
6139         
6140         'moved' : this.onMoved,
6141         
6142         'beforeresize' : new YAHOO.util.CustomEvent('beforeresize')
6143     }
6144 }
6145
6146 YAHOO.extendX(YAHOO.ext.SplitBar, YAHOO.ext.util.Observable, {
6147     onStartProxyDrag : function(x, y){
6148         this.fireEvent('beforeresize', this);
6149         if(this.useShim){
6150             if(!this.shim){
6151                 this.shim = YAHOO.ext.SplitBar.createShim();
6152             }
6153             this.shim.setVisible(true);
6154         }
6155         YAHOO.util.Dom.setStyle(this.proxy, 'display', 'block');
6156         var size = this.adapter.getElementSize(this);
6157         this.activeMinSize = this.getMinimumSize();;
6158         this.activeMaxSize = this.getMaximumSize();;
6159         var c1 = size - this.activeMinSize;
6160         var c2 = Math.max(this.activeMaxSize - size, 0);
6161         if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6162             this.dd.resetConstraints();
6163             this.dd.setXConstraint(
6164                 this.placement == YAHOO.ext.SplitBar.LEFT ? c1 : c2, 
6165                 this.placement == YAHOO.ext.SplitBar.LEFT ? c2 : c1
6166             );
6167             this.dd.setYConstraint(0, 0);
6168         }else{
6169             this.dd.resetConstraints();
6170             this.dd.setXConstraint(0, 0);
6171             this.dd.setYConstraint(
6172                 this.placement == YAHOO.ext.SplitBar.TOP ? c1 : c2, 
6173                 this.placement == YAHOO.ext.SplitBar.TOP ? c2 : c1
6174             );
6175          }
6176         this.dragSpecs.startSize = size;
6177         this.dragSpecs.startPoint = [x, y];
6178         
6179         YAHOO.util.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
6180     },
6181     
6182     
6183     onEndProxyDrag : function(e){
6184         YAHOO.util.Dom.setStyle(this.proxy, 'display', 'none');
6185         var endPoint = YAHOO.util.Event.getXY(e);
6186         if(this.useShim){
6187             this.shim.setVisible(false);
6188         }
6189         var newSize;
6190         if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6191             newSize = this.dragSpecs.startSize + 
6192                 (this.placement == YAHOO.ext.SplitBar.LEFT ?
6193                     endPoint[0] - this.dragSpecs.startPoint[0] :
6194                     this.dragSpecs.startPoint[0] - endPoint[0]
6195                 );
6196         }else{
6197             newSize = this.dragSpecs.startSize + 
6198                 (this.placement == YAHOO.ext.SplitBar.TOP ?
6199                     endPoint[1] - this.dragSpecs.startPoint[1] :
6200                     this.dragSpecs.startPoint[1] - endPoint[1]
6201                 );
6202         }
6203         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
6204         if(newSize != this.dragSpecs.startSize){
6205             this.adapter.setElementSize(this, newSize);
6206             this.onMoved.fireDirect(this, newSize);
6207         }
6208     },
6209     
6210     
6211     getAdapter : function(){
6212         return this.adapter;
6213     },
6214     
6215     
6216     setAdapter : function(adapter){
6217         this.adapter = adapter;
6218         this.adapter.init(this);
6219     },
6220     
6221     
6222     getMinimumSize : function(){
6223         return this.minSize;
6224     },
6225     
6226     
6227     setMinimumSize : function(minSize){
6228         this.minSize = minSize;
6229     },
6230     
6231     
6232     getMaximumSize : function(){
6233         return this.maxSize;
6234     },
6235     
6236     
6237     setMaximumSize : function(maxSize){
6238         this.maxSize = maxSize;
6239     },
6240     
6241     
6242     setCurrentSize : function(size){
6243         var oldAnimate = this.animate;
6244         this.animate = false;
6245         this.adapter.setElementSize(this, size);
6246         this.animate = oldAnimate;
6247     },
6248     
6249     
6250     destroy : function(removeEl){
6251         if(this.shim){
6252             this.shim.remove();
6253         }
6254         this.dd.unreg();
6255         this.proxy.parentNode.removeChild(this.proxy);
6256         if(removeEl){
6257             this.el.remove();
6258         }
6259     }
6260 });
6261
6262
6263 YAHOO.ext.SplitBar.createShim = function(){
6264     var shim = document.createElement('div');
6265     shim.unselectable = 'on';
6266     YAHOO.util.Dom.generateId(shim, 'split-shim');
6267     YAHOO.util.Dom.setStyle(shim, 'width', '100%');
6268     YAHOO.util.Dom.setStyle(shim, 'height', '100%');
6269     YAHOO.util.Dom.setStyle(shim, 'position', 'absolute');
6270     YAHOO.util.Dom.setStyle(shim, 'background', 'white');
6271     YAHOO.util.Dom.setStyle(shim, 'z-index', 11000);
6272     window.document.body.appendChild(shim);
6273     var shimEl = YAHOO.ext.Element.get(shim);
6274     shimEl.setOpacity(.01);
6275     shimEl.setXY([0, 0]);
6276     return shimEl;
6277 };
6278
6279
6280 YAHOO.ext.SplitBar.createProxy = function(orientation){
6281     var proxy = document.createElement('div');
6282     proxy.unselectable = 'on';
6283     YAHOO.util.Dom.generateId(proxy, 'split-proxy');
6284     YAHOO.util.Dom.setStyle(proxy, 'position', 'absolute');
6285     YAHOO.util.Dom.setStyle(proxy, 'visibility', 'hidden');
6286     YAHOO.util.Dom.setStyle(proxy, 'z-index', 11001);
6287     YAHOO.util.Dom.setStyle(proxy, 'background-color', "#aaa");
6288     if(orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6289         YAHOO.util.Dom.setStyle(proxy, 'cursor', 'e-resize');
6290     }else{
6291         YAHOO.util.Dom.setStyle(proxy, 'cursor', 'n-resize');
6292     }
6293     
6294     YAHOO.util.Dom.setStyle(proxy, 'line-height', '0px');
6295     YAHOO.util.Dom.setStyle(proxy, 'font-size', '0px');
6296     window.document.body.appendChild(proxy);
6297     return proxy;
6298 };
6299
6300
6301 YAHOO.ext.SplitBar.BasicLayoutAdapter = function(){
6302 };
6303
6304 YAHOO.ext.SplitBar.BasicLayoutAdapter.prototype = {
6305     
6306     init : function(s){
6307     
6308     },
6309     
6310      getElementSize : function(s){
6311         if(s.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6312             return s.resizingEl.getWidth();
6313         }else{
6314             return s.resizingEl.getHeight();
6315         }
6316     },
6317     
6318     
6319     setElementSize : function(s, newSize, onComplete){
6320         if(s.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
6321             if(!YAHOO.util.Anim || !s.animate){
6322                 s.resizingEl.setWidth(newSize);
6323                 if(onComplete){
6324                     onComplete(s, newSize);
6325                 }
6326             }else{
6327                 s.resizingEl.setWidth(newSize, true, .1, onComplete, YAHOO.util.Easing.easeOut);
6328             }
6329         }else{
6330             
6331             if(!YAHOO.util.Anim || !s.animate){
6332                 s.resizingEl.setHeight(newSize);
6333                 if(onComplete){
6334                     onComplete(s, newSize);
6335                 }
6336             }else{
6337                 s.resizingEl.setHeight(newSize, true, .1, onComplete, YAHOO.util.Easing.easeOut);
6338             }
6339         }
6340     }
6341 };
6342
6343
6344 YAHOO.ext.SplitBar.AbsoluteLayoutAdapter = function(container){
6345     this.basic = new YAHOO.ext.SplitBar.BasicLayoutAdapter();
6346     this.container = getEl(container);
6347 }
6348
6349 YAHOO.ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
6350     init : function(s){
6351         this.basic.init(s);
6352         
6353     },
6354     
6355     getElementSize : function(s){
6356         return this.basic.getElementSize(s);
6357     },
6358     
6359     setElementSize : function(s, newSize, onComplete){
6360         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
6361     },
6362     
6363     moveSplitter : function(s){
6364         var yes = YAHOO.ext.SplitBar;
6365         switch(s.placement){
6366             case yes.LEFT:
6367                 s.el.setX(s.resizingEl.getRight());
6368                 break;
6369             case yes.RIGHT:
6370                 s.el.setStyle('right', (this.container.getWidth() - s.resizingEl.getLeft()) + 'px');
6371                 break;
6372             case yes.TOP:
6373                 s.el.setY(s.resizingEl.getBottom());
6374                 break;
6375             case yes.BOTTOM:
6376                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
6377                 break;
6378         }
6379     }
6380 };
6381
6382
6383 YAHOO.ext.SplitBar.VERTICAL = 1;
6384
6385
6386 YAHOO.ext.SplitBar.HORIZONTAL = 2;
6387
6388
6389 YAHOO.ext.SplitBar.LEFT = 1;
6390
6391
6392 YAHOO.ext.SplitBar.RIGHT = 2;
6393
6394
6395 YAHOO.ext.SplitBar.TOP = 3;
6396
6397
6398 YAHOO.ext.SplitBar.BOTTOM = 4;
6399
6400
6401 YAHOO.ext.grid.Grid = function(container, config, colModel, selectionModel){
6402         
6403         this.container = YAHOO.ext.Element.get(container);
6404         this.container.update('');
6405         this.container.setStyle('overflow', 'hidden');
6406         this.id = this.container.id;
6407         this.rows = [];
6408     this.rowCount = 0;
6409     this.fieldId = null;
6410     var dataModel = config; 
6411     this.dataModel = dataModel;
6412     this.colModel = colModel;
6413     this.selModel = selectionModel;
6414         this.activeEditor = null;
6415         this.editingCell = null;
6416         
6417         
6418         this.minColumnWidth = 25;
6419         
6420         
6421         this.autoSizeColumns = false;
6422         
6423         
6424         this.autoSizeHeaders = false;
6425         
6426         
6427         this.monitorWindowResize = true;
6428         
6429         
6430         this.maxRowsToMeasure = 0;
6431         
6432         
6433         this.trackMouseOver = false;
6434         
6435         
6436         this.enableDragDrop = false;
6437         
6438         
6439         this.stripeRows = true;
6440         
6441         this.autoHeight = false;
6442         
6443         
6444         this.autoWidth = false;
6445         
6446         
6447         this.view = null;
6448         
6449         
6450     this.allowTextSelectionPattern = /INPUT|TEXTAREA|SELECT/i;
6451         
6452         if(typeof config == 'object' && !config.getRowCount){
6453             YAHOO.ext.util.Config.apply(this, config);
6454         }
6455         
6456         
6457         this.setValueDelegate = this.setCellValue.createDelegate(this);
6458         
6459         
6460         this.events = {
6461             
6462             
6463             'click' : true,
6464             
6465             'dblclick' : true,
6466             
6467             'mousedown' : true,
6468             
6469             'mouseup' : true,
6470             
6471             'mouseover' : true,
6472             
6473             'mouseout' : true,
6474             
6475             'keypress' : true,
6476             
6477             'keydown' : true,
6478             
6479             
6480             
6481             
6482             'cellclick' : true,
6483             
6484             'celldblclick' : true,
6485             
6486             'rowclick' : true,
6487             
6488             'rowdblclick' : true,
6489             
6490             'headerclick' : true,
6491             
6492             'rowcontextmenu' : true,
6493             
6494             'headercontextmenu' : true,
6495             
6496             'beforeedit' : true,
6497             
6498             'afteredit' : true,
6499             
6500             'bodyscroll' : true,
6501             
6502             'columnresize' : true,
6503             
6504             'startdrag' : true,
6505             
6506             'enddrag' : true,
6507             
6508             'dragdrop' : true,
6509             
6510             'dragover' : true,
6511             
6512             'dragenter' : true,
6513             
6514             'dragout' : true
6515         };
6516 };
6517
6518 YAHOO.ext.grid.Grid.prototype = { 
6519     
6520     render : function(){
6521         if((!this.container.dom.offsetHeight || this.container.dom.offsetHeight < 20) 
6522                 || this.container.getStyle('height') == 'auto'){
6523             this.autoHeight = true;   
6524         }              
6525         if((!this.container.dom.offsetWidth || this.container.dom.offsetWidth < 20)){
6526             this.autoWidth = true;   
6527         }              
6528         if(!this.view){
6529             if(this.dataModel.isPaged()){
6530                     this.view = new YAHOO.ext.grid.PagedGridView();
6531             }else{
6532                 this.view = new YAHOO.ext.grid.GridView();
6533             }
6534         }
6535         this.view.init(this);
6536         this.el = getEl(this.view.render(), true);
6537         var c = this.container;
6538         c.mon("click", this.onClick, this, true);
6539         c.mon("dblclick", this.onDblClick, this, true);
6540         c.mon("contextmenu", this.onContextMenu, this, true);
6541         c.mon("selectstart", this.cancelTextSelection, this, true);
6542         c.mon("mousedown", this.cancelTextSelection, this, true);
6543         c.mon("mousedown", this.onMouseDown, this, true);
6544         c.mon("mouseup", this.onMouseUp, this, true);
6545         if(this.trackMouseOver){
6546             this.el.mon("mouseover", this.onMouseOver, this, true);
6547             this.el.mon("mouseout", this.onMouseOut, this, true);
6548         }
6549         c.mon("keypress", this.onKeyPress, this, true);
6550         c.mon("keydown", this.onKeyDown, this, true);
6551         this.init();
6552         return this;
6553     },
6554     
6555     init : function(){
6556         this.rows = this.el.dom.rows;
6557         if(!this.disableSelection){
6558                 if(!this.selModel){
6559                     this.selModel = new YAHOO.ext.grid.DefaultSelectionModel(this);
6560                 }
6561                 this.selModel.init(this);
6562                 this.selModel.onSelectionChange.subscribe(this.updateField, this, true);
6563         }else{
6564             this.selModel = new YAHOO.ext.grid.DisableSelectionModel(this);
6565             this.selModel.init(this);
6566         }
6567         
6568         if(this.enableDragDrop){
6569             this.dd = new YAHOO.ext.grid.GridDD(this, this.container.dom);
6570         }
6571      },   
6572
6573     
6574     reset : function(config){
6575         this.destroy(false, true);
6576         YAHOO.ext.util.Config.apply(this, config);
6577         return this;
6578     },
6579     
6580     
6581     destroy : function(removeEl, keepListeners){
6582         var c = this.container;
6583         c.removeAllListeners();
6584         this.view.destroy();
6585         YAHOO.ext.EventManager.removeResizeListener(this.view.onWindowResize, this.view);
6586         this.view = null;
6587         this.colModel.purgeListeners();
6588         if(!keepListeners){
6589             this.purgeListeners();
6590         }
6591         c.update('');
6592         if(removeEl === true){
6593             c.remove();
6594         }
6595     },
6596     
6597     
6598     setDataModel : function(dm, rerender){
6599         this.view.unplugDataModel(this.dataModel);
6600         this.dataModel = dm;
6601         this.view.plugDataModel(dm);
6602         if(rerender){
6603             dm.fireEvent('datachanged');
6604         }
6605     },
6606     
6607     onMouseDown : function(e){
6608         this.fireEvent('mousedown', e);
6609     },
6610     
6611     onMouseUp : function(e){
6612         this.fireEvent('mouseup', e);
6613     },
6614     
6615     onMouseOver : function(e){
6616         this.fireEvent('mouseover', e);
6617     },
6618     
6619     onMouseOut : function(e){
6620         this.fireEvent('mouseout', e);
6621     },
6622     
6623     onKeyPress : function(e){
6624         this.fireEvent('keypress', e);
6625     },
6626     
6627     onKeyDown : function(e){
6628         this.fireEvent('keydown', e);
6629     },
6630     
6631     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
6632     on : YAHOO.ext.util.Observable.prototype.on,
6633     addListener : YAHOO.ext.util.Observable.prototype.addListener,
6634     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
6635     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
6636     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
6637     bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
6638     
6639     onClick : function(e){
6640         this.fireEvent('click', e);
6641         var target = e.getTarget();
6642         var row = this.getRowFromChild(target);
6643         var cell = this.getCellFromChild(target);
6644         var header = this.getHeaderFromChild(target);
6645         if(row){
6646             this.fireEvent('rowclick', this, row.rowIndex, e);
6647         }
6648         if(cell){
6649             this.fireEvent('cellclick', this, row.rowIndex, cell.columnIndex, e);
6650         }
6651         if(header){
6652             this.fireEvent('headerclick', this, header.columnIndex, e);
6653         }
6654     },
6655
6656     onContextMenu : function(e){
6657         var target = e.getTarget();
6658         var row = this.getRowFromChild(target);
6659         var header = this.getHeaderFromChild(target);
6660         if(row){
6661             this.fireEvent('rowcontextmenu', this, row.rowIndex, e);
6662         }
6663         if(header){
6664             this.fireEvent('headercontextmenu', this, header.columnIndex, e);
6665         }
6666         e.preventDefault();
6667     },
6668
6669     onDblClick : function(e){
6670         this.fireEvent('dblclick', e);
6671         var target = e.getTarget();
6672         var row = this.getRowFromChild(target);
6673         var cell = this.getCellFromChild(target);
6674         if(row){
6675             this.fireEvent('rowdblclick', this, row.rowIndex, e);
6676         }
6677         if(cell){
6678             this.fireEvent('celldblclick', this, row.rowIndex, cell.columnIndex, e);
6679         }
6680     },
6681     
6682     
6683     startEditing : function(rowIndex, colIndex){
6684         var row = this.rows[rowIndex];
6685         var cell = row.childNodes[colIndex];
6686         this.stopEditing();
6687         setTimeout(this.doEdit.createDelegate(this, [row, cell]), 10);
6688     },
6689         
6690     
6691     stopEditing : function(){
6692         if(this.activeEditor){
6693             this.activeEditor.stopEditing();
6694         }
6695     },
6696         
6697     
6698     doEdit : function(row, cell){
6699         if(!row || !cell) return;
6700         var cm = this.colModel;
6701         var dm = this.dataModel;
6702         var colIndex = cell.columnIndex;
6703         var rowIndex = row.rowIndex;
6704         if(cm.isCellEditable(colIndex, rowIndex)){
6705            var ed = cm.getCellEditor(colIndex, rowIndex);
6706            if(ed){
6707                if(this.activeEditor){
6708                    this.activeEditor.stopEditing();
6709                }
6710                this.fireEvent('beforeedit', this, rowIndex, colIndex);
6711                this.activeEditor = ed;
6712                this.editingCell = cell;
6713                this.view.ensureVisible(row, true);
6714                try{
6715                    cell.focus();
6716                }catch(e){}
6717                ed.init(this, this.el.dom.parentNode, this.setValueDelegate);
6718                var value = dm.getValueAt(rowIndex, cm.getDataIndex(colIndex));
6719                
6720                setTimeout(ed.startEditing.createDelegate(ed, [value, row, cell]), 1);
6721            }   
6722         }  
6723     },
6724     
6725     setCellValue : function(value, rowIndex, colIndex){
6726          this.dataModel.setValueAt(value, rowIndex, this.colModel.getDataIndex(colIndex));
6727          this.fireEvent('afteredit', this, rowIndex, colIndex);
6728     },
6729     
6730     
6731     cancelTextSelection : function(e){
6732         var target = e.getTarget();
6733         if(target && target != this.el.dom.parentNode && !this.allowTextSelectionPattern.test(target.tagName)){
6734             e.preventDefault();
6735         }
6736     },
6737     
6738     
6739     autoSize : function(){
6740         this.view.updateWrapHeight();
6741         this.view.adjustForScroll();
6742     },
6743     
6744     
6745     scrollTo : function(row){
6746         if(typeof row == 'number'){
6747             row = this.rows[row];
6748         }
6749         this.view.ensureVisible(row, true);
6750     },
6751     
6752     
6753     getEditingCell : function(){
6754         return this.editingCell;    
6755     },
6756     
6757     
6758     bindToField : function(fieldId){
6759         this.fieldId = fieldId;
6760         this.readField();
6761     },
6762     
6763     
6764     updateField : function(){
6765         if(this.fieldId){
6766             var field = YAHOO.util.Dom.get(this.fieldId);
6767             field.value = this.getSelectedRowIds().join(',');
6768         }
6769     },
6770     
6771     
6772     readField : function(){
6773         if(this.fieldId){
6774             var field = YAHOO.util.Dom.get(this.fieldId);
6775             var values = field.value.split(',');
6776             var rows = this.getRowsById(values);
6777             this.selModel.selectRows(rows, false);
6778         }
6779     },
6780         
6781         
6782     getRow : function(index){
6783         return this.rows[index];
6784     },
6785         
6786         
6787     getRowsById : function(id){
6788         var dm = this.dataModel;
6789         if(!(id instanceof Array)){
6790             for(var i = 0; i < this.rows.length; i++){
6791                 if(dm.getRowId(i) == id){
6792                     return this.rows[i];
6793                 }
6794             }
6795             return null;
6796         }
6797         var found = [];
6798         var re = "^(?:";
6799         for(var i = 0; i < id.length; i++){
6800             re += id[i];
6801             if(i != id.length-1) re += "|";
6802         }
6803         var regex = new RegExp(re + ")$");
6804         for(var i = 0; i < this.rows.length; i++){
6805             if(regex.test(dm.getRowId(i))){
6806                 found.push(this.rows[i]);
6807             }
6808         }
6809         return found;
6810     },
6811     
6812     
6813     getRowAfter : function(row){
6814         return this.getSibling('next', row);
6815     },
6816     
6817     
6818     getRowBefore : function(row){
6819         return this.getSibling('previous', row);
6820     },
6821     
6822     
6823     getCellAfter : function(cell, includeHidden){
6824         var next = this.getSibling('next', cell);
6825         if(next && !includeHidden && this.colModel.isHidden(next.columnIndex)){
6826             return this.getCellAfter(next);
6827         }
6828         return next;
6829     },
6830     
6831     
6832     getCellBefore : function(cell, includeHidden){
6833         var prev = this.getSibling('previous', cell);
6834         if(prev && !includeHidden && this.colModel.isHidden(prev.columnIndex)){
6835             return this.getCellBefore(prev);
6836         }
6837         return prev;
6838     },
6839     
6840     
6841     getLastCell : function(row, includeHidden){
6842         var cell = this.getElement('previous', row.lastChild);
6843         if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
6844             return this.getCellBefore(cell);
6845         }
6846         return cell;
6847     },
6848     
6849     
6850     getFirstCell : function(row, includeHidden){
6851         var cell = this.getElement('next', row.firstChild);
6852         if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
6853             return this.getCellAfter(cell);
6854         }
6855         return cell;
6856     },
6857     
6858     
6859     getSibling : function(type, node){
6860         if(!node) return null;
6861         type += 'Sibling';
6862         var n = node[type];
6863         while(n && n.nodeType != 1){
6864             n = n[type];
6865         }
6866         return n;
6867     },
6868     
6869     
6870     getElement : function(direction, node){
6871         if(!node || node.nodeType == 1) return node;
6872         else return this.getSibling(direction, node);
6873     },
6874     
6875     
6876     getElementFromChild : function(childEl, parentClass){
6877         if(!childEl || (YAHOO.util.Dom.hasClass(childEl, parentClass))){
6878                     return childEl;
6879             }
6880             var p = childEl.parentNode;
6881             var b = document.body;
6882             while(p && p != b){
6883             if(YAHOO.util.Dom.hasClass(p, parentClass)){
6884                 return p;
6885             }
6886             p = p.parentNode;
6887         }
6888             return null;
6889     },
6890     
6891     
6892     getRowFromChild : function(childEl){
6893         return this.getElementFromChild(childEl, 'ygrid-row');
6894     },
6895     
6896     
6897     getCellFromChild : function(childEl){
6898         return this.getElementFromChild(childEl, 'ygrid-col');
6899     },
6900     
6901     
6902     
6903      getHeaderFromChild : function(childEl){
6904         return this.getElementFromChild(childEl, 'ygrid-hd');
6905     },
6906     
6907     
6908     getSelectedRows : function(){
6909         return this.selModel.getSelectedRows();
6910     },
6911     
6912     
6913     getSelectedRow : function(){
6914         if(this.selModel.hasSelection()){
6915             return this.selModel.getSelectedRows()[0];
6916         }
6917         return null;
6918     },
6919     
6920     
6921     getSelectedRowIndexes : function(){
6922         var a = [];
6923         var rows = this.selModel.getSelectedRows();
6924         for(var i = 0; i < rows.length; i++) {
6925                 a[i] = rows[i].rowIndex;
6926         }
6927         return a;
6928     },
6929     
6930     
6931     getSelectedRowIndex : function(){
6932         if(this.selModel.hasSelection()){
6933            return this.selModel.getSelectedRows()[0].rowIndex;
6934         }
6935         return -1;
6936     },
6937     
6938     
6939     getSelectedRowId : function(){
6940         if(this.selModel.hasSelection()){
6941            return this.selModel.getSelectedRowIds()[0];
6942         }
6943         return null;
6944     },
6945     
6946     
6947     getSelectedRowIds : function(){
6948         return this.selModel.getSelectedRowIds();
6949     },
6950     
6951     
6952     clearSelections : function(){
6953         this.selModel.clearSelections();
6954     },
6955     
6956         
6957     
6958     selectAll : function(){
6959         this.selModel.selectAll();
6960     },
6961     
6962         
6963     
6964     getSelectionCount : function(){
6965         return this.selModel.getCount();
6966     },
6967     
6968     
6969     hasSelection : function(){
6970         return this.selModel.hasSelection();
6971     },
6972     
6973     
6974     getSelectionModel : function(){
6975         if(!this.selModel){
6976             this.selModel = new DefaultSelectionModel();
6977         }
6978         return this.selModel;
6979     },
6980     
6981     
6982     getDataModel : function(){
6983         return this.dataModel;
6984     },
6985     
6986     
6987     getColumnModel : function(){
6988         return this.colModel;
6989     },
6990     
6991     
6992     getView : function(){
6993         return this.view;
6994     },
6995     
6996     getDragDropText : function(){
6997         return this.ddText.replace('%0', this.selModel.getCount());
6998     }
6999 };
7000
7001 YAHOO.ext.grid.Grid.prototype.ddText = "%0 selected row(s)";
7002
7003
7004 if(YAHOO.util.DDProxy){
7005
7006 YAHOO.ext.grid.GridDD = function(grid, bwrap){
7007     this.grid = grid;
7008     var ddproxy = document.createElement('div');
7009     ddproxy.id = grid.container.id + '-ddproxy';
7010     ddproxy.className = 'ygrid-drag-proxy';
7011     document.body.insertBefore(ddproxy, document.body.firstChild);
7012     YAHOO.util.Dom.setStyle(ddproxy, 'opacity', .80);
7013     var ddicon = document.createElement('span');
7014     ddicon.className = 'ygrid-drop-icon ygrid-drop-nodrop';
7015     ddproxy.appendChild(ddicon);
7016     var ddtext = document.createElement('span');
7017     ddtext.className = 'ygrid-drag-text';
7018     ddtext.innerHTML = "&#160;";
7019     ddproxy.appendChild(ddtext);
7020     
7021     this.ddproxy = ddproxy;
7022     this.ddtext = ddtext;
7023     this.ddicon = ddicon;
7024     YAHOO.util.Event.on(bwrap, 'click', this.handleClick, this, true);
7025     YAHOO.ext.grid.GridDD.superclass.constructor.call(this, bwrap.id, 'GridDD', 
7026           {dragElId : ddproxy.id, resizeFrame: false});
7027           
7028     this.unlockDelegate = grid.selModel.unlock.createDelegate(grid.selModel);
7029 };
7030 YAHOO.extendX(YAHOO.ext.grid.GridDD, YAHOO.util.DDProxy);
7031
7032 YAHOO.ext.grid.GridDD.prototype.handleMouseDown = function(e){
7033     var row = this.grid.getRowFromChild(YAHOO.util.Event.getTarget(e));
7034     if(!row) return;
7035     if(this.grid.selModel.isSelected(row)){
7036         YAHOO.ext.grid.GridDD.superclass.handleMouseDown.call(this, e);
7037     }else {
7038         this.grid.selModel.unlock();
7039         YAHOO.ext.EventObject.setEvent(e);
7040         this.grid.selModel.rowClick(this.grid, row.rowIndex, YAHOO.ext.EventObject);
7041         YAHOO.ext.grid.GridDD.superclass.handleMouseDown.call(this, e);
7042         this.grid.selModel.lock();
7043     }
7044 };
7045
7046 YAHOO.ext.grid.GridDD.prototype.handleClick = function(e){
7047     if(this.grid.selModel.isLocked()){
7048          setTimeout(this.unlockDelegate, 1);
7049          YAHOO.util.Event.stopEvent(e);
7050     }
7051 };
7052
7053
7054 YAHOO.ext.grid.GridDD.prototype.setDropStatus = function(dropStatus){
7055     if(dropStatus === true){
7056         YAHOO.util.Dom.replaceClass(this.ddicon, 'ygrid-drop-nodrop', 'ygrid-drop-ok');
7057     }else{
7058         YAHOO.util.Dom.replaceClass(this.ddicon, 'ygrid-drop-ok', 'ygrid-drop-nodrop');
7059     }
7060 };
7061
7062 YAHOO.ext.grid.GridDD.prototype.startDrag = function(e){
7063     this.ddtext.innerHTML = this.grid.getDragDropText();
7064     this.setDropStatus(false);
7065     this.grid.selModel.lock();
7066     this.grid.fireEvent('startdrag', this.grid, this, e);
7067 };
7068        
7069 YAHOO.ext.grid.GridDD.prototype.endDrag = function(e){
7070     YAHOO.util.Dom.setStyle(this.ddproxy, 'visibility', 'hidden');
7071     this.grid.fireEvent('enddrag', this.grid, this, e);
7072 };
7073
7074 YAHOO.ext.grid.GridDD.prototype.autoOffset = function(iPageX, iPageY) {
7075     this.setDelta(-12, -20);
7076 };
7077
7078 YAHOO.ext.grid.GridDD.prototype.onDragEnter = function(e, id) {
7079     this.setDropStatus(true);
7080     this.grid.fireEvent('dragenter', this.grid, this, id, e);
7081 };
7082
7083 YAHOO.ext.grid.GridDD.prototype.onDragDrop = function(e, id) {
7084     this.grid.fireEvent('dragdrop', this.grid, this, id, e);
7085 };
7086
7087 YAHOO.ext.grid.GridDD.prototype.onDragOver = function(e, id) {
7088     this.grid.fireEvent('dragover', this.grid, this, id, e);
7089 };
7090
7091 YAHOO.ext.grid.GridDD.prototype.onDragOut = function(e, id) {
7092     this.setDropStatus(false);
7093     this.grid.fireEvent('dragout', this.grid, this, id, e);
7094 };
7095 };
7096
7097 YAHOO.ext.grid.GridView = function(){
7098         this.grid = null;
7099         this.lastFocusedRow = null;
7100         this.onScroll = new YAHOO.util.CustomEvent('onscroll');
7101         this.adjustScrollTask = new YAHOO.ext.util.DelayedTask(this._adjustForScroll, this);
7102         this.ensureVisibleTask = new YAHOO.ext.util.DelayedTask();
7103 };
7104
7105 YAHOO.ext.grid.GridView.prototype = {
7106         init: function(grid){
7107                 this.grid = grid;
7108         },
7109         
7110         fireScroll: function(scrollLeft, scrollTop){
7111                 this.onScroll.fireDirect(this.grid, scrollLeft, scrollTop);
7112         },
7113         
7114         
7115         getColumnRenderers : function(){
7116         var renderers = [];
7117         var cm = this.grid.colModel;
7118         var colCount = cm.getColumnCount();
7119         for(var i = 0; i < colCount; i++){
7120             renderers.push(cm.getRenderer(i));
7121         }
7122         return renderers;
7123     },
7124     
7125     buildIndexMap : function(){
7126         var colToData = {};
7127         var dataToCol = {};
7128         var cm = this.grid.colModel;
7129         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
7130             var di = cm.getDataIndex(i);
7131             colToData[i] = di;
7132             dataToCol[di] = i;
7133         }
7134         return {'colToData': colToData, 'dataToCol': dataToCol};
7135     },
7136     
7137     getDataIndexes : function(){
7138         if(!this.indexMap){
7139             this.indexMap = this.buildIndexMap();
7140         }
7141         return this.indexMap.colToData;
7142     },
7143     
7144     getColumnIndexByDataIndex : function(dataIndex){
7145         if(!this.indexMap){
7146             this.indexMap = this.buildIndexMap();
7147         }
7148         return this.indexMap.dataToCol[dataIndex];
7149     },
7150     
7151     updateHeaders : function(){
7152         var colModel = this.grid.colModel;
7153         var hcells = this.headers;
7154         var colCount = colModel.getColumnCount();
7155         for(var i = 0; i < colCount; i++){
7156             hcells[i].textNode.innerHTML = colModel.getColumnHeader(i);
7157         }
7158     },
7159     
7160     adjustForScroll : function(disableDelay){
7161         if(!disableDelay){
7162             this.adjustScrollTask.delay(50);
7163         }else{
7164             this._adjustForScroll();
7165         }
7166     },
7167     
7168     
7169      getCellAtPoint : function(x, y){
7170         var colIndex = null;        
7171         var rowIndex = null;
7172         
7173         
7174         var xy = YAHOO.util.Dom.getXY(this.wrap);
7175         x = (x - xy[0]) + this.wrap.scrollLeft;
7176         y = (y - xy[1]) + this.wrap.scrollTop;
7177         
7178         var colModel = this.grid.colModel;
7179         var pos = 0;
7180         var colCount = colModel.getColumnCount();
7181         for(var i = 0; i < colCount; i++){
7182             if(colModel.isHidden(i)) continue;
7183             var width = colModel.getColumnWidth(i);
7184             if(x >= pos && x < pos+width){
7185                 colIndex = i;
7186                 break;
7187             }
7188             pos += width;
7189         }
7190         if(colIndex != null){
7191             rowIndex = (y == 0 ? 0 : Math.floor(y / this.getRowHeight()));
7192             if(rowIndex >= this.grid.dataModel.getRowCount()){
7193                 return null;
7194             }
7195             return [colIndex, rowIndex];
7196         }
7197         return null;
7198     },
7199     
7200     
7201     _adjustForScroll : function(){
7202         this.forceScrollUpdate();
7203         if(this.scrollbarMode == YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP){
7204             var adjustment = 0;
7205             if(this.wrap.clientWidth && this.wrap.clientWidth !== 0){
7206                 adjustment = this.wrap.offsetWidth - this.wrap.clientWidth;
7207             }
7208             this.hwrap.setWidth(this.wrap.offsetWidth-adjustment);
7209         }else{
7210             this.hwrap.setWidth(this.wrap.offsetWidth);
7211         }
7212         this.bwrap.setWidth(Math.max(this.grid.colModel.getTotalWidth(), this.wrap.clientWidth));
7213     },
7214
7215     
7216      focusRow : function(row){
7217         if(typeof row == 'number'){
7218             row = this.getBodyTable().childNodes[row];
7219         }
7220         if(!row) return;
7221         var left = this.wrap.scrollLeft;
7222         try{ 
7223             row.childNodes.item(0).hideFocus = true;
7224                 row.childNodes.item(0).focus();
7225         }catch(e){}
7226         this.ensureVisible(row);
7227         this.wrap.scrollLeft = left;
7228         this.handleScroll();
7229         this.lastFocusedRow = row;
7230     },
7231
7232     
7233      ensureVisible : function(row, disableDelay){
7234         if(!disableDelay){
7235             this.ensureVisibleTask.delay(50, this._ensureVisible, this, [row]);
7236         }else{
7237             this._ensureVisible(row);
7238         }
7239     },
7240
7241     
7242     _ensureVisible : function(row){
7243         if(typeof row == 'number'){
7244             row = this.getBodyTable().childNodes[row];
7245         }
7246         if(!row) return;
7247         var left = this.wrap.scrollLeft;
7248         var rowTop = parseInt(row.offsetTop, 10); 
7249         var rowBottom = rowTop + row.offsetHeight;
7250         var clientTop = parseInt(this.wrap.scrollTop, 10); 
7251         var clientBottom = clientTop + this.wrap.clientHeight;
7252         if(rowTop < clientTop){
7253                 this.wrap.scrollTop = rowTop;
7254         }else if(rowBottom > clientBottom){
7255             this.wrap.scrollTop = rowBottom-this.wrap.clientHeight;
7256         }
7257         this.wrap.scrollLeft = left;
7258         this.handleScroll();
7259     },
7260     
7261     updateColumns : function(){
7262         this.grid.stopEditing();
7263         var colModel = this.grid.colModel;
7264         var hcols = this.headers;
7265         var colCount = colModel.getColumnCount();
7266         var pos = 0;
7267         var totalWidth = colModel.getTotalWidth();
7268         for(var i = 0; i < colCount; i++){
7269             if(colModel.isHidden(i)) continue;
7270             var width = colModel.getColumnWidth(i);
7271             hcols[i].style.width = width + 'px';
7272             hcols[i].style.left = pos + 'px';
7273             hcols[i].split.style.left = (pos+width-3) + 'px';
7274             this.setCSSWidth(i, width, pos);
7275             pos += width;
7276         }
7277         this.lastWidth = totalWidth;
7278         if(this.grid.autoWidth){
7279             this.grid.container.setWidth(totalWidth+this.grid.container.getBorderWidth('lr'));
7280             this.grid.autoSize();
7281         }
7282         this.bwrap.setWidth(Math.max(totalWidth, this.wrap.clientWidth));
7283         if(!YAHOO.ext.util.Browser.isIE){ 
7284                 this.wrap.scrollLeft = this.hwrap.dom.scrollLeft;
7285         }
7286         this.syncScroll();
7287         this.forceScrollUpdate();
7288         if(this.grid.autoHeight){
7289             this.autoHeight();
7290             this.updateWrapHeight();
7291         }
7292     },
7293     
7294     setCSSWidth : function(colIndex, width, pos){
7295         var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
7296         YAHOO.ext.util.CSS.updateRule(selector, 'width', width + 'px');
7297         if(typeof pos == 'number'){
7298             YAHOO.ext.util.CSS.updateRule(selector, 'left', pos + 'px');
7299         }
7300     },
7301     
7302     
7303      setCSSStyle : function(colIndex, name, value){
7304         var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
7305         YAHOO.ext.util.CSS.updateRule(selector, name, value);
7306     },
7307     
7308     handleHiddenChange : function(colModel, colIndex, hidden){
7309         if(hidden){
7310             this.hideColumn(colIndex);
7311         }else{
7312             this.unhideColumn(colIndex);
7313         }
7314         this.updateColumns();
7315     },
7316     
7317     hideColumn : function(colIndex){
7318         var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
7319         YAHOO.ext.util.CSS.updateRule(selector, 'position', 'absolute');
7320         YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'hidden');
7321         
7322         this.headers[colIndex].style.display = 'none';
7323         this.headers[colIndex].split.style.display = 'none';
7324     },
7325     
7326     unhideColumn : function(colIndex){
7327         var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
7328         YAHOO.ext.util.CSS.updateRule(selector, 'position', '');
7329         YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'visible');
7330         
7331         this.headers[colIndex].style.display = '';
7332         this.headers[colIndex].split.style.display = '';
7333     },
7334     
7335     getBodyTable : function(){
7336         return this.bwrap.dom;
7337     },
7338     
7339     updateRowIndexes : function(firstRow, lastRow){
7340         var stripeRows = this.grid.stripeRows;
7341         var bt = this.getBodyTable();
7342         var nodes = bt.childNodes;
7343         firstRow = firstRow || 0;
7344         lastRow = lastRow || nodes.length-1;
7345         var re = /^(?:ygrid-row ygrid-row-alt|ygrid-row)/;
7346         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
7347             var node = nodes[rowIndex];
7348             if(stripeRows && (rowIndex+1) % 2 == 0){
7349                         node.className = node.className.replace(re, 'ygrid-row ygrid-row-alt');
7350                 }else{
7351                         node.className = node.className.replace(re, 'ygrid-row');
7352                 }
7353             node.rowIndex = rowIndex;
7354             nodes[rowIndex].style.top = (rowIndex * this.rowHeight) + 'px';
7355         }
7356     },
7357
7358     insertRows : function(dataModel, firstRow, lastRow){
7359         this.updateBodyHeight();
7360         this.adjustForScroll(true);
7361         var renderers = this.getColumnRenderers();
7362         var dindexes = this.getDataIndexes();
7363         var colCount = this.grid.colModel.getColumnCount();
7364         var beforeRow = null;
7365         var bt = this.getBodyTable();
7366         if(firstRow < bt.childNodes.length){
7367             beforeRow = bt.childNodes[firstRow];
7368         }
7369         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
7370             var row = document.createElement('span');
7371             row.className = 'ygrid-row';
7372             row.style.top = (rowIndex * this.rowHeight) + 'px';
7373             this.renderRow(dataModel, row, rowIndex, colCount, renderers, dindexes);
7374             if(beforeRow){
7375                 bt.insertBefore(row, beforeRow);
7376             }else{
7377                 bt.appendChild(row);
7378             }
7379         }
7380         this.updateRowIndexes(firstRow);
7381         this.adjustForScroll(true);
7382     },
7383     
7384     renderRow : function(dataModel, row, rowIndex, colCount, renderers, dindexes){
7385         for(var colIndex = 0; colIndex < colCount; colIndex++){
7386             var td = document.createElement('span');
7387             td.className = 'ygrid-col ygrid-col-' + colIndex + (colIndex == colCount-1 ? ' ygrid-col-last' : '');
7388             td.columnIndex = colIndex;
7389             td.tabIndex = 0;
7390             var span = document.createElement('span');
7391             span.className = 'ygrid-cell-text';
7392             td.appendChild(span);
7393             var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td);
7394             if(typeof val == 'undefined' || val === '') val = '&#160;';
7395             span.innerHTML = val;
7396             row.appendChild(td);
7397         }
7398     },
7399     
7400     deleteRows : function(dataModel, firstRow, lastRow){
7401         this.updateBodyHeight();
7402         
7403         this.grid.selModel.deselectRange(firstRow, lastRow);
7404         var bt = this.getBodyTable();
7405         var rows = []; 
7406         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
7407             rows.push(bt.childNodes[rowIndex]);
7408         }
7409         for(var i = 0; i < rows.length; i++){
7410             bt.removeChild(rows[i]);
7411             rows[i] = null;
7412         }
7413         rows = null;
7414         this.updateRowIndexes(firstRow);
7415         this.adjustForScroll();
7416     },
7417     
7418     updateRows : function(dataModel, firstRow, lastRow){
7419         var bt = this.getBodyTable();
7420         var dindexes = this.getDataIndexes();
7421         var renderers = this.getColumnRenderers();
7422         var colCount = this.grid.colModel.getColumnCount();
7423         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
7424             var row = bt.rows[rowIndex];
7425             var cells = row.childNodes;
7426             for(var colIndex = 0; colIndex < colCount; colIndex++){
7427                 var td = cells[colIndex];
7428                 var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td);
7429                 if(typeof val == 'undefined' || val === '') val = '&#160;';
7430                 td.firstChild.innerHTML = val;
7431             }
7432         }
7433     },
7434     
7435     handleSort : function(dataModel, sortColumnIndex, sortDir, noRefresh){
7436         this.grid.selModel.syncSelectionsToIds();
7437         if(!noRefresh){
7438            this.updateRows(dataModel, 0, dataModel.getRowCount()-1);
7439         }
7440         this.updateHeaderSortState();
7441         if(this.lastFocusedRow){
7442             this.focusRow(this.lastFocusedRow);
7443         }
7444     },
7445     
7446     syncScroll : function(){
7447         this.hwrap.dom.scrollLeft = this.wrap.scrollLeft;
7448     },
7449     
7450     handleScroll : function(){
7451         this.syncScroll();
7452         this.fireScroll(this.wrap.scrollLeft, this.wrap.scrollTop);
7453         this.grid.fireEvent('bodyscroll', this.wrap.scrollLeft, this.wrap.scrollTop);
7454     },
7455     
7456     getRowHeight : function(){
7457         if(!this.rowHeight){
7458             var rule = YAHOO.ext.util.CSS.getRule(["#" + this.grid.id + " .ygrid-row", ".ygrid-row"]);
7459                 if(rule && rule.style.height){
7460                     this.rowHeight = parseInt(rule.style.height, 10);
7461                 }else{
7462                     this.rowHeight = 21;
7463                 }
7464         }
7465         return this.rowHeight;
7466     },
7467     
7468     renderRows : function(dataModel){
7469         this.grid.stopEditing();
7470         if(this.grid.selModel){
7471             this.grid.selModel.clearSelections();
7472         }
7473         var bt = this.getBodyTable();
7474         bt.innerHTML = '';
7475         this.rowHeight = this.getRowHeight();
7476         this.insertRows(dataModel, 0, dataModel.getRowCount()-1);
7477     },
7478     
7479     updateCell : function(dataModel, rowIndex, dataIndex){
7480         var colIndex = this.getColumnIndexByDataIndex(dataIndex);
7481         if(typeof colIndex == 'undefined'){ 
7482             return;
7483         }
7484         var bt = this.getBodyTable();
7485         var row = bt.childNodes[rowIndex];
7486         var cell = row.childNodes[colIndex];
7487         var renderer = this.grid.colModel.getRenderer(colIndex);
7488         var val = renderer(dataModel.getValueAt(rowIndex, dataIndex), rowIndex, colIndex, cell);
7489         if(typeof val == 'undefined' || val === '') val = '&#160;';
7490         cell.firstChild.innerHTML = val;
7491     },
7492     
7493     calcColumnWidth : function(colIndex, maxRowsToMeasure){
7494         var maxWidth = 0;
7495         var bt = this.getBodyTable();
7496         var rows = bt.childNodes;
7497         var stopIndex = Math.min(maxRowsToMeasure || rows.length, rows.length);
7498         if(this.grid.autoSizeHeaders){
7499             var h = this.headers[colIndex];
7500             var curWidth = h.style.width;
7501             h.style.width = this.grid.minColumnWidth+'px';
7502             maxWidth = Math.max(maxWidth, h.scrollWidth);
7503             h.style.width = curWidth;
7504         }
7505         for(var i = 0; i < stopIndex; i++){
7506             var cell = rows[i].childNodes[colIndex].firstChild;
7507             maxWidth = Math.max(maxWidth, cell.scrollWidth);
7508         }
7509         return maxWidth +  5;
7510     },
7511     
7512     
7513      autoSizeColumn : function(colIndex, forceMinSize){
7514         if(forceMinSize){
7515            this.setCSSWidth(colIndex, this.grid.minColumnWidth);
7516         }
7517         var newWidth = this.calcColumnWidth(colIndex);
7518         this.grid.colModel.setColumnWidth(colIndex,
7519             Math.max(this.grid.minColumnWidth, newWidth));
7520         this.grid.fireEvent('columnresize', colIndex, newWidth);
7521     },
7522     
7523     
7524      autoSizeColumns : function(){
7525         var colModel = this.grid.colModel;
7526         var colCount = colModel.getColumnCount();
7527         var wrap = this.wrap;
7528         for(var i = 0; i < colCount; i++){
7529             this.setCSSWidth(i, this.grid.minColumnWidth);
7530             colModel.setColumnWidth(i, this.calcColumnWidth(i, this.grid.maxRowsToMeasure), true);
7531         }
7532         if(colModel.getTotalWidth() < wrap.clientWidth){
7533             var diff = Math.floor((wrap.clientWidth - colModel.getTotalWidth()) / colCount);
7534             for(var i = 0; i < colCount; i++){
7535                 colModel.setColumnWidth(i, colModel.getColumnWidth(i) + diff, true);
7536             }
7537         }
7538         this.updateColumns();  
7539     },
7540     
7541     
7542     fitColumns : function(){
7543         var cm = this.grid.colModel;
7544         var colCount = cm.getColumnCount();
7545         var cols = [];
7546         var width = 0;
7547         var i, w;
7548         for (i = 0; i < colCount; i++){
7549             if(!cm.isHidden(i) && !cm.isFixed(i)){
7550                 w = cm.getColumnWidth(i);
7551                 cols.push(i);
7552                 cols.push(w);
7553                 width += w;
7554             }
7555         }
7556         var frac = (this.wrap.clientWidth - cm.getTotalWidth())/width;
7557         while (cols.length){
7558             w = cols.pop();
7559             i = cols.pop();
7560             cm.setColumnWidth(i, Math.floor(w + w*frac), true);
7561         }
7562         this.updateColumns();
7563     }, 
7564     
7565     onWindowResize : function(){
7566         if(this.grid.monitorWindowResize){
7567             this.adjustForScroll();
7568             this.updateWrapHeight();
7569             this.adjustForScroll();
7570         }  
7571     },
7572     
7573     updateWrapHeight : function(){
7574         this.grid.container.beginMeasure();
7575         this.autoHeight();
7576         var box = this.grid.container.getSize(true);
7577         this.wrapEl.setHeight(box.height-this.footerHeight-parseInt(this.wrap.offsetTop, 10));
7578         this.pwrap.setSize(box.width, box.height);
7579         this.grid.container.endMeasure();
7580     },
7581     
7582     forceScrollUpdate : function(){
7583         var wrap = this.wrapEl;
7584         wrap.setWidth(wrap.getWidth(true));
7585         setTimeout(function(){ 
7586             wrap.setWidth('');
7587         }, 1);
7588     },
7589     
7590     updateHeaderSortState : function(){
7591         var state = this.grid.dataModel.getSortState();
7592         if(!state || typeof state.column == 'undefined') return;
7593         var sortColumn = this.getColumnIndexByDataIndex(state.column);
7594         var sortDir = state.direction;
7595         for(var i = 0, len = this.headers.length; i < len; i++){
7596             var h = this.headers[i];
7597             if(i != sortColumn){
7598                 h.sortDesc.style.display = 'none';
7599                 h.sortAsc.style.display = 'none';
7600             }else{
7601                 h.sortDesc.style.display = sortDir == 'DESC' ? 'block' : 'none';
7602                 h.sortAsc.style.display = sortDir == 'ASC' ? 'block' : 'none';
7603             }
7604         }
7605     },
7606
7607     unplugDataModel : function(dm){
7608         dm.removeListener('cellupdated', this.updateCell, this);
7609         dm.removeListener('datachanged', this.renderRows, this);
7610         dm.removeListener('rowsdeleted', this.deleteRows, this);
7611         dm.removeListener('rowsinserted', this.insertRows, this);
7612         dm.removeListener('rowsupdated', this.updateRows, this);
7613         dm.removeListener('rowssorted', this.handleSort, this);
7614     },
7615     
7616     plugDataModel : function(dm){
7617         dm.on('cellupdated', this.updateCell, this, true);
7618         dm.on('datachanged', this.renderRows, this, true);
7619         dm.on('rowsdeleted', this.deleteRows, this, true);
7620         dm.on('rowsinserted', this.insertRows, this, true);
7621         dm.on('rowsupdated', this.updateRows, this, true);
7622         dm.on('rowssorted', this.handleSort, this, true);
7623     },
7624     
7625     destroy : function(){
7626         this.unplugDataModel(this.grid.dataModel);
7627         var sp = this.splitters;
7628         if(sp){
7629             for(var i in sp){
7630                 if(sp[i] && typeof sp[i] != 'function'){
7631                     sp[i].destroy(true);
7632                 }
7633             }
7634         }
7635     },
7636     
7637     render : function(){
7638         var grid = this.grid;
7639         var container = grid.container.dom;
7640         var dataModel = grid.dataModel;
7641         this.plugDataModel(dataModel);
7642     
7643         var colModel = grid.colModel;
7644         colModel.onWidthChange.subscribe(this.updateColumns, this, true);
7645         colModel.onHeaderChange.subscribe(this.updateHeaders, this, true);
7646         colModel.onHiddenChange.subscribe(this.handleHiddenChange, this, true);
7647         
7648         if(grid.monitorWindowResize === true){
7649             YAHOO.ext.EventManager.onWindowResize(this.onWindowResize, this, true);
7650         }
7651         var autoSizeDelegate = this.autoSizeColumn.createDelegate(this);
7652         
7653         var colCount = colModel.getColumnCount();
7654         
7655         var dh = YAHOO.ext.DomHelper;
7656         this.pwrap = dh.append(container, 
7657             {tag: 'div', cls: 'ygrid-positioner', 
7658             style: 'position:relative;width:100%;height:100%;left:0;top:0;overflow:hidden;'}, true);
7659         var pos = this.pwrap.dom;
7660         
7661         
7662         var wrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap'});
7663         this.wrap = wrap;
7664         this.wrapEl = getEl(wrap, true);
7665         YAHOO.ext.EventManager.on(wrap, 'scroll', this.handleScroll, this, true);
7666         
7667         var hwrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap-headers'});
7668         this.hwrap = getEl(hwrap, true);
7669         
7670         var bwrap = dh.append(wrap, {tag: 'div', cls: 'ygrid-wrap-body', id: container.id + '-body'});
7671         this.bwrap = getEl(bwrap, true);
7672         this.bwrap.setWidth(colModel.getTotalWidth());
7673         bwrap.rows = bwrap.childNodes;
7674         
7675         this.footerHeight = 0;
7676         var foot = this.appendFooter(this.pwrap.dom);
7677         if(foot){
7678             this.footer = getEl(foot, true);
7679             this.footerHeight = this.footer.getHeight();
7680         }
7681         this.updateWrapHeight();
7682         
7683         var hrow = dh.append(hwrap, {tag: 'span', cls: 'ygrid-hrow'});
7684         this.hrow = hrow;
7685         
7686         if(!YAHOO.ext.util.Browser.isGecko){
7687             
7688             var iframe = document.createElement('iframe');
7689             iframe.className = 'ygrid-hrow-frame';
7690             iframe.frameBorder = 0;
7691             iframe.src = YAHOO.ext.SSL_SECURE_URL;
7692             hwrap.appendChild(iframe);
7693         }
7694         this.headerCtrl = new YAHOO.ext.grid.HeaderController(this.grid);
7695         this.headers = [];
7696         this.cols = [];
7697         this.splitters = [];
7698         
7699         var htemplate = dh.createTemplate({
7700            tag: 'span', cls: 'ygrid-hd ygrid-header-{0}', children: [{
7701                 tag: 'span',
7702                 cls: 'ygrid-hd-body',
7703                 html: '<table border="0" cellpadding="0" cellspacing="0" title="{2}">' +
7704                       '<tbody><tr><td><span>{1}</span></td>' +
7705                       '<td><span class="sort-desc"></span><span class="sort-asc"></span></td>' +
7706                       '</tr></tbody></table>'
7707            }]
7708         });
7709         htemplate.compile();
7710         for(var i = 0; i < colCount; i++){
7711             var hd = htemplate.append(hrow, [i, colModel.getColumnHeader(i), colModel.getColumnTooltip(i) || '']);
7712             var spans = hd.getElementsByTagName('span');
7713             hd.textNode = spans[1];
7714             hd.sortDesc = spans[2];
7715             hd.sortAsc = spans[3];
7716             hd.columnIndex = i;
7717             this.headers.push(hd);
7718             if(colModel.isSortable(i)){
7719                 this.headerCtrl.register(hd);
7720             }
7721             var split = dh.append(hrow, {tag: 'span', cls: 'ygrid-hd-split'});
7722             hd.split = split;
7723                 
7724                 if(colModel.isResizable(i) && !colModel.isFixed(i)){
7725                 YAHOO.util.Event.on(split, 'dblclick', autoSizeDelegate.createCallback(i+0, true));
7726                 var sb = new YAHOO.ext.SplitBar(split, hd, null, YAHOO.ext.SplitBar.LEFT);
7727                 sb.columnIndex = i;
7728                 sb.minSize = grid.minColumnWidth;
7729                 sb.onMoved.subscribe(this.onColumnSplitterMoved, this, true);
7730                 YAHOO.util.Dom.addClass(sb.proxy, 'ygrid-column-sizer');
7731                 YAHOO.util.Dom.setStyle(sb.proxy, 'background-color', '');
7732                 sb.dd._resizeProxy = function(){
7733                     var el = this.getDragEl();
7734                     YAHOO.util.Dom.setStyle(el, 'height', (hwrap.clientHeight+wrap.clientHeight-2) +'px');
7735                 };
7736                 this.splitters[i] = sb;
7737                 }else{
7738                     split.style.cursor = 'default';
7739                 }
7740         }
7741        if(grid.autoSizeColumns){
7742             this.renderRows(dataModel);
7743             this.autoSizeColumns();
7744         }else{
7745             this.updateColumns();
7746             this.renderRows(dataModel);
7747         }
7748         
7749         for(var i = 0; i < colCount; i++){
7750             if(colModel.isHidden(i)){
7751                 this.hideColumn(i);
7752             }
7753         }
7754         this.updateHeaderSortState();
7755         return this.bwrap;
7756     },
7757     
7758     onColumnSplitterMoved : function(splitter, newSize){
7759         this.grid.colModel.setColumnWidth(splitter.columnIndex, newSize);
7760         this.grid.fireEvent('columnresize', splitter.columnIndex, newSize);
7761     },
7762     
7763     appendFooter : function(parentEl){
7764         return null;  
7765     },
7766     
7767     autoHeight : function(){
7768         if(this.grid.autoHeight){
7769             var h = this.getBodyHeight();
7770             var c = this.grid.container;
7771             var total = h + (parseInt(this.wrap.offsetTop, 10)||0) + 
7772                     this.footerHeight + c.getBorderWidth('tb') + c.getPadding('tb')
7773                     + (this.wrap.offsetHeight - this.wrap.clientHeight);
7774             c.setHeight(total);
7775             
7776         }
7777     },
7778     
7779     getBodyHeight : function(){
7780         return this.grid.dataModel.getRowCount() * this.getRowHeight();;
7781     },
7782     
7783     updateBodyHeight : function(){
7784         this.getBodyTable().style.height = this.getBodyHeight() + 'px';
7785         if(this.grid.autoHeight){
7786             this.autoHeight();
7787             this.updateWrapHeight();
7788         }
7789     }
7790 };
7791 YAHOO.ext.grid.GridView.SCROLLBARS_UNDER = 0;
7792 YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP = 1;
7793 YAHOO.ext.grid.GridView.prototype.scrollbarMode = YAHOO.ext.grid.GridView.SCROLLBARS_UNDER;
7794
7795 YAHOO.ext.grid.GridView.prototype.fitColumnsToContainer = YAHOO.ext.grid.GridView.prototype.fitColumns;
7796
7797 YAHOO.ext.grid.HeaderController = function(grid){
7798         this.grid = grid;
7799         this.headers = [];
7800 };
7801
7802 YAHOO.ext.grid.HeaderController.prototype = {
7803         register : function(header){
7804                 this.headers.push(header);
7805                 YAHOO.ext.EventManager.on(header, 'selectstart', this.cancelTextSelection, this, true);
7806         YAHOO.ext.EventManager.on(header, 'mousedown', this.cancelTextSelection, this, true);
7807         YAHOO.ext.EventManager.on(header, 'mouseover', this.headerOver, this, true);
7808         YAHOO.ext.EventManager.on(header, 'mouseout', this.headerOut, this, true);
7809         YAHOO.ext.EventManager.on(header, 'click', this.headerClick, this, true);
7810         },
7811         
7812         headerClick : function(e){
7813             var grid = this.grid, cm = grid.colModel, dm = grid.dataModel;
7814             grid.stopEditing();
7815         var header = grid.getHeaderFromChild(e.getTarget());
7816         var state = dm.getSortState();
7817         var direction = header.sortDir || 'ASC';
7818         if(typeof state.column != 'undefined' && 
7819                  grid.getView().getColumnIndexByDataIndex(state.column) == header.columnIndex){
7820             direction = (state.direction == 'ASC' ? 'DESC' : 'ASC');
7821         }
7822         header.sortDir = direction;
7823         dm.sort(cm, cm.getDataIndex(header.columnIndex), direction);
7824     },
7825     
7826     headerOver : function(e){
7827         var header = this.grid.getHeaderFromChild(e.getTarget());
7828         YAHOO.util.Dom.addClass(header, 'ygrid-hd-over');
7829         
7830     },
7831     
7832     headerOut : function(e){
7833         var header = this.grid.getHeaderFromChild(e.getTarget());
7834         YAHOO.util.Dom.removeClass(header, 'ygrid-hd-over');
7835         
7836     },
7837     
7838     cancelTextSelection : function(e){
7839         e.preventDefault();
7840     }
7841 };
7842
7843 YAHOO.ext.grid.PagedGridView = function(){
7844     YAHOO.ext.grid.PagedGridView.superclass.constructor.call(this);
7845     this.cursor = 1;
7846 };
7847
7848 YAHOO.extendX(YAHOO.ext.grid.PagedGridView, YAHOO.ext.grid.GridView, {
7849     appendFooter : function(parentEl){
7850         var fwrap = document.createElement('div');
7851         fwrap.className = 'ygrid-wrap-footer';
7852         var fbody = document.createElement('span');
7853         fbody.className = 'ygrid-footer';
7854         fwrap.appendChild(fbody);
7855         parentEl.appendChild(fwrap);
7856         this.createPagingToolbar(fbody);
7857         return fwrap;
7858     },
7859
7860     createPagingToolbar : function(container){
7861         var tb = new YAHOO.ext.Toolbar(container);
7862         this.pageToolbar = tb;
7863         this.first = tb.addButton({
7864             tooltip: this.firstText, 
7865             className: 'ygrid-page-first',
7866             disabled: true,
7867             click: this.onClick.createDelegate(this, ['first'])
7868         });
7869         this.prev = tb.addButton({
7870             tooltip: this.prevText, 
7871             className: 'ygrid-page-prev', 
7872             disabled: true,
7873             click: this.onClick.createDelegate(this, ['prev'])
7874         });
7875         tb.addSeparator();
7876         tb.add(this.beforePageText);
7877         var pageBox = document.createElement('input');
7878         pageBox.type = 'text';
7879         pageBox.size = 3;
7880         pageBox.value = '1';
7881         pageBox.className = 'ygrid-page-number';
7882         tb.add(pageBox);
7883         this.field = getEl(pageBox, true);
7884         this.field.mon('keydown', this.onEnter, this, true);
7885         this.field.on('focus', function(){pageBox.select();});
7886         this.afterTextEl = tb.addText(this.afterPageText.replace('%0', '1'));
7887         this.field.setHeight(18);
7888         tb.addSeparator();
7889         this.next = tb.addButton({
7890             tooltip: this.nextText, 
7891             className: 'ygrid-page-next', 
7892             disabled: true,
7893             click: this.onClick.createDelegate(this, ['next'])
7894         });
7895         this.last = tb.addButton({
7896             tooltip: this.lastText, 
7897             className: 'ygrid-page-last', 
7898             disabled: true,
7899             click: this.onClick.createDelegate(this, ['last'])
7900         });
7901         tb.addSeparator();
7902         this.loading = tb.addButton({
7903             tooltip: this.refreshText, 
7904             className: 'ygrid-loading',
7905             disabled: true,
7906             click: this.onClick.createDelegate(this, ['refresh'])
7907         });
7908         this.onPageLoaded(1, this.grid.dataModel.getTotalPages());
7909     },
7910     
7911     
7912     getPageToolbar : function(){
7913         return this.pageToolbar;  
7914     },
7915     
7916     onPageLoaded : function(pageNum, totalPages){
7917         this.cursor = pageNum;
7918         this.lastPage = totalPages;
7919         this.afterTextEl.innerHTML = this.afterPageText.replace('%0', totalPages);
7920         this.field.dom.value = pageNum;
7921         this.first.setDisabled(pageNum == 1);
7922         this.prev.setDisabled(pageNum == 1);
7923         this.next.setDisabled(pageNum == totalPages);
7924         this.last.setDisabled(pageNum == totalPages);
7925         this.loading.enable();
7926     },
7927     
7928     onLoadError : function(){
7929         this.loading.enable();
7930     },
7931     
7932     onEnter : function(e){
7933         if(e.browserEvent.keyCode == e.RETURN){
7934             var v = this.field.dom.value;
7935             if(!v){
7936                 this.field.dom.value = this.cursor;
7937                 return;
7938             }
7939             var pageNum = parseInt(v, 10);
7940             if(isNaN(pageNum)){
7941                 this.field.dom.value = this.cursor;
7942                 return;
7943             }
7944             pageNum = Math.min(Math.max(1, pageNum), this.lastPage);
7945             this.grid.dataModel.loadPage(pageNum);
7946             e.stopEvent();
7947         }
7948     },
7949     
7950     beforeLoad : function(){
7951         this.grid.stopEditing();
7952         if(this.loading){
7953             this.loading.disable();
7954         }  
7955     },
7956     
7957     onClick : function(which){
7958         switch(which){
7959             case 'first':
7960                 this.grid.dataModel.loadPage(1);
7961             break;
7962             case 'prev':
7963                 this.grid.dataModel.loadPage(this.cursor -1);
7964             break;
7965             case 'next':
7966                 this.grid.dataModel.loadPage(this.cursor + 1);
7967             break;
7968             case 'last':
7969                 this.grid.dataModel.loadPage(this.lastPage);
7970             break;
7971             case 'refresh':
7972                 this.grid.dataModel.loadPage(this.cursor);
7973             break;
7974         }
7975     },
7976     
7977     unplugDataModel : function(dm){
7978         dm.removeListener('beforeload', this.beforeLoad, this);
7979         dm.removeListener('load', this.onPageLoaded, this);
7980         dm.removeListener('loadexception', this.onLoadError, this);
7981         YAHOO.ext.grid.PagedGridView.superclass.unplugDataModel.call(this, dm);
7982     },
7983     
7984     plugDataModel : function(dm){
7985         dm.on('beforeload', this.beforeLoad, this, true);
7986         dm.on('load', this.onPageLoaded, this, true);
7987         dm.on('loadexception', this.onLoadError, this);
7988         YAHOO.ext.grid.PagedGridView.superclass.plugDataModel.call(this, dm);
7989     },
7990     
7991     
7992     beforePageText : "Page",
7993     
7994     afterPageText : "of %0",
7995     
7996     firstText : "First Page",
7997     
7998     prevText : "Previous Page",
7999     
8000     nextText : "Next Page",
8001     
8002     lastText : "Last Page",
8003     
8004     refreshText : "Refresh"
8005 });
8006
8007
8008 YAHOO.ext.grid.EditorGrid = function(container, dataModel, colModel){
8009     YAHOO.ext.grid.EditorGrid.superclass.constructor.call(this, container, dataModel, 
8010                       colModel, new YAHOO.ext.grid.EditorSelectionModel());
8011     this.container.addClass('yeditgrid');
8012 };
8013 YAHOO.extendX(YAHOO.ext.grid.EditorGrid, YAHOO.ext.grid.Grid);
8014
8015 YAHOO.ext.grid.AbstractColumnModel = function(){
8016         
8017         this.onWidthChange = new YAHOO.util.CustomEvent('widthChanged');
8018     this.onHeaderChange = new YAHOO.util.CustomEvent('headerChanged');
8019         this.onHiddenChange = new YAHOO.util.CustomEvent('hiddenChanged');
8020     
8021     this.events = {
8022         
8023             'widthchange': this.onWidthChange,
8024         
8025             'headerchange': this.onHeaderChange,
8026         
8027             'hiddenchange': this.onHiddenChange
8028     };
8029 };
8030
8031 YAHOO.ext.grid.AbstractColumnModel.prototype = {
8032         fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
8033     on : YAHOO.ext.util.Observable.prototype.on,
8034     addListener : YAHOO.ext.util.Observable.prototype.addListener,
8035     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
8036     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
8037     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
8038     bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
8039     
8040     fireWidthChange : function(colIndex, newWidth){
8041                 this.onWidthChange.fireDirect(this, colIndex, newWidth);
8042         },
8043         
8044         fireHeaderChange : function(colIndex, newHeader){
8045                 this.onHeaderChange.fireDirect(this, colIndex, newHeader);
8046         },
8047         
8048         fireHiddenChange : function(colIndex, hidden){
8049                 this.onHiddenChange.fireDirect(this, colIndex, hidden);
8050         },
8051         
8052         
8053     getColumnCount : function(){
8054         return 0;
8055     },
8056     
8057     
8058     isSortable : function(col){
8059         return false;
8060     },
8061     
8062     
8063     isHidden : function(col){
8064         return false;
8065     },
8066     
8067     
8068     getSortType : function(col){
8069         return YAHOO.ext.grid.DefaultColumnModel.sortTypes.none;
8070     },
8071     
8072     
8073     getRenderer : function(col){
8074         return YAHOO.ext.grid.DefaultColumnModel.defaultRenderer;
8075     },
8076     
8077     
8078     getColumnWidth : function(col){
8079         return 0;
8080     },
8081     
8082     
8083     getTotalWidth : function(){
8084         return 0;
8085     },
8086     
8087     
8088     getColumnHeader : function(col){
8089         return '';
8090     }
8091 };
8092
8093
8094 YAHOO.ext.grid.DefaultColumnModel = function(config){
8095         YAHOO.ext.grid.DefaultColumnModel.superclass.constructor.call(this);
8096     
8097     this.config = config;
8098     
8099     
8100     this.defaultWidth = 100;
8101     
8102     this.defaultSortable = false;
8103 };
8104 YAHOO.extendX(YAHOO.ext.grid.DefaultColumnModel, YAHOO.ext.grid.AbstractColumnModel, {
8105     
8106     
8107     getColumnCount : function(){
8108         return this.config.length;
8109     },
8110         
8111     
8112     isSortable : function(col){
8113         if(typeof this.config[col].sortable == 'undefined'){
8114             return this.defaultSortable;
8115         }
8116         return this.config[col].sortable;
8117     },
8118         
8119     
8120     getSortType : function(col){
8121         if(!this.dataMap){
8122             
8123             var map = [];
8124             for(var i = 0, len = this.config.length; i < len; i++){
8125                 map[this.getDataIndex(i)] = i;
8126             }
8127             this.dataMap = map;
8128         }
8129         col = this.dataMap[col];
8130         if(!this.config[col].sortType){
8131             return YAHOO.ext.grid.DefaultColumnModel.sortTypes.none;
8132         }
8133         return this.config[col].sortType;
8134     },
8135         
8136     
8137     setSortType : function(col, fn){
8138         this.config[col].sortType = fn;
8139     },
8140         
8141     
8142     
8143     getRenderer : function(col){
8144         if(!this.config[col].renderer){
8145             return YAHOO.ext.grid.DefaultColumnModel.defaultRenderer;
8146         }
8147         return this.config[col].renderer;
8148     },
8149         
8150     
8151     setRenderer : function(col, fn){
8152         this.config[col].renderer = fn;
8153     },
8154         
8155     
8156     getColumnWidth : function(col){
8157         return this.config[col].width || this.defaultWidth;
8158     },
8159         
8160     
8161     setColumnWidth : function(col, width, suppressEvent){
8162         this.config[col].width = width;
8163         this.totalWidth = null;
8164         if(!suppressEvent){
8165              this.onWidthChange.fireDirect(this, col, width);
8166         }
8167     },
8168         
8169     
8170     getTotalWidth : function(includeHidden){
8171         if(!this.totalWidth){
8172             this.totalWidth = 0;
8173             for(var i = 0; i < this.config.length; i++){
8174                 if(includeHidden || !this.isHidden(i)){
8175                     this.totalWidth += this.getColumnWidth(i);
8176                 }
8177             }
8178         }
8179         return this.totalWidth;
8180     },
8181         
8182     
8183     getColumnHeader : function(col){
8184         return this.config[col].header;
8185     },
8186          
8187     
8188     setColumnHeader : function(col, header){
8189         this.config[col].header = header;
8190         this.onHeaderChange.fireDirect(this, col, header);
8191     },
8192     
8193     
8194     getColumnTooltip : function(col){
8195             return this.config[col].tooltip;
8196     },
8197     
8198     setColumnTooltip : function(col, header){
8199             this.config[col].tooltip = tooltip;
8200     },
8201         
8202     
8203     getDataIndex : function(col){
8204         if(typeof this.config[col].dataIndex != 'number'){
8205             return col;
8206         }
8207         return this.config[col].dataIndex;
8208     },
8209          
8210     
8211     setDataIndex : function(col, dataIndex){
8212         this.config[col].dataIndex = dataIndex;
8213     },
8214     
8215     isCellEditable : function(colIndex, rowIndex){
8216         return this.config[colIndex].editable || (typeof this.config[colIndex].editable == 'undefined' && this.config[colIndex].editor);
8217     },
8218     
8219     
8220     getCellEditor : function(colIndex, rowIndex){
8221         return this.config[colIndex].editor;
8222     },
8223        
8224     
8225     setEditable : function(col, editable){
8226         this.config[col].editable = editable;
8227     },
8228     
8229     
8230     
8231     isHidden : function(colIndex){
8232         return this.config[colIndex].hidden;
8233     },
8234     
8235     
8236     
8237     isFixed : function(colIndex){
8238         return this.config[colIndex].fixed;
8239     },
8240     
8241     
8242     isResizable : function(colIndex){
8243         return this.config[colIndex].resizable !== false;
8244     },
8245     
8246     setHidden : function(colIndex, hidden){
8247         this.config[colIndex].hidden = hidden;
8248         this.totalWidth = null;
8249         this.fireHiddenChange(colIndex, hidden);
8250     },
8251     
8252     
8253     setEditor : function(col, editor){
8254         this.config[col].editor = editor;
8255     }
8256 });
8257
8258
8259 YAHOO.ext.grid.DefaultColumnModel.sortTypes = {
8260     none : function(s) {
8261         return s;
8262     },
8263
8264     asUCString : function(s) {
8265         return String(s).toUpperCase();
8266     },
8267     
8268     asDate : function(s) {
8269         if(s instanceof Date){
8270             return s.getTime();
8271         }
8272         return Date.parse(String(s));
8273     },
8274     
8275     asFloat : function(s) {
8276         var val = parseFloat(String(s).replace(/,/g, ''));
8277         if(isNaN(val)) val = 0;
8278         return val;
8279     },
8280     
8281     asInt : function(s) {
8282         var val = parseInt(String(s).replace(/,/g, ''));
8283         if(isNaN(val)) val = 0;
8284         return val;
8285     }
8286 };
8287
8288 YAHOO.ext.grid.DefaultColumnModel.defaultRenderer = function(value){
8289         if(typeof value == 'string' && value.length < 1){
8290             return '&#160;';
8291         }
8292         return value;
8293 }
8294
8295 YAHOO.ext.grid.AbstractDataModel = function(){
8296     
8297     this.onCellUpdated = new YAHOO.util.CustomEvent('onCellUpdated');
8298     
8299     this.onTableDataChanged = new YAHOO.util.CustomEvent('onTableDataChanged');
8300     
8301     this.onRowsDeleted = new YAHOO.util.CustomEvent('onRowsDeleted');
8302     
8303     this.onRowsInserted = new YAHOO.util.CustomEvent('onRowsInserted');
8304     
8305     this.onRowsUpdated = new YAHOO.util.CustomEvent('onRowsUpdated');
8306     
8307     this.onRowsSorted = new YAHOO.util.CustomEvent('onRowsSorted');
8308     
8309     this.events = {
8310       
8311       'cellupdated' : this.onCellUpdated,
8312       
8313       'datachanged' : this.onTableDataChanged,
8314       
8315       'rowsdeleted' : this.onRowsDeleted,
8316       
8317       'rowsinserted' : this.onRowsInserted,
8318       
8319       'rowsupdated' : this.onRowsUpdated,
8320       
8321       'rowssorted' : this.onRowsSorted
8322     };
8323 };
8324
8325 YAHOO.ext.grid.AbstractDataModel.prototype = {
8326     
8327     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
8328     on : YAHOO.ext.util.Observable.prototype.on,
8329     addListener : YAHOO.ext.util.Observable.prototype.addListener,
8330     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
8331     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
8332     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
8333     bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
8334     
8335     
8336     fireCellUpdated : function(row, col){
8337         this.onCellUpdated.fireDirect(this, row, col);
8338     },
8339     
8340     
8341     fireTableDataChanged : function(){
8342         this.onTableDataChanged.fireDirect(this);
8343     },
8344     
8345     
8346     fireRowsDeleted : function(firstRow, lastRow){
8347         this.onRowsDeleted.fireDirect(this, firstRow, lastRow);
8348     },
8349     
8350     
8351     fireRowsInserted : function(firstRow, lastRow){
8352         this.onRowsInserted.fireDirect(this, firstRow, lastRow);
8353     },
8354     
8355     
8356     fireRowsUpdated : function(firstRow, lastRow){
8357         this.onRowsUpdated.fireDirect(this, firstRow, lastRow);
8358     },
8359     
8360     
8361     fireRowsSorted : function(sortColumnIndex, sortDir, noRefresh){
8362         this.onRowsSorted.fireDirect(this, sortColumnIndex, sortDir, noRefresh);
8363     },
8364     
8365     
8366     sort : function(sortInfo, columnIndex, direction, suppressEvent){
8367         
8368     },
8369     
8370     
8371     getSortState : function(){
8372         return {column: this.sortColumn, direction: this.sortDir};
8373     },
8374     
8375     
8376     getRowCount : function(){
8377         
8378     },
8379     
8380     
8381     getTotalRowCount : function(){
8382         return this.getRowCount();
8383     },
8384     
8385     
8386     
8387     getRowId : function(rowIndex){
8388         
8389     },
8390     
8391     
8392     getValueAt : function(rowIndex, colIndex){
8393         
8394     },
8395     
8396     
8397     setValueAt : function(value, rowIndex, colIndex){
8398         
8399     },
8400     
8401     isPaged : function(){
8402         return false;
8403     }
8404 };
8405
8406
8407 YAHOO.ext.grid.DefaultDataModel = function(data){
8408     YAHOO.ext.grid.DefaultDataModel.superclass.constructor.call(this);
8409     
8410     this.data = data;
8411 };
8412 YAHOO.extendX(YAHOO.ext.grid.DefaultDataModel, YAHOO.ext.grid.AbstractDataModel, {
8413     
8414     getRowCount : function(){
8415         return this.data.length;
8416     },
8417         
8418     
8419     getRowId : function(rowIndex){
8420         return this.data[rowIndex][0];
8421     },
8422     
8423     
8424     getRow : function(rowIndex){
8425         return this.data[rowIndex];
8426     },
8427     
8428     
8429     getRows : function(indexes){
8430         var data = this.data;
8431         var r = [];
8432         for(var i = 0; i < indexes.length; i++){
8433            r.push(data[indexes[i]]);
8434         }
8435         return r;
8436     },
8437     
8438     
8439     getValueAt : function(rowIndex, colIndex){
8440         return this.data[rowIndex][colIndex];
8441     },
8442     
8443     
8444     setValueAt: function(value, rowIndex, colIndex){
8445         this.data[rowIndex][colIndex] = value;
8446         this.fireCellUpdated(rowIndex, colIndex);
8447     },
8448     
8449     
8450     removeRows: function(startIndex, endIndex){
8451         endIndex = endIndex || startIndex;
8452         this.data.splice(startIndex, endIndex-startIndex+1);
8453         this.fireRowsDeleted(startIndex, endIndex);
8454     },
8455     
8456     
8457     removeRow: function(index){
8458         this.data.splice(index, 1);
8459         this.fireRowsDeleted(index, index);
8460     },
8461     
8462     
8463     removeAll: function(){
8464         var count = this.getRowCount();
8465         if(count > 0){
8466                 this.removeRows(0, count-1);
8467         }
8468     },
8469     
8470     
8471     query: function(spec, returnUnmatched){
8472         var d = this.data;
8473         var r = [];
8474         for(var i = 0; i < d.length; i++){
8475             var row = d[i];
8476             var isMatch = true;
8477             for(var col in spec){
8478                 
8479                     if(!isMatch) continue;
8480                     var filter = spec[col];
8481                     switch(typeof filter){
8482                         case 'string':
8483                         case 'number':
8484                         case 'boolean':
8485                           if(row[col] != filter){
8486                               isMatch = false;
8487                           }
8488                         break;
8489                         case 'function':
8490                           if(!filter(row[col], row)){
8491                               isMatch = false;
8492                           }
8493                         break;
8494                         case 'object':
8495                            if(filter instanceof RegExp){
8496                                if(String(row[col]).search(filter) === -1){
8497                                    isMatch = false;
8498                                }
8499                            }
8500                         break;
8501                     }
8502                 
8503             }
8504             if(isMatch && !returnUnmatched){
8505                 r.push(i);
8506             }else if(!isMatch && returnUnmatched){
8507                 r.push(i);
8508             }
8509         }
8510         return r;
8511     },
8512     
8513     
8514     filter: function(query){
8515         var matches = this.query(query, true);
8516         var data = this.data;
8517         
8518         
8519         for(var i = 0; i < matches.length; i++){ 
8520             data[matches[i]]._deleted = true;
8521         }
8522         for(var i = 0; i < data.length; i++){
8523             while(data[i] && data[i]._deleted === true){
8524                 this.removeRow(i);
8525             }
8526         }
8527         return matches.length;
8528     },
8529     
8530     
8531     addRow: function(cellValues){
8532         this.data.push(cellValues);
8533         var newIndex = this.data.length-1;
8534         this.fireRowsInserted(newIndex, newIndex);
8535         this.applySort();
8536         return newIndex;
8537     },
8538     
8539     
8540     addRows: function(rowData){
8541         this.data = this.data.concat(rowData);
8542         var firstIndex = this.data.length-rowData.length;
8543         this.fireRowsInserted(firstIndex, firstIndex+rowData.length-1);
8544         this.applySort();
8545     },
8546     
8547     
8548     insertRow: function(index, cellValues){
8549         this.data.splice(index, 0, cellValues);
8550         this.fireRowsInserted(index, index);
8551         this.applySort();
8552         return index;
8553     },
8554     
8555     
8556     insertRows: function(index, rowData){
8557         
8558         var args = rowData.concat();
8559         args.splice(0, 0, index, 0);
8560         this.data.splice.apply(this.data, args);
8561         this.fireRowsInserted(index, index+rowData.length-1);
8562         this.applySort();
8563     },
8564     
8565     
8566     applySort: function(suppressEvent){
8567         if(typeof this.sortColumn != 'undefined'){
8568                 this.sort(this.sortInfo, this.sortColumn, this.sortDir, suppressEvent);
8569         }
8570     },
8571     
8572     
8573     setDefaultSort: function(sortInfo, columnIndex, direction){
8574         this.sortInfo = sortInfo;
8575         this.sortColumn = columnIndex;
8576         this.sortDir = direction;
8577     },
8578     
8579     sort: function(sortInfo, columnIndex, direction, suppressEvent){
8580         
8581         this.sortInfo = sortInfo;
8582         this.sortColumn = columnIndex;
8583         this.sortDir = direction;
8584         
8585         var dsc = (direction && direction.toUpperCase() == 'DESC');
8586         var sortType = null;
8587         if(sortInfo != null){
8588             if(typeof sortInfo == 'function'){
8589                 sortType = sortInfo;
8590             }else if(typeof sortInfo == 'object'){
8591                 sortType = sortInfo.getSortType(columnIndex);;
8592             }
8593         }
8594         var fn = function(cells, cells2){
8595             var v1 = sortType ? sortType(cells[columnIndex], cells) : cells[columnIndex];
8596             var v2 = sortType ? sortType(cells2[columnIndex], cells2) : cells2[columnIndex];
8597             if(v1 < v2)
8598                         return dsc ? +1 : -1;
8599                 if(v1 > v2)
8600                         return dsc ? -1 : +1;
8601             return 0;
8602         };
8603         this.data.sort(fn);
8604         if(!suppressEvent){
8605            this.fireRowsSorted(columnIndex, direction);
8606         }
8607     },
8608     
8609      
8610     each: function(fn, scope){
8611         var d = this.data;
8612         for(var i = 0, len = d.length; i < len; i++){
8613             if(fn.call(scope || window, d[i], i) === false) break;
8614         }
8615     }
8616 });
8617
8618
8619 if(YAHOO.ext.grid.DefaultColumnModel){
8620     YAHOO.ext.grid.DefaultDataModel.sortTypes = YAHOO.ext.grid.DefaultColumnModel.sortTypes;
8621 }
8622
8623 YAHOO.ext.grid.LoadableDataModel = function(dataType){
8624     YAHOO.ext.grid.LoadableDataModel.superclass.constructor.call(this, []);
8625     
8626     
8627     this.onLoad = new YAHOO.util.CustomEvent('load');
8628     
8629     this.onLoadException = new YAHOO.util.CustomEvent('loadException');
8630     
8631     this.events['load'] = this.onLoad;
8632     
8633     this.events['beforeload'] = new YAHOO.util.CustomEvent('beforeload');
8634     
8635     this.events['loadexception'] = this.onLoadException;
8636     
8637     
8638     this.dataType = dataType;
8639     
8640     this.preprocessors = [];
8641     
8642     this.postprocessors = [];
8643     
8644     
8645     
8646     this.loadedPage = 1;
8647     
8648     this.remoteSort = false;
8649     
8650     this.pageSize = 0;
8651     
8652     this.pageUrl = null;
8653     
8654     this.baseParams = {};
8655     
8656     this.paramMap = {'page':'page', 'pageSize':'pageSize', 'sortColumn':'sortColumn', 'sortDir':'sortDir'};
8657     
8658 };
8659 YAHOO.extendX(YAHOO.ext.grid.LoadableDataModel, YAHOO.ext.grid.DefaultDataModel, {
8660     
8661     
8662     setLoadedPage: function(pageNum, userCallback){
8663         this.loadedPage = pageNum;
8664         if(typeof userCallback == 'function'){
8665             userCallback();
8666         }
8667     },
8668     
8669     
8670     isPaged: function(){
8671         return this.pageSize > 0;
8672     },
8673     
8674     
8675     getTotalRowCount: function(){
8676         return this.totalCount || this.getRowCount();
8677     },
8678     
8679     
8680     getPageSize: function(){
8681         return this.pageSize;
8682     },
8683     
8684     
8685     getTotalPages: function(){
8686         if(this.getPageSize() == 0 || this.getTotalRowCount() == 0){
8687             return 1;
8688         }
8689         return Math.ceil(this.getTotalRowCount()/this.getPageSize());
8690     },
8691     
8692     
8693     initPaging: function(url, pageSize, baseParams){
8694         this.pageUrl = url;
8695         this.pageSize = pageSize;
8696         this.remoteSort = true;
8697         if(baseParams) this.baseParams = baseParams;
8698     },
8699     
8700     
8701     createParams: function(pageNum, sortColumn, sortDir){
8702         var params = {}, map = this.paramMap;
8703         for(var key in this.baseParams){
8704             if(typeof this.baseParams[key] != 'function'){
8705                 params[key] = this.baseParams[key];
8706             }
8707         }
8708         params[map['page']] = pageNum;
8709         params[map['pageSize']] = this.getPageSize();
8710         params[map['sortColumn']] = (typeof sortColumn == 'undefined' ? '' : sortColumn);
8711         params[map['sortDir']] = sortDir || '';
8712         return params;
8713     },
8714     
8715     
8716     loadPage: function(pageNum, callback, keepExisting){
8717         var sort = this.getSortState();
8718         var params = this.createParams(pageNum, sort.column, sort.direction);
8719         this.load(this.pageUrl, params, this.setLoadedPage.createDelegate(this, [pageNum, callback]), 
8720                    keepExisting ? (pageNum-1) * this.pageSize : null);
8721     },
8722     
8723     
8724     applySort: function(suppressEvent){
8725         if(!this.remoteSort){
8726             YAHOO.ext.grid.LoadableDataModel.superclass.applySort.apply(this, arguments);
8727         }else if(!suppressEvent){
8728             var sort = this.getSortState();
8729             if(sort.column){
8730                this.fireRowsSorted(sort.column, sort.direction, true);
8731             }
8732         }
8733     },
8734     
8735     
8736     resetPaging: function(){
8737         this.loadedPage = 1;
8738     },
8739     
8740     
8741     sort: function(sortInfo, columnIndex, direction, suppressEvent){
8742         if(!this.remoteSort){
8743             YAHOO.ext.grid.LoadableDataModel.superclass.sort.apply(this, arguments);
8744         }else{
8745             this.sortInfo = sortInfo;
8746             this.sortColumn = columnIndex;
8747             this.sortDir = direction;
8748             var params = this.createParams(this.loadedPage, columnIndex, direction);
8749             this.load(this.pageUrl, params, this.fireRowsSorted.createDelegate(this, [columnIndex, direction, true]));
8750         }
8751     },
8752     
8753     
8754     load: function(url, params, callback, insertIndex){
8755         this.fireEvent('beforeload', this);
8756         if(params && typeof params != 'string'){ 
8757             var buf = [];
8758             for(var key in params){
8759                 if(typeof params[key] != 'function'){
8760                     buf.push(encodeURIComponent(key), '=', encodeURIComponent(params[key]), '&');
8761                 }
8762             }
8763             delete buf[buf.length-1];
8764             params = buf.join('');
8765         }
8766         var cb = {
8767             success: this.processResponse,
8768             failure: this.processException,
8769             scope: this,
8770                 argument: {callback: callback, insertIndex: insertIndex}
8771         };
8772         var method = params ? 'POST' : 'GET';
8773         this.transId = YAHOO.util.Connect.asyncRequest(method, url, cb, params);
8774     },
8775     
8776     
8777     processResponse: function(response){
8778         var cb = response.argument.callback;
8779         var keepExisting = (typeof response.argument.insertIndex == 'number');
8780         var insertIndex = response.argument.insertIndex;
8781         switch(this.dataType){
8782                 case YAHOO.ext.grid.LoadableDataModel.XML:
8783                         this.loadData(response.responseXML, cb, keepExisting, insertIndex);
8784                 break;
8785                 case YAHOO.ext.grid.LoadableDataModel.JSON:
8786                         var rtext = response.responseText;
8787                         try { 
8788                         
8789                         while(rtext.substring(0,1) == " ") {
8790                             rtext = rtext.substring(1, rtext.length);
8791                         }
8792                         
8793                         if(rtext.indexOf("{") < 0) {
8794                             throw "Invalid JSON response";
8795                         }
8796                 
8797                         
8798                         if(rtext.indexOf("{}") === 0) {
8799                             this.loadData({}, response.argument.callback);
8800                             return;
8801                         }
8802                 
8803                         
8804                         
8805                         var jsonObjRaw = eval("(" + rtext + ")");
8806                         if(!jsonObjRaw) {
8807                             throw "Error evaling JSON response";
8808                         }
8809                                 this.loadData(jsonObjRaw, cb, keepExisting, insertIndex);
8810                     } catch(e) {
8811                         this.fireLoadException(e, response);
8812                                 if(typeof cb == 'function'){
8813                                 cb(this, false);
8814                             }
8815                         }
8816                 break;
8817                 case YAHOO.ext.grid.LoadableDataModel.TEXT:
8818                         this.loadData(response.responseText, cb, keepExisting, insertIndex);
8819                 break;
8820         };
8821     },
8822     
8823     
8824     processException: function(response){
8825         this.fireLoadException(null, response);
8826         if(typeof response.argument.callback == 'function'){
8827             response.argument.callback(this, false);
8828         }
8829     },
8830     
8831     fireLoadException: function(e, responseObj){
8832         this.onLoadException.fireDirect(this, e, responseObj);
8833     },
8834     
8835     fireLoadEvent: function(){
8836         this.fireEvent('load', this.loadedPage, this.getTotalPages());
8837     },
8838     
8839     
8840     addPreprocessor: function(columnIndex, fn){
8841         this.preprocessors[columnIndex] = fn;
8842     },
8843     
8844     
8845     getPreprocessor: function(columnIndex){
8846         return this.preprocessors[columnIndex];
8847     },
8848     
8849     
8850     removePreprocessor: function(columnIndex){
8851         this.preprocessors[columnIndex] = null;
8852     },
8853     
8854     
8855     addPostprocessor: function(columnIndex, fn){
8856         this.postprocessors[columnIndex] = fn;
8857     },
8858     
8859     
8860     getPostprocessor: function(columnIndex){
8861         return this.postprocessors[columnIndex];
8862     },
8863     
8864     
8865     removePostprocessor: function(columnIndex){
8866         this.postprocessors[columnIndex] = null;
8867     },
8868     
8869     loadData: function(data, callback, keepExisting, insertIndex){
8870         
8871     }
8872 });
8873
8874 YAHOO.ext.grid.LoadableDataModel.XML = 'xml';
8875 YAHOO.ext.grid.LoadableDataModel.JSON = 'json';
8876 YAHOO.ext.grid.LoadableDataModel.TEXT = 'text';
8877
8878
8879
8880
8881
8882
8883
8884 YAHOO.ext.grid.XMLDataModel = function(schema, xml){
8885     YAHOO.ext.grid.XMLDataModel.superclass.constructor.call(this, YAHOO.ext.grid.LoadableDataModel.XML);
8886     
8887     this.schema = schema;
8888     this.xml = xml;
8889     if(xml){
8890         this.loadData(xml);
8891     }
8892     this.idSeed = 0;
8893 };
8894 YAHOO.extendX(YAHOO.ext.grid.XMLDataModel, YAHOO.ext.grid.LoadableDataModel, {
8895     
8896     getDocument: function(){
8897        return this.xml;    
8898     },
8899     
8900     
8901     loadData: function(doc, callback, keepExisting, insertIndex){
8902         //debugger;
8903         this.xml = doc;
8904         var idField = this.schema.id;
8905         var fields = this.schema.fields;
8906         if(this.schema.totalTag){
8907             this.totalCount = null;
8908             var totalNode = doc.getElementsByTagName(this.schema.totalTag);
8909             if(totalNode && totalNode.item(0) && totalNode.item(0).firstChild) {
8910                 var v = parseInt(totalNode.item(0).firstChild.nodeValue, 10);
8911                 if(!isNaN(v)){
8912                     this.totalCount = v;
8913                 }
8914                 }
8915         }
8916         var rowData = [];
8917         var nodes = doc.getElementsByTagName(this.schema.tagName);
8918         if(nodes && nodes.length > 0) {
8919             for(var i = 0; i < nodes.length; i++) {
8920                 var node = nodes.item(i);
8921                 var colData = [];
8922                 colData.node = node;
8923                 colData.id = this.getNamedValue(node, idField, String(++this.idSeed));
8924                 for(var j = 0; j < fields.length; j++) {
8925                     var val = this.getNamedValue(node, fields[j], "");
8926                     if(this.preprocessors[j]){
8927                         val = this.preprocessors[j](val);
8928                     }
8929                     colData.push(val);
8930                 }
8931                 rowData.push(colData);
8932             }
8933         }
8934         if(keepExisting !== true){
8935            YAHOO.ext.grid.XMLDataModel.superclass.removeAll.call(this);
8936         }
8937         if(typeof insertIndex != 'number'){
8938             insertIndex = this.getRowCount();
8939         }
8940         YAHOO.ext.grid.XMLDataModel.superclass.insertRows.call(this, insertIndex, rowData);
8941         if(typeof callback == 'function'){
8942                 callback(this, true);
8943         }
8944         this.fireLoadEvent();
8945     },
8946     
8947     
8948     addRow: function(id, cellValues){
8949         var node = this.createNode(this.xml, id, cellValues);
8950         cellValues.id = id || ++this.idSeed;
8951         cellValues.node = node;
8952         return YAHOO.ext.grid.XMLDataModel.superclass.addRow.call(this, cellValues);
8953     },
8954     
8955     
8956     insertRow: function(index, id, cellValues){
8957         var node = this.createNode(this.xml, id, cellValues);
8958         cellValues.id = id || ++this.idSeed;
8959         cellValues.node = node;
8960         return YAHOO.ext.grid.XMLDataModel.superclass.insertRow.call(this, index, cellValues);
8961     },
8962     
8963     
8964     removeRow: function(index){
8965         var node = this.data[index].node;
8966         node.parentNode.removeChild(node);
8967         YAHOO.ext.grid.XMLDataModel.superclass.removeRow.call(this, index, index);
8968     },
8969     
8970     getNode: function(rowIndex){
8971         return this.data[rowIndex].node;
8972     },
8973     
8974     
8975     createNode: function(xmlDoc, id, colData){
8976         var template = this.data[0].node;
8977         var newNode = template.cloneNode(true);
8978         var fields = this.schema.fields;
8979         for(var i = 0, len = fields.length; i < len; i++){
8980             var nodeValue = colData[i];
8981             if(this.postprocessors[i]){
8982                 nodeValue = this.postprocessors[i](nodeValue);
8983             }
8984             this.setNamedValue(newNode, fields[i], nodeValue);
8985         }
8986         if(id){
8987             this.setNamedValue(newNode, this.schema.idField, id);
8988         }
8989         template.parentNode.appendChild(newNode);
8990         return newNode;
8991     },
8992     
8993     
8994     getNamedValue: function(node, name, defaultValue){
8995         if(!node || !name){
8996                 return defaultValue;
8997         }
8998         var nodeValue = defaultValue;
8999         var attrNode = node.attributes.getNamedItem(name);
9000         if(attrNode) {
9001                 nodeValue = attrNode.value;
9002         } else {
9003             var childNode = node.getElementsByTagName(name);
9004             if(childNode && childNode.item(0) && childNode.item(0).firstChild) {
9005                 nodeValue = childNode.item(0).firstChild.nodeValue;
9006                 }else{
9007                     
9008                     var index = name.indexOf(':');
9009                     if(index > 0){
9010                         return this.getNamedValue(node, name.substr(index+1), defaultValue);
9011                     }
9012                 }
9013         }
9014         return nodeValue;
9015     },
9016     
9017     
9018     setNamedValue: function(node, name, value){
9019         if(!node || !name){
9020                 return;
9021         }
9022         var attrNode = node.attributes.getNamedItem(name);
9023         if(attrNode) {
9024                 attrNode.value = value;
9025                 return;
9026         }
9027         var childNode = node.getElementsByTagName(name);
9028         if(childNode && childNode.item(0) && childNode.item(0).firstChild) {
9029             childNode.item(0).firstChild.nodeValue = value;
9030         }else{
9031             
9032             var index = name.indexOf(':');
9033             if(index > 0){
9034                 this.setNamedValue(node, name.substr(index+1), value);
9035             }
9036         }
9037     },
9038     
9039     
9040     setValueAt: function(value, rowIndex, colIndex){
9041         var node = this.data[rowIndex].node;
9042         if(node){
9043             var nodeValue = value;
9044             if(this.postprocessors[colIndex]){
9045                 nodeValue = this.postprocessors[colIndex](value);
9046             }
9047             this.setNamedValue(node, this.schema.fields[colIndex], nodeValue);
9048         }
9049         YAHOO.ext.grid.XMLDataModel.superclass.setValueAt.call(this, value, rowIndex, colIndex);
9050     },
9051     
9052     
9053     getRowId: function(rowIndex){
9054         return this.data[rowIndex].id;
9055     },
9056     
9057     addRows : function(rowData){   
9058         for(var j = 0, len = rowData.length; j < len; j++){
9059            var cellValues = rowData[j];
9060            var id = ++this.idSeed; 
9061            var node = this.createNode(this.xml, id, cellValues);       
9062            cellValues.node=node;
9063            cellValues.id = cellValues.id || id;
9064            YAHOO.ext.grid.XMLDataModel.superclass.addRow.call(this,cellValues);
9065         }
9066     },   
9067
9068    insertRows : function(index, rowData){
9069        
9070        rowData = rowData.slice(0).reverse();
9071        for(var j = 0, len = rowData.length; j < len; j++){
9072           var cellValues = rowData[j];
9073           var id = ++this.idSeed; 
9074           var node = this.createNode(this.xml, id, cellValues);
9075           cellValues.id = cellValues.id || id;
9076           cellValues.node = node;
9077           YAHOO.ext.grid.XMLDataModel.superclass.insertRow.call(this, index, cellValues);
9078        }
9079    }
9080 });
9081
9082 YAHOO.ext.grid.XMLQueryDataModel = function(){
9083    YAHOO.ext.grid.XMLQueryDataModel.superclass.constructor.apply(this, arguments);
9084 };
9085 YAHOO.extendX(YAHOO.ext.grid.XMLQueryDataModel, YAHOO.ext.grid.XMLDataModel, {
9086     getNamedValue: function(node, name, defaultValue){
9087         if(!node || !name){
9088                 return defaultValue;
9089         }
9090         var nodeValue = defaultValue;
9091         var childNode = cssQuery(name, node);
9092         if(childNode && childNode[0]) {
9093             nodeValue = childNode[0].firstChild.nodeValue;
9094         }
9095         return nodeValue;
9096     }
9097 });
9098
9099
9100 YAHOO.ext.grid.JSONDataModel = function(schema){
9101     YAHOO.ext.grid.JSONDataModel.superclass.constructor.call(this, YAHOO.ext.grid.LoadableDataModel.JSON);
9102     
9103     this.schema = schema;
9104 };
9105 YAHOO.extendX(YAHOO.ext.grid.JSONDataModel, YAHOO.ext.grid.LoadableDataModel, {
9106     
9107     loadData : function(data, callback, keepExisting){
9108         var idField = this.schema.id;
9109         var fields = this.schema.fields;
9110         try{
9111                 if(this.schema.totalProperty){
9112                 var v = parseInt(eval('data.' + this.schema.totalProperty), 10);
9113                 if(!isNaN(v)){
9114                     this.totalCount = v;
9115                 }
9116             }
9117                 var rowData = [];
9118             var root = eval('data.' + this.schema.root);
9119             for(var i = 0; i < root.length; i++){
9120                         var node = root[i];
9121                         var colData = [];
9122                         colData.node = node;
9123                         colData.id = (typeof node[idField] != 'undefined' && node[idField] !== '' ? node[idField] : String(i));
9124                         for(var j = 0; j < fields.length; j++) {
9125                             var val = node[fields[j]];
9126                             if(typeof val == 'undefined'){
9127                                 val = '';
9128                             }
9129                     if(this.preprocessors[j]){
9130                         val = this.preprocessors[j](val);
9131                     }
9132                     colData.push(val);
9133                 }
9134                 rowData.push(colData);
9135                 }
9136                 if(keepExisting !== true){
9137                   this.removeAll();
9138                 }
9139             this.addRows(rowData);
9140                 if(typeof callback == 'function'){
9141                 callback(this, true);
9142             }
9143                 this.fireLoadEvent();
9144         }catch(e){
9145                 this.fireLoadException(e, null);
9146                 if(typeof callback == 'function'){
9147                 callback(this, false);
9148             }
9149         }
9150     },
9151     
9152     
9153     getRowId : function(rowIndex){
9154         return this.data[rowIndex].id;
9155     }
9156 });
9157
9158 YAHOO.ext.grid.DefaultSelectionModel = function(){
9159     this.selectedRows = [];
9160     this.selectedRowIds = [];
9161     this.lastSelectedRow = null;
9162     
9163     this.onRowSelect = new YAHOO.util.CustomEvent('SelectionTable.rowSelected');
9164     this.onSelectionChange = new YAHOO.util.CustomEvent('SelectionTable.selectionChanged');
9165     
9166     this.events = {
9167         
9168             'selectionchange' : this.onSelectionChange,
9169         
9170             'rowselect' : this.onRowSelect
9171     };
9172     
9173     this.locked = false;
9174 };
9175
9176 YAHOO.ext.grid.DefaultSelectionModel.prototype = {
9177     
9178     init : function(grid){
9179         this.grid = grid;
9180         this.initEvents();
9181     },
9182     
9183     
9184     lock : function(){
9185         this.locked = true;
9186     },
9187     
9188     
9189     unlock : function(){
9190         this.locked = false;  
9191     },
9192     
9193     
9194     isLocked : function(){
9195         return this.locked;    
9196     },
9197     
9198     
9199     initEvents : function(){
9200         if(this.grid.trackMouseOver){
9201                 this.grid.addListener("mouseover", this.handleOver, this, true);
9202                 this.grid.addListener("mouseout", this.handleOut, this, true);
9203         }
9204         this.grid.addListener("rowclick", this.rowClick, this, true);
9205         this.grid.addListener("keydown", this.keyDown, this, true);
9206     },
9207     
9208     fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
9209     on : YAHOO.ext.util.Observable.prototype.on,
9210     addListener : YAHOO.ext.util.Observable.prototype.addListener,
9211     delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
9212     removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
9213     purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
9214     bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
9215     
9216     
9217     syncSelectionsToIds : function(){
9218         if(this.getCount() > 0){
9219             var ids = this.selectedRowIds.concat();
9220             this.clearSelections();
9221             this.selectRowsById(ids, true);
9222         }
9223     },
9224     
9225     
9226     selectRowsById : function(id, keepExisting){
9227         var rows = this.grid.getRowsById(id);
9228         if (!(rows instanceof Array)){
9229             this.selectRow(rows, keepExisting);
9230             return;
9231         }
9232         this.selectRows(rows, keepExisting);
9233     },
9234     
9235     
9236     getCount : function(){
9237         return this.selectedRows.length;
9238     },
9239     
9240     
9241     selectFirstRow : function(){
9242         for(var j = 0; j < this.grid.rows.length; j++){
9243             if(this.isSelectable(this.grid.rows[j])){
9244                 this.focusRow(this.grid.rows[j]);
9245                 this.setRowState(this.grid.rows[j], true);
9246                 return;
9247             }
9248         }
9249     },
9250     
9251     
9252     selectNext : function(keepExisting){
9253         if(this.lastSelectedRow){
9254             for(var j = (this.lastSelectedRow.rowIndex+1); j < this.grid.rows.length; j++){
9255                 var row = this.grid.rows[j];
9256                 if(this.isSelectable(row)){
9257                     this.focusRow(row);
9258                     this.setRowState(row, true, keepExisting);
9259                     return;
9260                 }
9261             }
9262         }
9263     },
9264     
9265     
9266     selectPrevious : function(keepExisting){
9267         if(this.lastSelectedRow){
9268             for(var j = (this.lastSelectedRow.rowIndex-1); j >= 0; j--){
9269                 var row = this.grid.rows[j];
9270                 if(this.isSelectable(row)){
9271                     this.focusRow(row);
9272                     this.setRowState(row, true, keepExisting);
9273                     return;
9274                 }
9275             }
9276         }
9277     },
9278     
9279     
9280     getSelectedRows : function(){
9281         return this.selectedRows;
9282     },
9283     
9284     
9285     getSelectedRowIds : function(){
9286         return this.selectedRowIds;
9287     },
9288     
9289     
9290     clearSelections : function(){
9291         if(this.isLocked()) return;
9292         var oldSelections = this.selectedRows.concat();
9293         for(var j = 0; j < oldSelections.length; j++){
9294             this.setRowState(oldSelections[j], false);
9295         }
9296         this.selectedRows = [];
9297         this.selectedRowIds = [];
9298     },
9299     
9300         
9301     
9302     selectAll : function(){
9303         if(this.isLocked()) return;
9304         this.selectedRows = [];
9305         this.selectedRowIds = [];
9306         for(var j = 0, len = this.grid.rows.length; j < len; j++){
9307             this.setRowState(this.grid.rows[j], true, true);
9308         }
9309     },
9310     
9311     
9312     hasSelection : function(){
9313         return this.selectedRows.length > 0;
9314     },
9315     
9316     
9317     isSelected : function(row){
9318         return row && (row.selected === true || row.getAttribute('selected') == 'true');
9319     },
9320     
9321     
9322     isSelectable : function(row){
9323         return row && row.getAttribute('selectable') != 'false';
9324     },
9325     
9326     
9327     rowClick : function(grid, rowIndex, e){
9328         if(this.isLocked()) return;
9329         var row = grid.getRow(rowIndex);
9330         if(this.isSelectable(row)){
9331             if(e.shiftKey && this.lastSelectedRow){
9332                 var lastIndex = this.lastSelectedRow.rowIndex;
9333                 this.selectRange(this.lastSelectedRow, row, e.ctrlKey);
9334                 this.lastSelectedRow = this.grid.el.dom.rows[lastIndex];
9335             }else{
9336                 this.focusRow(row);
9337                 var rowState = e.ctrlKey ? !this.isSelected(row) : true;
9338                 this.setRowState(row, rowState, e.hasModifier());
9339             }
9340         }
9341     },
9342     
9343     
9344     focusRow : function(row){
9345         this.grid.view.focusRow(row);
9346     },
9347
9348     
9349     selectRow : function(row, keepExisting){
9350         this.setRowState(this.getRow(row), true, keepExisting);
9351     },
9352     
9353     
9354     selectRows : function(rows, keepExisting){
9355         if(!keepExisting){
9356             this.clearSelections();
9357         }
9358         for(var i = 0; i < rows.length; i++){
9359             this.selectRow(rows[i], true);
9360         }
9361     },
9362     
9363     
9364     deselectRow : function(row){
9365         this.setRowState(this.getRow(row), false);
9366     },
9367     
9368     
9369     getRow : function(row){
9370         if(typeof row == 'number'){
9371             row = this.grid.rows[row];
9372         }
9373         return row;
9374     },
9375     
9376     
9377     selectRange : function(startRow, endRow, keepExisting){
9378         startRow = this.getRow(startRow);
9379         endRow = this.getRow(endRow);
9380         this.setRangeState(startRow, endRow, true, keepExisting);
9381     },
9382     
9383     
9384     deselectRange : function(startRow, endRow){
9385         startRow = this.getRow(startRow);
9386         endRow = this.getRow(endRow);
9387         this.setRangeState(startRow, endRow, false, true);
9388     },
9389     
9390     
9391     setRowStateFromChild : function(childEl, selected, keepExisting){
9392         var row = this.grid.getRowFromChild(childEl);
9393         this.setRowState(row, selected, keepExisting);
9394     },
9395     
9396     
9397     setRangeState : function(startRow, endRow, selected, keepExisting){
9398         if(this.isLocked()) return;
9399         if(!keepExisting){
9400             this.clearSelections();
9401         }
9402         var curRow = startRow;
9403         while(curRow.rowIndex != endRow.rowIndex){
9404             this.setRowState(curRow, selected, true);
9405             curRow = (startRow.rowIndex < endRow.rowIndex ? 
9406                         this.grid.getRowAfter(curRow) : this.grid.getRowBefore(curRow))
9407         }
9408         this.setRowState(endRow, selected, true);
9409     },
9410     
9411     
9412     setRowState : function(row, selected, keepExisting){
9413         if(this.isLocked()) return;
9414         if(this.isSelectable(row)){
9415             if(selected){
9416                 if(!keepExisting){
9417                     this.clearSelections();
9418                 }
9419                 this.setRowClass(row, 'selected');
9420                 row.selected = true;
9421                 this.selectedRows.push(row);
9422                 this.selectedRowIds.push(this.grid.dataModel.getRowId(row.rowIndex));
9423                 this.lastSelectedRow = row;
9424             }else{
9425                 this.setRowClass(row, '');
9426                 row.selected = false;
9427                 this._removeSelected(row);
9428             }
9429             this.fireEvent('rowselect', this, row, selected);
9430             this.fireEvent('selectionchange', this, this.selectedRows, this.selectedRowIds);
9431         }
9432     },
9433
9434     
9435     handleOver : function(e){
9436         var row = this.grid.getRowFromChild(e.getTarget());
9437         if(this.isSelectable(row) && !this.isSelected(row)){
9438             this.setRowClass(row, 'over');
9439         }
9440     },
9441     
9442     
9443     handleOut : function(e){
9444         var row = this.grid.getRowFromChild(e.getTarget());
9445         if(this.isSelectable(row) && !this.isSelected(row)){
9446             this.setRowClass(row, '');
9447         }
9448     },
9449     
9450     
9451     keyDown : function(e){
9452         if(e.browserEvent.keyCode == e.DOWN){
9453             this.selectNext(e.shiftKey);
9454             e.preventDefault();
9455         }else if(e.browserEvent.keyCode == e.UP){
9456             this.selectPrevious(e.shiftKey);
9457             e.preventDefault();
9458         }
9459     },
9460
9461     
9462     setRowClass : function(row, cssClass){
9463         if(this.isSelectable(row)){
9464             if(cssClass == 'selected'){
9465                 YAHOO.util.Dom.removeClass(row, 'ygrid-row-over');
9466                 YAHOO.util.Dom.addClass(row, 'ygrid-row-selected');
9467             }else if(cssClass == 'over'){
9468                 YAHOO.util.Dom.removeClass(row, 'ygrid-row-selected');
9469                 YAHOO.util.Dom.addClass(row, 'ygrid-row-over');
9470             }else if(cssClass == ''){
9471                 YAHOO.util.Dom.removeClass(row, 'ygrid-row-selected');
9472                 YAHOO.util.Dom.removeClass(row, 'ygrid-row-over');
9473             }
9474         }
9475     },
9476     
9477     
9478     _removeSelected : function(row){
9479         var sr = this.selectedRows;
9480         for (var i = 0; i < sr.length; i++) {
9481           if (sr[i] === row){
9482               this.selectedRows.splice(i, 1);
9483               this.selectedRowIds.splice(i, 1);
9484               return;
9485           }
9486         }
9487     }
9488 };
9489
9490
9491 YAHOO.ext.grid.SingleSelectionModel = function(){
9492     YAHOO.ext.grid.SingleSelectionModel.superclass.constructor.call(this);
9493 };
9494
9495 YAHOO.extendX(YAHOO.ext.grid.SingleSelectionModel, YAHOO.ext.grid.DefaultSelectionModel);
9496
9497
9498 YAHOO.ext.grid.SingleSelectionModel.prototype.setRowState = function(row, selected){
9499     YAHOO.ext.grid.SingleSelectionModel.superclass.setRowState.call(this, row, selected, false);
9500 };
9501
9502 YAHOO.ext.grid.DisableSelectionModel = function(){
9503     YAHOO.ext.grid.DisableSelectionModel.superclass.constructor.call(this);
9504 };
9505
9506 YAHOO.extendX(YAHOO.ext.grid.DisableSelectionModel, YAHOO.ext.grid.DefaultSelectionModel);
9507
9508 YAHOO.ext.grid.DisableSelectionModel.prototype.initEvents = function(){
9509 };
9510
9511
9512 YAHOO.ext.grid.EditorSelectionModel = function(){
9513     YAHOO.ext.grid.EditorSelectionModel.superclass.constructor.call(this);
9514     
9515     this.clicksToActivateCell = 1;
9516     this.events['cellactivate'] = new YAHOO.util.CustomEvent('cellactivate');
9517 };
9518
9519 YAHOO.extendX(YAHOO.ext.grid.EditorSelectionModel, YAHOO.ext.grid.DefaultSelectionModel);
9520
9521 YAHOO.ext.grid.EditorSelectionModel.prototype.disableArrowNavigation = false;
9522 YAHOO.ext.grid.EditorSelectionModel.prototype.controlForArrowNavigation = false;
9523
9524
9525 YAHOO.ext.grid.EditorSelectionModel.prototype.initEvents = function(){
9526     this.grid.addListener("cellclick", this.onCellClick, this, true);
9527     this.grid.addListener("celldblclick", this.onCellDblClick, this, true);
9528     this.grid.addListener("keydown", this.keyDown, this, true);
9529 };
9530
9531 YAHOO.ext.grid.EditorSelectionModel.prototype.onCellClick = function(grid, rowIndex, colIndex){
9532     if(this.clicksToActivateCell == 1){
9533         var row = this.grid.getRow(rowIndex);
9534         var cell = row.childNodes[colIndex];
9535         if(cell){
9536             this.activate(row, cell);
9537         }
9538     }
9539 };
9540
9541 YAHOO.ext.grid.EditorSelectionModel.prototype.activate = function(row, cell){
9542     this.fireEvent('cellactivate', this, row, cell);
9543     this.grid.doEdit(row, cell);
9544 };
9545
9546 YAHOO.ext.grid.EditorSelectionModel.prototype.onCellDblClick = function(grid, rowIndex, colIndex){
9547     if(this.clicksToActivateCell == 2){
9548         var row = this.grid.getRow(rowIndex);
9549         var cell = row.childNodes[colIndex];
9550         if(cell){
9551             this.activate(row, cell);
9552         }
9553     }
9554 };
9555
9556
9557 YAHOO.ext.grid.EditorSelectionModel.prototype.setRowState = function(row, selected){
9558     YAHOO.ext.grid.EditorSelectionModel.superclass.setRowState.call(this, row, false, false);
9559 };
9560
9561 YAHOO.ext.grid.EditorSelectionModel.prototype.focusRow = function(row, selected){
9562 };
9563
9564 YAHOO.ext.grid.EditorSelectionModel.prototype.getEditorCellAfter = function(cell, spanRows){
9565     var g = this.grid;
9566     var next = g.getCellAfter(cell);
9567     while(next && !g.colModel.isCellEditable(next.columnIndex)){
9568         next = g.getCellAfter(next);
9569     }
9570     if(!next && spanRows){
9571         var row = g.getRowAfter(g.getRowFromChild(cell));
9572         if(row){
9573             next = g.getFirstCell(row);
9574             if(!g.colModel.isCellEditable(next.columnIndex)){
9575                 next = this.getEditorCellAfter(next);
9576             }
9577         }
9578     }
9579     return next;
9580 };
9581
9582 YAHOO.ext.grid.EditorSelectionModel.prototype.getEditorCellBefore = function(cell, spanRows){
9583     var g = this.grid;
9584     var prev = g.getCellBefore(cell);
9585     while(prev && !g.colModel.isCellEditable(prev.columnIndex)){
9586         prev = g.getCellBefore(prev);
9587     }
9588     if(!prev && spanRows){
9589         var row = g.getRowBefore(g.getRowFromChild(cell));
9590         if(row){
9591             prev = g.getLastCell(row);
9592             if(!g.colModel.isCellEditable(prev.columnIndex)){
9593                prev = this.getEditorCellBefore(prev);
9594             }
9595         }
9596     }
9597     return prev;
9598 };
9599
9600 YAHOO.ext.grid.EditorSelectionModel.prototype.allowArrowNav = function(e){
9601     return (!this.disableArrowNavigation && (!this.controlForArrowNavigation || e.ctrlKey));
9602 }
9603
9604 YAHOO.ext.grid.EditorSelectionModel.prototype.keyDown = function(e){
9605     var g = this.grid, cm = g.colModel, cell = g.getEditingCell();
9606     if(!cell) return;
9607     var newCell;
9608     switch(e.browserEvent.keyCode){
9609          case e.TAB:
9610              if(e.shiftKey){
9611                  newCell = this.getEditorCellBefore(cell, true);
9612              }else{
9613                  newCell = this.getEditorCellAfter(cell, true);
9614              }
9615              e.preventDefault();
9616          break;
9617          case e.DOWN:
9618              if(this.allowArrowNav(e)){
9619                  var next = g.getRowAfter(g.getRowFromChild(cell));
9620                  if(next){
9621                      newCell = next.childNodes[cell.columnIndex];
9622                  }
9623              }
9624          break;
9625          case e.UP:
9626              if(this.allowArrowNav(e)){
9627                  var prev = g.getRowBefore(g.getRowFromChild(cell));
9628                  if(prev){
9629                      newCell = prev.childNodes[cell.columnIndex];
9630                  }
9631              }
9632          break;
9633          case e.RETURN:
9634              if(e.shiftKey){
9635                  var prev = g.getRowBefore(g.getRowFromChild(cell));
9636                  if(prev){
9637                      newCell = prev.childNodes[cell.columnIndex];
9638                  }
9639              }else{
9640                  var next = g.getRowAfter(g.getRowFromChild(cell));
9641                  if(next){
9642                      newCell = next.childNodes[cell.columnIndex];
9643                  }
9644              }
9645          break;
9646          case e.RIGHT:
9647              if(this.allowArrowNav(e)){
9648                  newCell = this.getEditorCellAfter(cell);
9649              }
9650          break;
9651          case e.LEFT:
9652              if(this.allowArrowNav(e)){
9653                  newCell = this.getEditorCellBefore(cell);
9654              }
9655          break;
9656     };
9657     if(newCell){
9658         this.activate(g.getRowFromChild(newCell), newCell);
9659         e.stopEvent();
9660     }
9661 };
9662
9663
9664 YAHOO.ext.grid.EditorAndSelectionModel = function(){
9665     YAHOO.ext.grid.EditorAndSelectionModel.superclass.constructor.call(this);
9666     this.events['cellactivate'] = new YAHOO.util.CustomEvent('cellactivate');
9667 };
9668
9669 YAHOO.extendX(YAHOO.ext.grid.EditorAndSelectionModel, YAHOO.ext.grid.DefaultSelectionModel);
9670
9671 YAHOO.ext.grid.EditorAndSelectionModel.prototype.initEvents = function(){
9672     YAHOO.ext.grid.EditorAndSelectionModel.superclass.initEvents.call(this);
9673     this.grid.addListener("celldblclick", this.onCellDblClick, this, true);
9674 };
9675
9676 YAHOO.ext.grid.EditorAndSelectionModel.prototype.onCellDblClick = function(grid, rowIndex, colIndex){
9677     var row = this.grid.getRow(rowIndex);
9678     var cell = row.childNodes[colIndex];
9679     if(cell){
9680         this.fireEvent('cellactivate', this, row, cell);
9681         this.grid.doEdit(row, cell);
9682     }
9683 }; 
9684
9685 YAHOO.ext.grid.CellEditor = function(element){
9686     this.colIndex = null;
9687     this.rowIndex = null;
9688     this.grid = null;
9689     this.editing = false;
9690     this.originalValue = null;
9691     this.element = getEl(element, true);
9692     this.element.addClass('ygrid-editor');
9693     this.element.dom.tabIndex = 1;
9694     this.initialized = false;
9695     this.callback = null;
9696 };
9697
9698 YAHOO.ext.grid.CellEditor.prototype = {
9699     init : function(grid, bodyElement, callback){
9700         
9701         
9702         
9703         if(this.initialized) return;
9704         this.initialized = true;
9705         this.callback = callback;
9706         this.grid = grid;
9707         bodyElement.appendChild(this.element.dom);
9708         this.initEvents();
9709     },
9710     
9711     initEvents : function(){
9712         var stopOnEnter = function(e){
9713             if(e.browserEvent.keyCode == e.RETURN){
9714                 this.stopEditing(true);
9715             }else if(e.browserEvent.keyCode == e.ESC){
9716                 this.setValue(this.originalValue);
9717                 this.stopEditing(true);
9718             }
9719         }
9720         this.element.mon('keydown', stopOnEnter, this, true);
9721         this.element.on('blur', this.stopEditing, this, true);
9722     },
9723
9724     startEditing : function(value, row, cell){
9725         this.originalValue = value;
9726         this.rowIndex = row.rowIndex;
9727         this.colIndex = cell.columnIndex;
9728         this.cell = cell;
9729         this.setValue(value);
9730         var cellbox = getEl(cell, true).getBox();
9731         this.fitToCell(cellbox);
9732         this.editing = true;
9733         this.show();
9734     },
9735      
9736     stopEditing : function(focusCell){
9737          if(this.editing){
9738              this.editing = false;
9739              var newValue = this.getValue();
9740              this.hide();
9741              
9742              if(this.originalValue != newValue){
9743                 this.callback(newValue, this.rowIndex, this.colIndex);
9744              }
9745          }
9746      },
9747      
9748     setValue : function(value){
9749         this.element.dom.value = value;
9750     },
9751     
9752     getValue : function(){
9753         return this.element.dom.value;
9754     },
9755     
9756     fitToCell : function(box){
9757         this.element.setBox(box, true);
9758     },
9759     
9760     show : function(){
9761         this.element.show();
9762         this.element.focus();
9763     },
9764     
9765     hide : function(){
9766         try{
9767             this.element.dom.blur();
9768         }catch(e){}
9769         this.element.hide();
9770     }
9771 };
9772
9773 YAHOO.ext.grid.CheckboxEditor = function(){
9774     var div = document.createElement('span');
9775     div.className = 'ygrid-editor ygrid-checkbox-editor';
9776     var cb = document.createElement('input');
9777     cb.type = 'checkbox';
9778     cb.setAttribute('autocomplete', 'off');
9779     div.appendChild(cb);
9780     document.body.appendChild(div);
9781     YAHOO.ext.grid.CheckboxEditor.superclass.constructor.call(this, div);
9782     div.tabIndex = '';
9783     cb.tabIndex = 1;
9784     this.cb = getEl(cb, true);
9785 };
9786
9787 YAHOO.extendX(YAHOO.ext.grid.CheckboxEditor, YAHOO.ext.grid.CellEditor);
9788
9789 YAHOO.ext.grid.CheckboxEditor.prototype.fitToCell = function(box){
9790     this.element.setBox(box, true);
9791 };
9792
9793 YAHOO.ext.grid.CheckboxEditor.prototype.setValue = function(value){
9794      this.cb.dom.checked = (value === true || value === 'true' || value === 1 || value === '1');
9795 };
9796
9797 YAHOO.ext.grid.CheckboxEditor.prototype.getValue = function(){
9798      return this.cb.dom.checked;
9799 };
9800
9801 YAHOO.ext.grid.CheckboxEditor.prototype.show = function(){
9802     this.element.show();
9803     this.cb.focus();
9804 };
9805
9806 YAHOO.ext.grid.CheckboxEditor.prototype.initEvents = function(){
9807     var stopOnEnter = function(e){
9808         if(e.browserEvent.keyCode == e.RETURN){
9809             this.stopEditing(true);
9810         }else if(e.browserEvent.keyCode == e.ESC){
9811             this.setValue(this.originalValue);
9812             this.stopEditing(true);
9813         }
9814     }
9815     this.cb.mon('keydown', stopOnEnter, this, true);
9816     this.cb.on('blur', this.stopEditing, this, true);
9817 };
9818
9819 YAHOO.ext.grid.CheckboxEditor.prototype.hide = function(){
9820     try{
9821         this.cb.dom.blur();
9822     }catch(e){}
9823     this.element.hide();
9824 };
9825
9826 YAHOO.ext.grid.DateEditor = function(config){
9827     var div = document.createElement('span');
9828     div.className = 'ygrid-editor ygrid-editor-container';
9829     
9830     var element = document.createElement('input');
9831     element.type = 'text';
9832     element.tabIndex = 1;
9833     element.setAttribute('autocomplete', 'off');
9834     div.appendChild(element);
9835     
9836     var pick = document.createElement('span');
9837     pick.className = 'pick-button';
9838     div.appendChild(pick);
9839     
9840     document.body.appendChild(div);
9841     
9842     this.div = getEl(div, true);
9843     this.element = getEl(element, true);
9844     this.pick = getEl(pick, true);
9845     
9846     this.colIndex = null;
9847     this.rowIndex = null;
9848     this.grid = null;
9849     this.editing = false;
9850     this.originalValue = null;
9851     this.initialized = false;
9852     this.callback = null;
9853     
9854     this.cal = null;
9855     this.mouseDownHandler = YAHOO.ext.EventManager.wrap(this.handleMouseDown, this, true);
9856     
9857     YAHOO.ext.util.Config.apply(this, config);
9858     if(typeof this.minValue == 'string') this.minValue = this.parseDate(this.minValue);
9859     if(typeof this.maxValue == 'string') this.maxValue = this.parseDate(this.maxValue);
9860     this.ddMatch = /ddnone/;
9861     if(this.disabledDates){
9862         var dd = this.disabledDates;
9863         var re = "(?:";
9864         for(var i = 0; i < dd.length; i++){
9865             re += dd[i];
9866             if(i != dd.length-1) re += "|";
9867         }
9868         this.ddMatch = new RegExp(re + ")");
9869     }
9870 };
9871
9872 YAHOO.ext.grid.DateEditor.prototype = {
9873     init : function(grid, bodyElement, callback){
9874         if(this.initialized) return;
9875         
9876         this.initialized = true;
9877         this.callback = callback;
9878         this.grid = grid;
9879         bodyElement.appendChild(this.div.dom);
9880         this.initEvents();
9881     },
9882     
9883     initEvents : function(){
9884          var stopOnEnter = function(e){
9885             if(e.browserEvent.keyCode == e.RETURN){
9886                 this.stopEditing(true);
9887             }else if(e.browserEvent.keyCode == e.ESC){
9888                 this.setValue(this.originalValue);
9889                 this.stopEditing(true);
9890             }
9891         }
9892         this.element.mon('keydown', stopOnEnter, this, true);
9893         var vtask = new YAHOO.ext.util.DelayedTask(this.validate, this);
9894         this.element.mon('keyup', vtask.delay.createDelegate(vtask, [this.validationDelay]));
9895         this.pick.on('click', this.showCalendar, this, true);
9896     },
9897     
9898     startEditing : function(value, row, cell){
9899         this.originalValue = value;
9900         this.rowIndex = row.rowIndex;
9901         this.colIndex = cell.columnIndex;
9902         this.cell = cell;
9903         this.setValue(value);
9904         this.validate();
9905         var cellbox = getEl(cell, true).getBox();
9906         this.div.setBox(cellbox, true);
9907         this.element.setWidth(cellbox.width-this.pick.getWidth());
9908         this.editing = true;
9909         YAHOO.util.Event.on(document, "mousedown", this.mouseDownHandler);
9910         this.show();
9911     },
9912      
9913      stopEditing : function(focusCell){
9914          if(this.editing){
9915              YAHOO.util.Event.removeListener(document, "mousedown", this.mouseDownHandler);
9916              this.editing = false;
9917              var newValue = this.getValue();
9918              this.hide();
9919              
9920              if(this.originalValue != newValue){
9921                 this.callback(newValue, this.rowIndex, this.colIndex);
9922              }
9923          }
9924      },
9925     
9926     setValue : function(value){
9927         this.element.dom.value = this.formatDate(value);
9928         this.validate();
9929     },
9930     
9931     getValue : function(){
9932         if(!this.validate()){
9933            return this.originalValue;
9934        }else{
9935            var value = this.element.dom.value;
9936            if(value.length < 1){
9937                return value;
9938            } else{
9939                return this.parseDate(value);
9940            }
9941        }   
9942     },
9943     
9944     show : function() {
9945         this.div.show();
9946         this.element.focus();
9947         this.validate();
9948     },
9949     
9950     hide : function(){
9951         try{
9952             this.element.dom.blur();
9953         }catch(e){}
9954         this.div.hide();
9955     },
9956     
9957     validate : function(){
9958         var dom = this.element.dom;
9959         var value = dom.value;
9960         if(value.length < 1){ 
9961              if(this.allowBlank){
9962                  dom.title = '';
9963                  this.element.removeClass('ygrid-editor-invalid');
9964                  return true;
9965              }else{
9966                  dom.title = this.blankText;
9967                  this.element.addClass('ygrid-editor-invalid');
9968                  return false;
9969              }
9970         }
9971         value = this.parseDate(value);
9972         if(!value){
9973             dom.title = this.invalidText.replace('%0', dom.value).replace('%1', this.format);
9974             this.element.addClass('ygrid-editor-invalid');
9975             return false;
9976         }
9977         var time = value.getTime();
9978         if(this.minValue && time < this.minValue.getTime()){
9979             dom.title = this.minText.replace('%0', this.formatDate(this.minValue));
9980             this.element.addClass('ygrid-editor-invalid');
9981             return false;
9982         }
9983         if(this.maxValue && time > this.maxValue.getTime()){
9984             dom.title = this.maxText.replace('%0', this.formatDate(this.maxValue));
9985             this.element.addClass('ygrid-editor-invalid');
9986             return false;
9987         }
9988         if(this.disabledDays){
9989             var day = value.getDay();
9990             for(var i = 0; i < this.disabledDays.length; i++) {
9991                 if(day === this.disabledDays[i]){
9992                     dom.title = this.disabledDaysText;
9993                     this.element.addClass('ygrid-editor-invalid');
9994                     return false;
9995                 }
9996             }
9997         }
9998         var fvalue = this.formatDate(value);
9999         if(this.ddMatch.test(fvalue)){
10000             dom.title = this.disabledDatesText.replace('%0', fvalue);
10001             this.element.addClass('ygrid-editor-invalid');
10002             return false;
10003         }
10004         var msg = this.validator(value);
10005         if(msg !== true){
10006             dom.title = msg;
10007             this.element.addClass('ygrid-editor-invalid');
10008             return false;
10009         }
10010         dom.title = '';
10011         this.element.removeClass('ygrid-editor-invalid');
10012         return true;
10013     },
10014     
10015     handleMouseDown : function(e){
10016         var t = e.getTarget();
10017         var dom = this.div.dom;
10018         if(t != dom && !YAHOO.util.Dom.isAncestor(dom, t)){
10019             this.stopEditing();
10020         }
10021     },
10022     
10023     showCalendar : function(value){
10024         if(this.cal == null){
10025             this.cal = new YAHOO.ext.DatePicker(this.div.dom.parentNode.parentNode);
10026         }
10027         this.cal.minDate = this.minValue;
10028         this.cal.maxDate = this.maxValue;
10029         this.cal.disabledDatesRE = this.ddMatch;
10030         this.cal.disabledDatesText = this.disabledDatesText;
10031         this.cal.disabledDays = this.disabledDays;
10032         this.cal.disabledDaysText = this.disabledDaysText;
10033         this.cal.format = this.format;
10034         if(this.minValue){
10035             this.cal.minText = this.minText.replace('%0', this.formatDate(this.minValue));
10036         }
10037         if(this.maxValue){
10038             this.cal.maxText = this.maxText.replace('%0', this.formatDate(this.maxValue));
10039         }
10040         var r = this.div.getRegion();
10041         this.cal.show(r.left, r.bottom, this.getValue(), this.setValue.createDelegate(this));
10042     },
10043     
10044     parseDate : function(value){
10045         if(!value || value instanceof Date) return value;
10046         return Date.parseDate(value, this.format);
10047     },
10048     
10049     formatDate : function(date){
10050         if(!date || !(date instanceof Date)) return date;
10051         return date.format(this.format);
10052     }
10053 };
10054
10055 YAHOO.ext.grid.DateEditor.prototype.format = 'm/d/y';
10056 YAHOO.ext.grid.DateEditor.prototype.disabledDays = null;
10057 YAHOO.ext.grid.DateEditor.prototype.disabledDaysText = '';
10058 YAHOO.ext.grid.DateEditor.prototype.disabledDates = null;
10059 YAHOO.ext.grid.DateEditor.prototype.disabledDatesText = '';
10060 YAHOO.ext.grid.DateEditor.prototype.allowBlank = true;
10061 YAHOO.ext.grid.DateEditor.prototype.minValue = null;
10062 YAHOO.ext.grid.DateEditor.prototype.maxValue = null;
10063 YAHOO.ext.grid.DateEditor.prototype.minText = 'The date in this field must be after %0';
10064 YAHOO.ext.grid.DateEditor.prototype.maxText = 'The date in this field must be before %0';
10065 YAHOO.ext.grid.DateEditor.prototype.blankText = 'This field cannot be blank';
10066 YAHOO.ext.grid.DateEditor.prototype.invalidText = '%0 is not a valid date - it must be in the format %1';
10067 YAHOO.ext.grid.DateEditor.prototype.validationDelay = 200;
10068 YAHOO.ext.grid.DateEditor.prototype.validator = function(){return true;};
10069
10070 YAHOO.ext.grid.NumberEditor = function(config){
10071     var element = document.createElement('input');
10072     element.type = 'text';
10073     element.className = 'ygrid-editor ygrid-num-editor';
10074     element.setAttribute('autocomplete', 'off');
10075     document.body.appendChild(element);
10076     YAHOO.ext.grid.NumberEditor.superclass.constructor.call(this, element);
10077     YAHOO.ext.util.Config.apply(this, config);
10078 };
10079 YAHOO.extendX(YAHOO.ext.grid.NumberEditor, YAHOO.ext.grid.CellEditor);
10080
10081 YAHOO.ext.grid.NumberEditor.prototype.initEvents = function(){
10082     var stopOnEnter = function(e){
10083         if(e.browserEvent.keyCode == e.RETURN){
10084             this.stopEditing(true);
10085         }else if(e.browserEvent.keyCode == e.ESC){
10086             this.setValue(this.originalValue);
10087             this.stopEditing(true);
10088         }
10089     };
10090     
10091     var allowed = "0123456789";
10092     if(this.allowDecimals){
10093         allowed += this.decimalSeparator;
10094     }
10095     if(this.allowNegative){
10096         allowed += '-';
10097     }
10098     var keyPress = function(e){
10099         var c = e.getCharCode();
10100         if(c != e.BACKSPACE && allowed.indexOf(String.fromCharCode(c)) === -1){
10101             e.stopEvent();
10102         }
10103     };
10104     this.element.mon('keydown', stopOnEnter, this, true);
10105     var vtask = new YAHOO.ext.util.DelayedTask(this.validate, this);
10106     this.element.mon('keyup', vtask.delay.createDelegate(vtask, [this.validationDelay]));
10107     this.element.mon('keypress', keyPress, this, true);
10108     this.element.on('blur', this.stopEditing, this, true);
10109 };
10110
10111 YAHOO.ext.grid.NumberEditor.prototype.validate = function(){
10112     var dom = this.element.dom;
10113     var value = dom.value;
10114     if(value.length < 1){ 
10115          if(this.allowBlank){
10116              dom.title = '';
10117              this.element.removeClass('ygrid-editor-invalid');
10118              return true;
10119          }else{
10120              dom.title = this.blankText;
10121              this.element.addClass('ygrid-editor-invalid');
10122              return false;
10123          }
10124     }
10125     if(value.search(/\d+/) === -1){
10126         dom.title = this.nanText.replace('%0', value);
10127         this.element.addClass('ygrid-editor-invalid');
10128         return false;
10129     }
10130     var num = this.parseValue(value);
10131     if(num < this.minValue){
10132         dom.title = this.minText.replace('%0', this.minValue);
10133         this.element.addClass('ygrid-editor-invalid');
10134         return false;
10135     }
10136     if(num > this.maxValue){
10137         dom.title = this.maxText.replace('%0', this.maxValue);
10138         this.element.addClass('ygrid-editor-invalid');
10139         return false;
10140     }
10141     var msg = this.validator(value);
10142     if(msg !== true){
10143         dom.title = msg;
10144         this.element.addClass('ygrid-editor-invalid');
10145         return false;
10146     }
10147     dom.title = '';
10148     this.element.removeClass('ygrid-editor-invalid');
10149     return true;
10150 };
10151
10152 YAHOO.ext.grid.NumberEditor.prototype.show = function(){
10153     this.element.dom.title = '';
10154     YAHOO.ext.grid.NumberEditor.superclass.show.call(this);
10155     if(this.selectOnFocus){
10156         try{
10157             this.element.dom.select();
10158         }catch(e){}
10159     }
10160     this.validate(this.element.dom.value);
10161 };
10162
10163 YAHOO.ext.grid.NumberEditor.prototype.getValue = function(){
10164    if(!this.validate()){
10165        return this.originalValue;
10166    }else{
10167        var value = this.element.dom.value;
10168        if(value.length < 1){
10169            return value;
10170        } else{
10171            return this.fixPrecision(this.parseValue(value));
10172        }
10173    }   
10174 };
10175 YAHOO.ext.grid.NumberEditor.prototype.parseValue = function(value){
10176     return parseFloat(new String(value).replace(this.decimalSeparator, '.'));
10177 };
10178
10179 YAHOO.ext.grid.NumberEditor.prototype.fixPrecision = function(value){
10180    if(!this.allowDecimals || this.decimalPrecision == -1 || isNaN(value) || value == 0 || !value){
10181        return value;
10182    }
10183    
10184    
10185    
10186    
10187    
10188    
10189    var scale = Math.pow(10, this.decimalPrecision+1);
10190    var fixed = this.decimalPrecisionFcn(value * scale);
10191    fixed = this.decimalPrecisionFcn(fixed/10);
10192    return fixed / (scale/10);
10193 };
10194
10195 YAHOO.ext.grid.NumberEditor.prototype.allowBlank = true;
10196 YAHOO.ext.grid.NumberEditor.prototype.allowDecimals = true;
10197 YAHOO.ext.grid.NumberEditor.prototype.decimalSeparator = '.';
10198 YAHOO.ext.grid.NumberEditor.prototype.decimalPrecision = 2;
10199 YAHOO.ext.grid.NumberEditor.prototype.decimalPrecisionFcn = Math.floor;
10200 YAHOO.ext.grid.NumberEditor.prototype.allowNegative = true;
10201 YAHOO.ext.grid.NumberEditor.prototype.selectOnFocus = true;
10202 YAHOO.ext.grid.NumberEditor.prototype.minValue = Number.NEGATIVE_INFINITY;
10203 YAHOO.ext.grid.NumberEditor.prototype.maxValue = Number.MAX_VALUE;
10204 YAHOO.ext.grid.NumberEditor.prototype.minText = 'The minimum value for this field is %0';
10205 YAHOO.ext.grid.NumberEditor.prototype.maxText = 'The maximum value for this field is %0';
10206 YAHOO.ext.grid.NumberEditor.prototype.blankText = 'This field cannot be blank';
10207 YAHOO.ext.grid.NumberEditor.prototype.nanText = '%0 is not a valid number';
10208 YAHOO.ext.grid.NumberEditor.prototype.validationDelay = 100;
10209 YAHOO.ext.grid.NumberEditor.prototype.validator = function(){return true;};
10210 YAHOO.ext.DatePicker = function(id, parentElement){
10211     this.id = id;
10212     this.selectedDate = new Date();
10213     this.visibleDate = new Date();
10214     this.element = null;
10215     this.shadow = null;
10216     this.callback = null;
10217     this.buildControl(parentElement || document.body);
10218     this.mouseDownHandler = YAHOO.ext.EventManager.wrap(this.handleMouseDown, this, true);
10219     this.keyDownHandler = YAHOO.ext.EventManager.wrap(this.handleKeyDown, this, true);
10220     this.wheelHandler = YAHOO.ext.EventManager.wrap(this.handleMouseWheel, this, true);
10221 };
10222
10223 YAHOO.ext.DatePicker.prototype = {
10224     show : function(x, y, value, callback){
10225         this.hide();
10226         this.selectedDate = value;
10227         this.visibleDate = value;
10228         this.callback = callback;
10229         this.refresh();
10230         this.element.show();
10231         this.element.setXY(this.constrainToViewport ? this.constrainXY(x, y) : [x, y]);
10232         this.shadow.show();
10233         this.shadow.setRegion(this.element.getRegion());
10234         this.element.dom.tabIndex = 1;
10235         this.element.focus();
10236         YAHOO.util.Event.on(document, "mousedown", this.mouseDownHandler);
10237         YAHOO.util.Event.on(document, "keydown", this.keyDownHandler);
10238         YAHOO.util.Event.on(document, "mousewheel", this.wheelHandler);
10239         YAHOO.util.Event.on(document, "DOMMouseScroll", this.wheelHandler);
10240     },
10241     
10242     constrainXY : function(x, y){
10243         var w = YAHOO.util.Dom.getViewportWidth();
10244         var h = YAHOO.util.Dom.getViewportHeight();
10245         var size = this.element.getSize();
10246         return [
10247             Math.min(w-size.width, x),
10248             Math.min(h-size.height, y)
10249         ];
10250     },
10251     
10252     hide : function(){
10253         this.shadow.hide();
10254         this.element.hide();
10255         YAHOO.util.Event.removeListener(document, "mousedown", this.mouseDownHandler);
10256         YAHOO.util.Event.removeListener(document, "keydown", this.keyDownHandler);
10257         YAHOO.util.Event.removeListener(document, "mousewheel", this.wheelHandler);
10258         YAHOO.util.Event.removeListener(document, "DOMMouseScroll", this.wheelHandler);
10259     },
10260     
10261     setSelectedDate : function(date){
10262         this.selectedDate = date;
10263     },
10264     
10265     getSelectedDate : function(){
10266         return this.selectedDate;
10267     },
10268     
10269     showPrevMonth : function(){
10270         this.visibleDate = this.getPrevMonth(this.visibleDate);
10271         this.refresh();
10272     },
10273     
10274     showNextMonth : function(){
10275         this.visibleDate = this.getNextMonth(this.visibleDate);
10276         this.refresh();
10277     },
10278     
10279     showPrevYear : function(){
10280         var d = this.visibleDate;
10281         this.visibleDate = new Date(d.getFullYear()-1, d.getMonth(), d.getDate());
10282         this.refresh();
10283     },
10284     
10285     showNextYear : function(){
10286         var d = this.visibleDate;
10287         this.visibleDate = new Date(d.getFullYear()+1, d.getMonth(), d.getDate());
10288         this.refresh();
10289     },
10290     
10291     handleMouseDown : function(e){
10292         var target = e.getTarget();
10293         if(target != this.element.dom && !YAHOO.util.Dom.isAncestor(this.element.dom, target)){
10294             this.hide();
10295         }
10296     },
10297     
10298     handleKeyDown : function(e){
10299         switch(e.browserEvent.keyCode){
10300             case e.LEFT:
10301                 this.showPrevMonth();
10302                 e.stopEvent();
10303             break;
10304             case e.RIGHT:
10305                 this.showNextMonth();
10306                 e.stopEvent();
10307             break;
10308             case e.DOWN:
10309                 this.showPrevYear();
10310                 e.stopEvent();
10311             break;
10312             case e.UP:
10313                 this.showNextYear();
10314                 e.stopEvent();
10315             break;
10316         }
10317     },
10318     
10319     handleMouseWheel : function(e){
10320         var delta = e.getWheelDelta();
10321         if(delta > 0){
10322             this.showPrevMonth();
10323             e.stopEvent();
10324         } else if(delta < 0){
10325             this.showNextMonth();
10326             e.stopEvent();
10327         }
10328     },
10329     
10330     handleClick : function(e){
10331         var d = this.visibleDate;
10332         var t = e.getTarget();
10333         if(t && t.className){
10334             switch(t.className){
10335                 case 'active':
10336                     this.handleSelection(new Date(d.getFullYear(), d.getMonth(), parseInt(t.innerHTML)));
10337                 break;
10338                 case 'prevday':
10339                     var p = this.getPrevMonth(d);
10340                     this.handleSelection(new Date(p.getFullYear(), p.getMonth(), parseInt(t.innerHTML)));
10341                 break;
10342                 case 'nextday':
10343                     var n = this.getNextMonth(d);
10344                     this.handleSelection(new Date(n.getFullYear(), n.getMonth(), parseInt(t.innerHTML)));
10345                 break;
10346                 case 'ypopcal-today':
10347                     this.handleSelection(new Date());
10348                 break;
10349                 case 'next-month':
10350                     this.showNextMonth();
10351                 break;
10352                 case 'prev-month':
10353                     this.showPrevMonth();
10354                 break;
10355             }   
10356         }
10357         e.stopEvent();
10358     },
10359     
10360     selectToday : function(){
10361         this.handleSelection(new Date());
10362     },
10363     
10364     handleSelection: function(date){
10365         this.selectedDate = date;
10366         this.callback(date);
10367         this.hide();    
10368     },
10369     
10370     getPrevMonth : function(d){
10371         var m = d.getMonth();var y = d.getFullYear();
10372         return (m == 0 ? new Date(--y, 11, 1) : new Date(y, --m, 1));
10373     },
10374     
10375     getNextMonth : function(d){
10376         var m = d.getMonth();var y = d.getFullYear();
10377         return (m == 11 ? new Date(++y, 0, 1) : new Date(y, ++m, 1));
10378     },
10379     
10380     getDaysInMonth : function(m, y){
10381         return (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) ? 31 : (m == 4 || m == 6 || m == 9 || m == 11) ? 30 : this.isLeapYear(y) ? 29 : 28;
10382     },
10383     
10384     isLeapYear : function(y){
10385         return (((y % 4) == 0) && ((y % 100) != 0) || ((y % 400) == 0));
10386     },
10387     
10388     clearTime : function(date){
10389         if(date){
10390             date.setHours(0);
10391             date.setMinutes(0);
10392             date.setSeconds(0);
10393             date.setMilliseconds(0);
10394         }
10395         return date;
10396     },
10397     
10398     refresh : function(){
10399         var d = this.visibleDate;
10400         this.buildInnerCal(d);
10401         this.calHead.update(this.monthNames[d.getMonth()] + ' ' + d.getFullYear());
10402         if(this.element.isVisible()){
10403             this.shadow.setRegion(this.element.getRegion());
10404         }
10405     }
10406 };
10407
10408  
10409 YAHOO.ext.DatePicker.prototype.buildControl = function(parentElement){
10410     var c = document.createElement('div');
10411     c.style.position = 'absolute';
10412     c.style.visibility = 'hidden';
10413     document.body.appendChild(c);
10414     var html = '<iframe id="'+this.id+'_shdw" frameborder="0" style="position:absolute; z-index:2000; display:none; top:0px; left:0px;" class="ypopcal-shadow"></iframe>' +
10415     '<div hidefocus="true" class="ypopcal" id="'+this.id+'" style="-moz-outline:none; position:absolute; z-index:2001; display:none; top:0px; left:0px;">' +
10416     '<table class="ypopcal-head" border=0 cellpadding=0 cellspacing=0><tbody><tr><td class="ypopcal-arrow"><div class="prev-month">&#160;</div></td><td class="ypopcal-month">&#160;</td><td class="ypopcal-arrow"><div class="next-month">&#160;</div></td></tr></tbody></table>' +
10417     '<center><div class="ypopcal-inner">';
10418     html += "<table border=0 cellpadding=2 cellspacing=0 class=\"ypopcal-table\"><thead><tr class=\"ypopcal-daynames\">";
10419     var names = this.dayNames;
10420     for(var i = 0; i < names.length; i++){
10421         html += '<td>' + names[i].substr(0, 1) + '</td>';
10422     }
10423     html+= "</tr></thead><tbody><tr>";
10424     for(var i = 0; i < 42; i++) {
10425         if(i % 7 == 0 && i != 0){
10426             html += '</tr><tr>';
10427         }
10428         html += "<td>&nbsp;</td>";
10429     }
10430     html += "</tr></tbody></table>";
10431     html += '</div><button class="ypopcal-today" style="margin-top:2px;">'+this.todayText+'</button></center></div>';
10432     c.innerHTML = html;
10433     this.shadow = getEl(c.childNodes[0], true);
10434     this.shadow.enableDisplayMode();
10435     this.element = getEl(c.childNodes[1], true);
10436     this.element.enableDisplayMode();
10437     document.body.appendChild(this.shadow.dom);
10438     document.body.appendChild(this.element.dom);
10439     document.body.removeChild(c);
10440     this.element.on("selectstart", function(){return false;});
10441     var tbody = this.element.dom.getElementsByTagName('tbody')[1];
10442     this.cells = tbody.getElementsByTagName('td');
10443     this.calHead = this.element.getChildrenByClassName('ypopcal-month', 'td')[0];
10444     this.element.mon('mousedown', this.handleClick, this, true);
10445 };
10446
10447 YAHOO.ext.DatePicker.prototype.buildInnerCal = function(dateVal){
10448     var days = this.getDaysInMonth(dateVal.getMonth() + 1, dateVal.getFullYear());
10449     var firstOfMonth = new Date(dateVal.getFullYear(), dateVal.getMonth(), 1);
10450     var startingPos = firstOfMonth.getDay();
10451     if(startingPos == 0) startingPos = 7;
10452     var pm = this.getPrevMonth(dateVal);
10453     var prevStart = this.getDaysInMonth(pm.getMonth()+1, pm.getFullYear())-startingPos;
10454     var cells = this.cells;
10455     days += startingPos;
10456     
10457     
10458     var day = 86400000;
10459     var date = this.clearTime(new Date(pm.getFullYear(), pm.getMonth(), prevStart));
10460     var today = this.clearTime(new Date()).getTime();
10461     var sel = this.selectedDate ? this.clearTime(this.selectedDate).getTime() : today + 1; 
10462     var min = this.minDate ? this.clearTime(this.minDate).getTime() : Number.NEGATIVE_INFINITY;
10463     var max = this.maxDate ? this.clearTime(this.maxDate).getTime() : Number.POSITIVE_INFINITY;
10464     var ddMatch = this.disabledDatesRE;
10465     var ddText = this.disabledDatesText;
10466     var ddays = this.disabledDays;
10467     var ddaysText = this.disabledDaysText;
10468     var format = this.format;
10469     
10470     var setCellClass = function(cal, cell, d){
10471         cell.title = '';
10472         var t = d.getTime();
10473         if(t == today){
10474             cell.className += ' today';
10475             cell.title = cal.todayText;
10476         }
10477         if(t == sel){
10478             cell.className += ' selected';
10479         }
10480         
10481         if(t < min) {
10482             cell.className = ' ypopcal-disabled';
10483             cell.title = cal.minText;
10484             return;
10485         }
10486         if(t > max) {
10487             cell.className = ' ypopcal-disabled';
10488             cell.title = cal.maxText;
10489             return;
10490         }
10491         if(ddays){
10492             var day = d.getDay();
10493             for(var i = 0; i < ddays.length; i++) {
10494                 if(day === ddays[i]){
10495                     cell.title = ddaysText;
10496                     cell.className = ' ypopcal-disabled';
10497                     return;
10498                 }
10499             }
10500         }
10501         if(ddMatch && format){
10502             var fvalue = d.format(format);
10503             if(ddMatch.test(fvalue)){
10504                 cell.title = ddText.replace('%0', fvalue);
10505                 cell.className = ' ypopcal-disabled';
10506                 return;
10507             }
10508         }
10509     };
10510     
10511     var i = 0;
10512     for(; i < startingPos; i++) {
10513         cells[i].innerHTML = (++prevStart);
10514         date.setDate(date.getDate()+1);
10515         cells[i].className = 'prevday';
10516         setCellClass(this, cells[i], date);
10517     }
10518     for(; i < days; i++){
10519         intDay = i - startingPos + 1;
10520         cells[i].innerHTML = (intDay);
10521         date.setDate(date.getDate()+1);
10522         cells[i].className = 'active';
10523         setCellClass(this, cells[i], date);
10524     }
10525     var extraDays = 0;
10526     for(; i < 42; i++) {
10527          cells[i].innerHTML = (++extraDays);
10528          date.setDate(date.getDate()+1);
10529          cells[i].className = 'nextday';
10530          setCellClass(this, cells[i], date);
10531     }
10532 };
10533
10534 YAHOO.ext.DatePicker.prototype.todayText = "Today";
10535 YAHOO.ext.DatePicker.prototype.minDate = null;
10536 YAHOO.ext.DatePicker.prototype.maxDate = null;
10537 YAHOO.ext.DatePicker.prototype.minText = "This date is before the minimum date";
10538 YAHOO.ext.DatePicker.prototype.maxText = "This date is after the maximum date";
10539 YAHOO.ext.DatePicker.prototype.format = 'm/d/y';
10540 YAHOO.ext.DatePicker.prototype.disabledDays = null;
10541 YAHOO.ext.DatePicker.prototype.disabledDaysText = '';
10542 YAHOO.ext.DatePicker.prototype.disabledDatesRE = null;
10543 YAHOO.ext.DatePicker.prototype.disabledDatesText = '';
10544 YAHOO.ext.DatePicker.prototype.constrainToViewport = true;
10545
10546
10547 YAHOO.ext.DatePicker.prototype.monthNames = Date.monthNames;
10548
10549 YAHOO.ext.DatePicker.prototype.dayNames = Date.dayNames;
10550
10551 YAHOO.ext.grid.SelectEditor = function(element){
10552     element.hideFocus = true;
10553     YAHOO.ext.grid.SelectEditor.superclass.constructor.call(this, element);
10554     this.element.swallowEvent('click');
10555 };
10556 YAHOO.extendX(YAHOO.ext.grid.SelectEditor, YAHOO.ext.grid.CellEditor);
10557
10558 YAHOO.ext.grid.SelectEditor.prototype.fitToCell = function(box){
10559     if(YAHOO.ext.util.Browser.isGecko){
10560         box.height -= 3;
10561     }
10562     this.element.setBox(box, true);
10563 };
10564
10565 YAHOO.ext.grid.TextEditor = function(config){
10566     var element = document.createElement('input');
10567     element.type = 'text';
10568     element.className = 'ygrid-editor ygrid-text-editor';
10569     element.setAttribute('autocomplete', 'off');
10570     document.body.appendChild(element);
10571     YAHOO.ext.grid.TextEditor.superclass.constructor.call(this, element);
10572     YAHOO.ext.util.Config.apply(this, config);
10573 };
10574 YAHOO.extendX(YAHOO.ext.grid.TextEditor, YAHOO.ext.grid.CellEditor);
10575
10576 YAHOO.ext.grid.TextEditor.prototype.validate = function(){
10577     var dom = this.element.dom;
10578     var value = dom.value;
10579     if(value.length < 1){ 
10580          if(this.allowBlank){
10581              dom.title = '';
10582              this.element.removeClass('ygrid-editor-invalid');
10583              return true;
10584          }else{
10585              dom.title = this.blankText;
10586              this.element.addClass('ygrid-editor-invalid');
10587              return false;
10588          }
10589     }
10590     if(value.length < this.minLength){
10591         dom.title = this.minText.replace('%0', this.minLength);
10592         this.element.addClass('ygrid-editor-invalid');
10593         return false;
10594     }
10595     if(value.length > this.maxLength){
10596         dom.title = this.maxText.replace('%0', this.maxLength);
10597         this.element.addClass('ygrid-editor-invalid');
10598         return false;
10599     }
10600     var msg = this.validator(value);
10601     if(msg !== true){
10602         dom.title = msg;
10603         this.element.addClass('ygrid-editor-invalid');
10604         return false;
10605     }
10606     if(this.regex && !this.regex.test(value)){
10607         dom.title = this.regexText;
10608         this.element.addClass('ygrid-editor-invalid');
10609         return false;
10610     }
10611     dom.title = '';
10612     this.element.removeClass('ygrid-editor-invalid');
10613     return true;
10614 };
10615
10616 YAHOO.ext.grid.TextEditor.prototype.initEvents = function(){
10617     YAHOO.ext.grid.TextEditor.superclass.initEvents.call(this);
10618     var vtask = new YAHOO.ext.util.DelayedTask(this.validate, this);
10619     this.element.mon('keyup', vtask.delay.createDelegate(vtask, [this.validationDelay]));
10620 };
10621
10622 YAHOO.ext.grid.TextEditor.prototype.show = function(){
10623     this.element.dom.title = '';
10624     YAHOO.ext.grid.TextEditor.superclass.show.call(this);
10625     this.element.focus();
10626     if(this.selectOnFocus){
10627         try{
10628             this.element.dom.select();
10629         }catch(e){}
10630     }
10631     this.validate(this.element.dom.value);
10632 };
10633
10634 YAHOO.ext.grid.TextEditor.prototype.getValue = function(){
10635    if(!this.validate()){
10636        return this.originalValue;
10637    }else{
10638        return this.element.dom.value;
10639    }   
10640 };
10641
10642 YAHOO.ext.grid.TextEditor.prototype.allowBlank = true;
10643 YAHOO.ext.grid.TextEditor.prototype.minLength = 0;
10644 YAHOO.ext.grid.TextEditor.prototype.maxLength = Number.MAX_VALUE;
10645 YAHOO.ext.grid.TextEditor.prototype.minText = 'The minimum length for this field is %0';
10646 YAHOO.ext.grid.TextEditor.prototype.maxText = 'The maximum length for this field is %0';
10647 YAHOO.ext.grid.TextEditor.prototype.selectOnFocus = true;
10648 YAHOO.ext.grid.TextEditor.prototype.blankText = 'This field cannot be blank';
10649 YAHOO.ext.grid.TextEditor.prototype.validator = function(){return true;};
10650 YAHOO.ext.grid.TextEditor.prototype.validationDelay = 200;
10651 YAHOO.ext.grid.TextEditor.prototype.regex = null;
10652 YAHOO.ext.grid.TextEditor.prototype.regexText = '';
10653
10654 YAHOO.ext.LayoutManager = function(container){
10655     YAHOO.ext.LayoutManager.superclass.constructor.call(this);
10656     this.el = getEl(container, true);
10657     this.id = this.el.id;
10658     this.el.addClass('ylayout-container');
10659     
10660     this.monitorWindowResize = true;
10661     this.regions = {};
10662     this.events = {
10663         
10664         'layout' : new YAHOO.util.CustomEvent(),
10665         
10666         'regionresized' : new YAHOO.util.CustomEvent(),
10667         
10668         'regioncollapsed' : new YAHOO.util.CustomEvent(),
10669         
10670         'regionexpanded' : new YAHOO.util.CustomEvent()
10671     };
10672     this.updating = false;
10673     YAHOO.ext.EventManager.onWindowResize(this.onWindowResize, this, true);
10674 };
10675
10676 YAHOO.extendX(YAHOO.ext.LayoutManager, YAHOO.ext.util.Observable, {
10677     
10678     isUpdating : function(){
10679         return this.updating; 
10680     },
10681     
10682     
10683     beginUpdate : function(){
10684         this.updating = true;    
10685     },
10686     
10687     
10688     endUpdate : function(noLayout){
10689         this.updating = false;
10690         if(!noLayout){
10691             this.layout();
10692         }    
10693     },
10694     
10695     layout: function(){
10696         
10697     },
10698     
10699     onRegionResized : function(region, newSize){
10700         this.fireEvent('regionresized', region, newSize);
10701         this.layout();
10702     },
10703     
10704     onRegionCollapsed : function(region){
10705         this.fireEvent('regioncollapsed', region);
10706     },
10707     
10708     onRegionExpanded : function(region){
10709         this.fireEvent('regionexpanded', region);
10710     },
10711         
10712     
10713     getViewSize : function(){
10714         var size;
10715         if(this.el.dom != document.body){
10716             this.el.beginMeasure();
10717             size = this.el.getSize();
10718             this.el.endMeasure();
10719         }else{
10720             size = {width: YAHOO.util.Dom.getViewportWidth(), height: YAHOO.util.Dom.getViewportHeight()};
10721         }
10722         size.width -= this.el.getBorderWidth('lr')-this.el.getPadding('lr');
10723         size.height -= this.el.getBorderWidth('tb')-this.el.getPadding('tb');
10724         return size;
10725     },
10726     
10727     
10728     getEl : function(){
10729         return this.el;
10730     },
10731     
10732     
10733     getRegion : function(target){
10734         return this.regions[target.toLowerCase()];
10735     },
10736     
10737     onWindowResize : function(){
10738         if(this.monitorWindowResize){
10739             this.layout();
10740         }
10741     }
10742 });
10743
10744 YAHOO.ext.LayoutRegion = function(mgr, config, pos){
10745     this.mgr = mgr;
10746     this.position  = pos;
10747     var dh = YAHOO.ext.DomHelper;
10748     
10749     this.el = dh.append(mgr.el.dom, {tag: 'div', cls: 'ylayout-panel ylayout-panel-' + this.position}, true);
10750     
10751     this.titleEl = dh.append(this.el.dom, {tag: 'div', unselectable: 'on', cls: 'yunselectable ylayout-panel-hd ylayout-title-'+this.position, children:[
10752         {tag: 'span', cls: 'yunselectable ylayout-panel-hd-text', unselectable: 'on', html: '&#160;'},
10753         {tag: 'div', cls: 'yunselectable ylayout-panel-hd-tools', unselectable: 'on'}
10754     ]}, true);
10755     this.titleEl.enableDisplayMode();
10756     
10757     this.titleTextEl = this.titleEl.dom.firstChild;
10758     this.tools = getEl(this.titleEl.dom.childNodes[1], true);
10759     this.closeBtn = this.createTool(this.tools.dom, 'ylayout-close');
10760     this.closeBtn.enableDisplayMode();
10761     this.closeBtn.on('click', this.closeClicked, this, true);
10762     this.closeBtn.hide();
10763     
10764     this.bodyEl = dh.append(this.el.dom, {tag: 'div', cls: 'ylayout-panel-body'}, true);
10765     this.events = {
10766         
10767         'beforeremove' : new YAHOO.util.CustomEvent('beforeremove'),
10768         
10769         'invalidated' : new YAHOO.util.CustomEvent('invalidated'),
10770         
10771         'visibilitychange' : new YAHOO.util.CustomEvent('visibilitychange'),
10772         
10773         'paneladded' : new YAHOO.util.CustomEvent('paneladded'),
10774         
10775         'panelremoved' : new YAHOO.util.CustomEvent('panelremoved'),
10776         
10777         'collapsed' : new YAHOO.util.CustomEvent('collapsed'),
10778         
10779         'expanded' : new YAHOO.util.CustomEvent('expanded'),
10780         
10781         'panelactivated' : new YAHOO.util.CustomEvent('panelactivated'),
10782         
10783         'resized' : new YAHOO.util.CustomEvent('resized')
10784     };
10785     
10786     this.panels = new YAHOO.ext.util.MixedCollection();
10787     this.panels.getKey = this.getPanelId.createDelegate(this);
10788     this.box = null;
10789     this.visible = false;
10790     this.collapsed = false;
10791     this.hide();
10792     this.on('paneladded', this.validateVisibility, this, true);
10793     this.on('panelremoved', this.validateVisibility, this, true);
10794     this.activePanel = null;
10795     
10796     this.applyConfig(config);
10797     
10798     
10799 };
10800
10801 YAHOO.extendX(YAHOO.ext.LayoutRegion, YAHOO.ext.util.Observable, {
10802     getPanelId : function(p){
10803         return p.getId();
10804     },
10805     
10806     applyConfig : function(config){
10807         if(config.collapsible && this.position != 'center' && !this.collapsedEl){
10808             var dh = YAHOO.ext.DomHelper;
10809             this.collapseBtn = this.createTool(this.tools.dom, 'ylayout-collapse-'+this.position);
10810             this.collapseBtn.mon('click', this.collapse, this, true);
10811             
10812             this.collapsedEl = dh.append(this.mgr.el.dom, {tag: 'div', cls: 'ylayout-collapsed ylayout-collapsed-'+this.position, children:[
10813                 {tag: 'div', cls: 'ylayout-collapsed-tools'}
10814             ]}, true);
10815             if(config.floatable !== false){
10816                this.collapsedEl.addClassOnOver('ylayout-collapsed-over');
10817                this.collapsedEl.mon('click', this.collapseClick, this, true);
10818             }
10819             this.expandBtn = this.createTool(this.collapsedEl.dom.firstChild, 'ylayout-expand-'+this.position);
10820             this.expandBtn.mon('click', this.expand, this, true);
10821         }
10822         if(this.collapseBtn){
10823             this.collapseBtn.setVisible(config.collapsible == true);
10824         }
10825         this.cmargins = config.cmargins || this.cmargins || 
10826                          (this.position == 'west' || this.position == 'east' ? 
10827                              {top: 0, left: 2, right:2, bottom: 0} : 
10828                              {top: 2, left: 0, right:0, bottom: 2});
10829         this.margins = config.margins || this.margins || {top: 0, left: 0, right:0, bottom: 0};
10830         this.bottomTabs = config.tabPosition != 'top';
10831         this.autoScroll = config.autoScroll || false;
10832         if(this.autoScroll){
10833             this.bodyEl.setStyle('overflow', 'auto');
10834         }else{
10835             this.bodyEl.setStyle('overflow', 'hidden');
10836         }
10837         if((!config.titlebar && !config.title) || config.titlebar === false){
10838             this.titleEl.hide();
10839         }else{
10840             this.titleEl.show();
10841             if(config.title){
10842                 this.titleTextEl.innerHTML = config.title;
10843             }
10844         }
10845         this.duration = config.duration || .30;
10846         this.slideDuration = config.slideDuration || .45;
10847         this.config = config;
10848         if(config.collapsed){
10849             this.collapse(true);
10850         }
10851     },
10852     
10853     
10854     resizeTo : function(newSize){
10855         switch(this.position){
10856             case 'east':
10857             case 'west':
10858                 this.el.setWidth(newSize);
10859                 this.fireEvent('resized', this, newSize);
10860             break;
10861             case 'north':
10862             case 'south':
10863                 this.el.setHeight(newSize);
10864                 this.fireEvent('resized', this, newSize);
10865             break;                
10866         }
10867     },
10868     
10869     getBox : function(){
10870         var b;
10871         if(!this.collapsed){
10872             b = this.el.getBox(false, true);
10873         }else{
10874             b = this.collapsedEl.getBox(false, true);
10875         }
10876         return b;
10877     },
10878     
10879     getMargins : function(){
10880         return this.collapsed ? this.cmargins : this.margins;
10881     },
10882     
10883     highlight : function(){
10884         this.el.addClass('ylayout-panel-dragover'); 
10885     },
10886     
10887     unhighlight : function(){
10888         this.el.removeClass('ylayout-panel-dragover'); 
10889     },
10890     
10891     updateBox : function(box){
10892         this.box = box;
10893         if(!this.collapsed){
10894             this.el.dom.style.left = box.x + 'px';
10895             this.el.dom.style.top = box.y + 'px';
10896             this.el.setSize(box.width, box.height);
10897             var bodyHeight = this.titleEl.isVisible() ? box.height - (this.titleEl.getHeight()||0) : box.height;
10898             bodyHeight -= this.el.getBorderWidth('tb');
10899             bodyWidth = box.width - this.el.getBorderWidth('rl');
10900             this.bodyEl.setHeight(bodyHeight);
10901             this.bodyEl.setWidth(bodyWidth);
10902             var tabHeight = bodyHeight;
10903             if(this.tabs){
10904                 tabHeight = this.tabs.syncHeight(bodyHeight);
10905                 if(YAHOO.ext.util.Browser.isIE) this.tabs.el.repaint();
10906             }
10907             this.panelSize = {width: bodyWidth, height: tabHeight};
10908             if(this.activePanel){
10909                 this.activePanel.setSize(bodyWidth, tabHeight);
10910             }
10911         }else{
10912             this.collapsedEl.dom.style.left = box.x + 'px';
10913             this.collapsedEl.dom.style.top = box.y + 'px';
10914             this.collapsedEl.setSize(box.width, box.height);
10915         }
10916         if(this.tabs){
10917             this.tabs.autoSizeTabs();
10918         }
10919     },
10920     
10921     
10922     getEl : function(){
10923         return this.el;
10924     },
10925     
10926     
10927     hide : function(){
10928         if(!this.collapsed){
10929             this.el.dom.style.left = '-2000px';
10930             this.el.hide();
10931         }else{
10932             this.collapsedEl.dom.style.left = '-2000px';
10933             this.collapsedEl.hide();
10934         }
10935         this.visible = false;
10936         this.fireEvent('visibilitychange', this, false);
10937     },
10938     
10939     
10940     show : function(){
10941         if(!this.collapsed){
10942             this.el.show();
10943         }else{
10944             this.collapsedEl.show();
10945         }
10946         this.visible = true;
10947         this.fireEvent('visibilitychange', this, true);
10948     },
10949     
10950     
10951     isVisible : function(){
10952         return this.visible;
10953     },
10954     
10955     closeClicked : function(){
10956         if(this.activePanel){
10957             this.remove(this.activePanel);
10958         }
10959     },
10960     
10961     collapseClick : function(e){
10962        if(this.isSlid){
10963            e.stopPropagation();
10964            this.slideIn();
10965        }else{
10966            e.stopPropagation();
10967            this.slideOut();
10968        }   
10969     },
10970     
10971     
10972     collapse : function(skipAnim){
10973         if(this.collapsed) return;
10974         this.collapsed = true;
10975         if(this.split){
10976             this.split.el.hide();
10977         }
10978         if(this.config.animate && skipAnim !== true){
10979             this.fireEvent('invalidated', this);    
10980             this.animateCollapse();
10981         }else{
10982             this.el.setLocation(-20000,-20000);
10983             this.el.hide();
10984             this.collapsedEl.show();
10985             this.fireEvent('collapsed', this);
10986             this.fireEvent('invalidated', this); 
10987         }
10988     },
10989     
10990     animateCollapse : function(){
10991         
10992     },
10993     
10994     
10995     expand : function(e, skipAnim){
10996         if(e) e.stopPropagation();
10997         if(!this.collapsed) return;
10998         if(this.isSlid){
10999             this.slideIn(this.expand.createDelegate(this));
11000             return;
11001         }
11002         this.collapsed = false;
11003         this.el.show();
11004         if(this.config.animate && skipAnim !== true){
11005             this.animateExpand();
11006         }else{
11007             if(this.split){
11008                 this.split.el.show();
11009             }
11010             this.collapsedEl.setLocation(-2000,-2000);
11011             this.collapsedEl.hide();
11012             this.fireEvent('invalidated', this);
11013             this.fireEvent('expanded', this);
11014         }
11015     },
11016     
11017     animateExpand : function(){
11018         
11019     },
11020     
11021     initTabs : function(){
11022         this.bodyEl.setStyle('overflow', 'hidden');
11023         var ts = new YAHOO.ext.TabPanel(this.bodyEl.dom, this.bottomTabs);
11024         this.tabs = ts;
11025         ts.resizeTabs = this.config.resizeTabs === true;
11026         ts.minTabWidth = this.config.minTabWidth || 40;
11027         ts.maxTabWidth = this.config.maxTabWidth || 250;
11028         ts.preferredTabWidth = this.config.preferredTabWidth || 150;
11029         ts.monitorResize = false;
11030         ts.bodyEl.setStyle('overflow', this.config.autoScroll ? 'auto' : 'hidden');
11031         this.panels.each(this.initPanelAsTab, this);
11032     },
11033     
11034     initPanelAsTab : function(panel){
11035         var ti = this.tabs.addTab(panel.getEl().id, panel.getTitle(), null, 
11036                     this.config.closeOnTab && panel.isClosable());
11037         ti.on('activate', function(){ 
11038               this.setActivePanel(panel); 
11039         }, this, true);
11040         if(this.config.closeOnTab){
11041             ti.on('beforeclose', function(t, e){
11042                 e.cancel = true;
11043                 this.remove(panel);
11044             }, this, true);
11045         }
11046         return ti;
11047     },
11048     
11049     updatePanelTitle : function(panel, title){
11050         if(this.activePanel == panel){
11051             this.updateTitle(title);
11052         }
11053         if(this.tabs){
11054             this.tabs.getTab(panel.getEl().id).setText(title);
11055         }
11056     },
11057     
11058     updateTitle : function(title){
11059         if(this.titleTextEl && !this.config.title){
11060             this.titleTextEl.innerHTML = (typeof title != 'undefined' && title.length > 0 ? title : "&#160;");
11061         }
11062     },
11063     
11064     setActivePanel : function(panel){
11065         panel = this.getPanel(panel);
11066         if(this.activePanel && this.activePanel != panel){
11067             this.activePanel.setActiveState(false);
11068         }
11069         this.activePanel = panel;
11070         panel.setActiveState(true);
11071         if(this.panelSize){
11072             panel.setSize(this.panelSize.width, this.panelSize.height);
11073         }
11074         this.closeBtn.setVisible(!this.config.closeOnTab && !this.isSlid && panel.isClosable());
11075         this.updateTitle(panel.getTitle());
11076         this.fireEvent('panelactivated', this, panel);
11077         
11078     },
11079     
11080     
11081     showPanel : function(panel){
11082         if(panel = this.getPanel(panel)){
11083             if(this.tabs){
11084                 this.tabs.activate(panel.getEl().id);
11085             }else{
11086                 this.setActivePanel(panel);
11087             }
11088         }
11089         return panel;
11090     },
11091     
11092     
11093     getActivePanel : function(){
11094         return this.activePanel;
11095     },
11096     
11097     validateVisibility : function(){
11098         if(this.panels.getCount() < 1){
11099             this.updateTitle('&#160;');
11100             this.closeBtn.hide();
11101             this.hide();
11102         }else{
11103             if(!this.isVisible()){
11104                 this.show();
11105             }
11106         }
11107     },
11108     
11109     
11110     add : function(panel){
11111         if(arguments.length > 1){
11112             for(var i = 0, len = arguments.length; i < len; i++) {
11113                 this.add(arguments[i]);
11114             }
11115             return null;
11116         }
11117         if(this.hasPanel(panel)){
11118             this.showPanel(panel);
11119             return panel;
11120         }
11121         panel.setRegion(this);
11122         this.panels.add(panel);
11123         if(this.panels.getCount() == 1 && !this.config.alwaysShowTabs){
11124             this.bodyEl.dom.appendChild(panel.getEl().dom);
11125             this.setActivePanel(panel);
11126             this.fireEvent('paneladded', this, panel);
11127             return panel;
11128         }
11129         if(!this.tabs){
11130             this.initTabs();
11131         }else{
11132             this.initPanelAsTab(panel);
11133         }
11134         this.tabs.activate(panel.getEl().id);
11135         this.fireEvent('paneladded', this, panel);
11136         return panel;
11137     },
11138     
11139     
11140     hasPanel : function(panel){
11141         if(typeof panel == 'object'){ 
11142             panel = panel.getId();
11143         }
11144         return this.getPanel(panel) ? true : false;
11145     },
11146     
11147     
11148     hidePanel : function(panel){
11149         if(this.tabs && (panel = this.getPanel(panel))){
11150             this.tabs.hideTab(panel.getEl().id);
11151         }
11152     },
11153     
11154     
11155     unhidePanel : function(panel){
11156         if(this.tabs && (panel = this.getPanel(panel))){
11157             this.tabs.unhideTab(panel.getEl().id);
11158         }
11159     },
11160     
11161     clearPanels : function(){
11162         while(this.panels.getCount() > 0){
11163              this.remove(this.panels.first());
11164         }
11165     },
11166     
11167     
11168     remove : function(panel, preservePanel){
11169         panel = this.getPanel(panel);
11170         if(!panel){
11171             return null;
11172         }
11173         var e = {};
11174         this.fireEvent('beforeremove', this, panel, e);
11175         if(e.cancel === true){
11176             return null;
11177         }
11178         preservePanel = (typeof preservePanel != 'undefined' ? preservePanel : (this.config.preservePanels === true || panel.preserve === true));
11179         var panelId = panel.getId();
11180         this.panels.removeKey(panelId);
11181         if(preservePanel){
11182             document.body.appendChild(panel.getEl().dom);
11183         }
11184         if(this.tabs){
11185             this.tabs.removeTab(panel.getEl().id);
11186         }else if (!preservePanel){
11187             this.bodyEl.dom.removeChild(panel.getEl().dom);
11188         }
11189         if(this.panels.getCount() == 1 && this.tabs && !this.config.alwaysShowTabs){
11190             var p = this.panels.first();
11191             var tempEl = document.createElement('span'); 
11192             tempEl.appendChild(p.getEl().dom);
11193             this.bodyEl.update('');
11194             this.bodyEl.dom.appendChild(p.getEl().dom);
11195             tempEl = null;
11196             this.updateTitle(p.getTitle());
11197             this.tabs = null;
11198             this.bodyEl.setStyle('overflow', this.config.autoScroll ? 'auto' : 'hidden');
11199             this.setActivePanel(p);
11200         }
11201         panel.setRegion(null);
11202         if(this.activePanel == panel){
11203             this.activePanel = null;
11204         }
11205         if(this.config.autoDestroy !== false && preservePanel !== true){
11206             try{panel.destroy();}catch(e){}
11207         }
11208         this.fireEvent('panelremoved', this, panel);
11209         return panel;
11210     },
11211     
11212     
11213     getTabs : function(){
11214         return this.tabs;    
11215     },
11216     
11217     
11218     getPanel : function(id){
11219         if(typeof id == 'object'){ 
11220             return id;
11221         }
11222         return this.panels.get(id);
11223     },
11224     
11225     
11226     getPosition: function(){
11227         return this.position;    
11228     },
11229     
11230     createTool : function(parentEl, className){
11231         var btn = YAHOO.ext.DomHelper.append(parentEl, {tag: 'div', cls: 'ylayout-tools-button', 
11232             children: [{tag: 'div', cls: 'ylayout-tools-button-inner ' + className, html: '&#160;'}]}, true);
11233         btn.addClassOnOver('ylayout-tools-button-over');
11234         return btn;
11235     }
11236 });
11237
11238 YAHOO.ext.SplitLayoutRegion = function(mgr, config, pos, cursor){
11239     this.cursor = cursor;
11240     YAHOO.ext.SplitLayoutRegion.superclass.constructor.call(this, mgr, config, pos);
11241     if(config.split){
11242         this.hide();
11243     }
11244 };
11245
11246 YAHOO.extendX(YAHOO.ext.SplitLayoutRegion, YAHOO.ext.LayoutRegion, {
11247     applyConfig : function(config){
11248         YAHOO.ext.SplitLayoutRegion.superclass.applyConfig.call(this, config);
11249         if(config.split){
11250             if(!this.split){
11251                 var splitEl = YAHOO.ext.DomHelper.append(this.mgr.el.dom, 
11252                         {tag: 'div', id: this.el.id + '-split', cls: 'ylayout-split ylayout-split-'+this.position, html: '&#160;'});
11253                 
11254                 this.split = new YAHOO.ext.SplitBar(splitEl, this.el);
11255                 this.split.onMoved.subscribe(this.onSplitMove, this, true);
11256                 this.split.useShim = config.useShim === true;
11257                 YAHOO.util.Dom.setStyle([this.split.el.dom, this.split.proxy], 'cursor', this.cursor);
11258                 this.split.getMaximumSize = this.getMaxSize.createDelegate(this);
11259             }
11260             if(typeof config.minSize != 'undefined'){
11261                 this.split.minSize = config.minSize;
11262             }
11263             if(typeof config.maxSize != 'undefined'){
11264                 this.split.maxSize = config.maxSize;
11265             }
11266         }
11267     },
11268     
11269     getMaxSize : function(){
11270          var cmax = this.config.maxSize || 10000;
11271          var center = this.mgr.getRegion('center');
11272          return Math.min(cmax, (this.el.getWidth()+center.getEl().getWidth())-center.getMinWidth());
11273     },
11274     
11275     onSplitMove : function(split, newSize){
11276         this.fireEvent('resized', this, newSize);
11277     },
11278     
11279     
11280     getSplitBar : function(){
11281         return this.split;
11282     },
11283     
11284     hide : function(){
11285         if(this.split){
11286             this.split.el.setLocation(-2000,-2000);
11287             this.split.el.hide();
11288         }
11289         YAHOO.ext.SplitLayoutRegion.superclass.hide.call(this);
11290     },
11291     
11292     show : function(){
11293         if(this.split){
11294             this.split.el.show();
11295         }
11296         YAHOO.ext.SplitLayoutRegion.superclass.show.call(this);
11297     },
11298     
11299     beforeSlide: function(){
11300         if(YAHOO.ext.util.Browser.isGecko){
11301             this.bodyEl.clip();
11302             if(this.tabs) this.tabs.bodyEl.clip();
11303             if(this.activePanel){
11304                 this.activePanel.getEl().clip();
11305                 
11306                 if(this.activePanel.beforeSlide){
11307                     this.activePanel.beforeSlide();
11308                 }
11309             }
11310         }
11311     },
11312     
11313     afterSlide : function(){
11314         if(YAHOO.ext.util.Browser.isGecko){
11315             this.bodyEl.unclip();
11316             if(this.tabs) this.tabs.bodyEl.unclip();
11317             if(this.activePanel){
11318                 this.activePanel.getEl().unclip();
11319                 if(this.activePanel.afterSlide){
11320                     this.activePanel.afterSlide();
11321                 }
11322             }
11323         }
11324     },
11325     
11326     slideOut : function(){
11327         if(!this.slideEl){
11328             this.slideEl = new YAHOO.ext.Actor(
11329                 YAHOO.ext.DomHelper.append(this.mgr.el.dom, {tag: 'div', cls:'ylayout-slider'}));
11330             if(this.config.autoHide !== false){
11331                 var slideInTask = new YAHOO.ext.util.DelayedTask(this.slideIn, this);
11332                 this.slideEl.mon('mouseout', function(e){
11333                     var to = e.getRelatedTarget();
11334                     if(to && to != this.slideEl.dom && !YAHOO.util.Dom.isAncestor(this.slideEl.dom, to)){
11335                         slideInTask.delay(500);
11336                     }
11337                 }, this, true);
11338                 this.slideEl.mon('mouseover', function(e){
11339                     slideInTask.cancel();
11340                 }, this, true);
11341             }
11342         }
11343         var sl = this.slideEl, c = this.collapsedEl, cm = this.cmargins;
11344         this.isSlid = true;
11345         this.snapshot = {
11346             'left': this.el.getLeft(true),
11347             'top': this.el.getTop(true),
11348             'colbtn': this.collapseBtn.isVisible(),
11349             'closebtn': this.closeBtn.isVisible()
11350         };
11351         this.collapseBtn.hide();
11352         this.closeBtn.hide();
11353         this.el.show();
11354         this.el.setLeftTop(0,0);
11355         sl.startCapture(true);
11356         var size;
11357         switch(this.position){
11358             case 'west':
11359                 sl.setLeft(c.getRight(true));
11360                 sl.setTop(c.getTop(true));
11361                 size = this.el.getWidth();
11362             break;
11363             case 'east':
11364                 sl.setRight(this.mgr.getViewSize().width-c.getLeft(true));
11365                 sl.setTop(c.getTop(true));
11366                 size = this.el.getWidth();
11367             break;
11368             case 'north':
11369                 sl.setLeft(c.getLeft(true));
11370                 sl.setTop(c.getBottom(true));
11371                 size = this.el.getHeight();
11372             break;
11373             case 'south':
11374                 sl.setLeft(c.getLeft(true));
11375                 sl.setBottom(this.mgr.getViewSize().height-c.getTop(true));
11376                 size = this.el.getHeight();
11377             break;
11378         }
11379         sl.dom.appendChild(this.el.dom);
11380         YAHOO.util.Event.on(document.body, 'click', this.slideInIf, this, true);
11381         sl.setSize(this.el.getWidth(), this.el.getHeight());
11382         this.beforeSlide();
11383         if(this.activePanel){
11384             this.activePanel.setSize(this.bodyEl.getWidth(), this.bodyEl.getHeight());
11385         }
11386         sl.slideShow(this.getAnchor(), size, this.slideDuration, null, false);
11387         sl.play(function(){
11388             this.afterSlide();
11389         }.createDelegate(this));
11390     },
11391     
11392     slideInIf : function(e){
11393         var t = YAHOO.util.Event.getTarget(e);
11394         if(!YAHOO.util.Dom.isAncestor(this.el.dom, t)){
11395             this.slideIn();
11396         }
11397     },
11398     
11399     slideIn : function(callback){
11400         if(this.isSlid && !this.slideEl.playlist.isPlaying()){
11401             YAHOO.util.Event.removeListener(document.body, 'click', this.slideInIf, this, true);
11402             this.slideEl.startCapture(true);
11403             this.slideEl.slideHide(this.getAnchor(), this.slideDuration, null);
11404             this.beforeSlide();
11405             this.slideEl.play(function(){
11406                 this.isSlid = false;
11407                 this.el.setPositioning(this.snapshot);
11408                 this.collapseBtn.setVisible(this.snapshot.colbtn);
11409                 this.closeBtn.setVisible(this.snapshot.closebtn);
11410                 this.afterSlide();
11411                 this.mgr.el.dom.appendChild(this.el.dom);
11412                 if(typeof callback == 'function'){
11413                     callback();
11414                 }
11415             }.createDelegate(this));
11416         }
11417     },
11418     
11419     animateExpand : function(){
11420         var em = this.margins, cm = this.cmargins;
11421         var c = this.collapsedEl, el = this.el;
11422         var direction, distance;
11423         switch(this.position){
11424             case 'west':
11425                 direction = 'right';
11426                 el.setLeft(-(el.getWidth() + (em.right+em.left)));
11427                 el.setTop(c.getTop(true)-cm.top+em.top);
11428                 distance = el.getWidth() + (em.right+em.left);
11429             break;
11430             case 'east':
11431                 direction = 'left';
11432                 el.setLeft(this.mgr.getViewSize().width + em.left);
11433                 el.setTop(c.getTop(true)-cm.top+em.top);
11434                 distance = el.getWidth() + (em.right+em.left);
11435             break;
11436             case 'north':
11437                 direction = 'down';
11438                 el.setLeft(em.left);
11439                 el.setTop(-(el.getHeight() + (em.top+em.bottom)));
11440                 distance = el.getHeight() + (em.top+em.bottom);
11441             break;
11442             case 'south':
11443                 direction = 'up';
11444                 el.setLeft(em.left);
11445                 el.setTop(this.mgr.getViewSize().height + em.top);
11446                 distance = el.getHeight() + (em.top+em.bottom);
11447             break;
11448         }
11449         this.beforeSlide();
11450         el.setStyle('z-index', '100');
11451         el.show();
11452         c.setLocation(-2000,-2000);
11453         c.hide();
11454         el.move(direction, distance, true, this.duration, function(){
11455             this.afterSlide();
11456             el.setStyle('z-index', '');
11457             if(this.split){
11458                 this.split.el.show();
11459             }
11460             this.fireEvent('invalidated', this);
11461             this.fireEvent('expanded', this);
11462         }.createDelegate(this), this.config.easing || YAHOO.util.Easing.easeOut);
11463     },
11464     
11465     animateCollapse : function(){
11466         var em = this.margins, cm = this.cmargins;
11467         var c = this.collapsedEl, el = this.el;
11468         var direction, distance;
11469         switch(this.position){
11470             case 'west':
11471                 direction = 'left';
11472                 distance = el.getWidth() + (em.right+em.left);
11473             break;
11474             case 'east':
11475                 direction = 'right';
11476                 distance = el.getWidth() + (em.right+em.left);
11477             break;
11478             case 'north':
11479                 direction = 'up';
11480                 distance = el.getHeight() + (em.top+em.bottom);
11481             break;
11482             case 'south':
11483                 direction = 'down';
11484                 distance = el.getHeight() + (em.top+em.bottom);
11485             break;
11486         }
11487         this.el.setStyle('z-index', '100');
11488         this.beforeSlide();
11489         this.el.move(direction, distance, true, this.duration, function(){
11490             this.afterSlide();
11491             this.el.setStyle('z-index', '');
11492             this.el.setLocation(-20000,-20000);
11493             this.el.hide();
11494             this.collapsedEl.show();
11495             this.fireEvent('collapsed', this); 
11496         }.createDelegate(this), YAHOO.util.Easing.easeIn);
11497     },
11498     
11499     getAnchor : function(){
11500         switch(this.position){
11501             case 'west':
11502                 return 'left';
11503             case 'east':
11504                 return 'right';
11505             case 'north':
11506                 return 'top';
11507             case 'south':
11508                 return 'bottom';
11509         }
11510     }
11511 });
11512
11513 YAHOO.ext.BorderLayout = function(container, config){
11514     YAHOO.ext.BorderLayout.superclass.constructor.call(this, container);
11515     this.factory = config.factory || YAHOO.ext.BorderLayout.RegionFactory;
11516     
11517     this.hideOnLayout = config.hideOnLayout || false;
11518     for(var i = 0, len = this.factory.validRegions.length; i < len; i++) {
11519         var target = this.factory.validRegions[i];
11520         if(config[target]){
11521             this.addRegion(target, config[target]);
11522         }
11523     }
11524     
11525 };
11526
11527 YAHOO.extendX(YAHOO.ext.BorderLayout, YAHOO.ext.LayoutManager, {
11528     
11529     addRegion : function(target, config){
11530         if(!this.regions[target]){
11531             var r = this.factory.create(target, this, config);
11532             this.regions[target] = r;
11533             r.on('visibilitychange', this.layout, this, true);
11534             r.on('paneladded', this.layout, this, true);
11535             r.on('panelremoved', this.layout, this, true);
11536             r.on('invalidated', this.layout, this, true);
11537             r.on('resized', this.onRegionResized, this, true);
11538             r.on('collapsed', this.onRegionCollapsed, this, true);
11539             r.on('expanded', this.onRegionExpanded, this, true);
11540         }
11541         return this.regions[target];
11542     },
11543     
11544     
11545     layout : function(){
11546         if(this.updating) return;
11547         
11548             
11549         var size = this.getViewSize();
11550         var w = size.width, h = size.height;
11551         var centerW = w, centerH = h, centerY = 0, centerX = 0;
11552         var x = 0, y = 0;
11553         
11554         var rs = this.regions;
11555         var n = rs['north'], s = rs['south'], west = rs['west'], e = rs['east'], c = rs['center'];
11556         if(this.hideOnLayout){
11557             c.el.setStyle('display', 'none');
11558         }
11559         if(n && n.isVisible()){
11560             var b = n.getBox();
11561             var m = n.getMargins();
11562             b.width = w - (m.left+m.right);
11563             b.x = m.left;
11564             b.y = m.top;
11565             centerY = b.height + b.y + m.bottom;
11566             centerH -= centerY;
11567             n.updateBox(this.safeBox(b));
11568         }
11569         if(s && s.isVisible()){
11570             var b = s.getBox();
11571             var m = s.getMargins();
11572             b.width = w - (m.left+m.right);
11573             b.x = m.left;
11574             var totalHeight = (b.height + m.top + m.bottom);
11575             b.y = h - totalHeight + m.top;
11576             centerH -= totalHeight;
11577             s.updateBox(this.safeBox(b));
11578         }
11579         if(west && west.isVisible()){
11580             var b = west.getBox();
11581             var m = west.getMargins();
11582             b.height = centerH - (m.top+m.bottom);
11583             b.x = m.left;
11584             b.y = centerY + m.top;
11585             var totalWidth = (b.width + m.left + m.right);
11586             centerX += totalWidth;
11587             centerW -= totalWidth;
11588             west.updateBox(this.safeBox(b));
11589         }
11590         if(e && e.isVisible()){
11591             var b = e.getBox();
11592             var m = e.getMargins();
11593             b.height = centerH - (m.top+m.bottom);
11594             var totalWidth = (b.width + m.left + m.right);
11595             b.x = w - totalWidth + m.left;
11596             b.y = centerY + m.top;
11597             centerW -= totalWidth;
11598             e.updateBox(this.safeBox(b));
11599         }
11600         if(c){
11601             var m = c.getMargins();
11602             var centerBox = {
11603                 x: centerX + m.left,
11604                 y: centerY + m.top,
11605                 width: centerW - (m.left+m.right),
11606                 height: centerH - (m.top+m.bottom)
11607             };
11608             if(this.hideOnLayout){
11609                 c.el.setStyle('display', 'block');
11610             }
11611             c.updateBox(this.safeBox(centerBox));
11612         }
11613         this.el.repaint();
11614         this.fireEvent('layout', this);
11615         
11616             
11617     },
11618     
11619     safeBox : function(box){
11620         box.width = Math.max(0, box.width);
11621         box.height = Math.max(0, box.height);
11622         return box;
11623     },
11624     
11625     
11626     add : function(target, panel){
11627         target = target.toLowerCase();
11628         return this.regions[target].add(panel);
11629     },
11630     
11631     
11632     remove : function(target, panel){
11633         target = target.toLowerCase();
11634         return this.regions[target].remove(panel);
11635     },
11636     
11637     
11638     findPanel : function(panelId){
11639         var rs = this.regions;
11640         for(var target in rs){
11641             if(typeof rs[target] != 'function'){
11642                 var p = rs[target].getPanel(panelId);
11643                 if(p){
11644                     return p;
11645                 }
11646             }
11647         }
11648         return null;
11649     },
11650     
11651     
11652     showPanel : function(panelId) {
11653       var rs = this.regions;
11654       for(var target in rs){
11655          var r = rs[target];
11656          if(typeof r != 'function'){
11657             if(r.hasPanel(panelId)){
11658                return r.showPanel(panelId);
11659             }
11660          }
11661       }
11662       return null;
11663    },
11664    
11665    
11666     restoreState : function(provider){
11667         if(!provider){
11668             provider = YAHOO.ext.state.Manager;
11669         }
11670         var sm = new YAHOO.ext.LayoutStateManager();
11671         sm.init(this, provider);
11672     }
11673 });
11674
11675 YAHOO.ext.BorderLayout.RegionFactory = {};
11676 YAHOO.ext.BorderLayout.RegionFactory.validRegions = ['north','south','east','west','center'];
11677 YAHOO.ext.BorderLayout.RegionFactory.create = function(target, mgr, config){
11678     if(config.lightweight){
11679         return new YAHOO.ext.LayoutRegionLite(mgr, config);
11680     }
11681     target = target.toLowerCase();
11682     switch(target){
11683         case 'north':
11684             return new YAHOO.ext.NorthLayoutRegion(mgr, config);
11685         case 'south':
11686             return new YAHOO.ext.SouthLayoutRegion(mgr, config);
11687         case 'east':
11688             return new YAHOO.ext.EastLayoutRegion(mgr, config);
11689         case 'west':
11690             return new YAHOO.ext.WestLayoutRegion(mgr, config);
11691         case 'center':
11692             return new YAHOO.ext.CenterLayoutRegion(mgr, config);
11693     }
11694     throw 'Layout region "'+target+'" not supported.';
11695 };
11696
11697 YAHOO.ext.CenterLayoutRegion = function(mgr, config){
11698     YAHOO.ext.CenterLayoutRegion.superclass.constructor.call(this, mgr, config, 'center');
11699     this.visible = true;
11700     this.minWidth = config.minWidth || 20;
11701     this.minHeight = config.minHeight || 20;
11702 };
11703
11704 YAHOO.extendX(YAHOO.ext.CenterLayoutRegion, YAHOO.ext.LayoutRegion, {
11705     hide : function(){
11706         
11707     },
11708     
11709     show : function(){
11710         
11711     },
11712     
11713     getMinWidth: function(){
11714         return this.minWidth;
11715     },
11716     
11717     getMinHeight: function(){
11718         return this.minHeight;
11719     }
11720 });
11721
11722
11723 YAHOO.ext.NorthLayoutRegion = function(mgr, config){
11724     YAHOO.ext.NorthLayoutRegion.superclass.constructor.call(this, mgr, config, 'north', 'n-resize');
11725     if(this.split){
11726         this.split.placement = YAHOO.ext.SplitBar.TOP;
11727         this.split.orientation = YAHOO.ext.SplitBar.VERTICAL;
11728         this.split.el.addClass('ylayout-split-v');
11729     }
11730     if(typeof config.initialSize != 'undefined'){
11731         this.el.setHeight(config.initialSize);
11732     }
11733 };
11734 YAHOO.extendX(YAHOO.ext.NorthLayoutRegion, YAHOO.ext.SplitLayoutRegion, {
11735     getBox : function(){
11736         if(this.collapsed){
11737             return this.collapsedEl.getBox();
11738         }
11739         var box = this.el.getBox();
11740         if(this.split){
11741             box.height += this.split.el.getHeight();
11742         }
11743         return box;
11744     },
11745     
11746     updateBox : function(box){
11747         if(this.split && !this.collapsed){
11748             box.height -= this.split.el.getHeight();
11749             this.split.el.setLeft(box.x);
11750             this.split.el.setTop(box.y+box.height);
11751             this.split.el.setWidth(box.width);
11752         }
11753         if(this.collapsed){
11754             this.el.setWidth(box.width);
11755             var bodyWidth = box.width - this.el.getBorderWidth('rl');
11756             this.bodyEl.setWidth(bodyWidth);
11757             if(this.activePanel && this.panelSize){
11758                 this.activePanel.setSize(bodyWidth, this.panelSize.height);
11759             }
11760         }
11761         YAHOO.ext.NorthLayoutRegion.superclass.updateBox.call(this, box);
11762     }
11763 });
11764
11765 YAHOO.ext.SouthLayoutRegion = function(mgr, config){
11766     YAHOO.ext.SouthLayoutRegion.superclass.constructor.call(this, mgr, config, 'south', 's-resize');
11767     if(this.split){
11768         this.split.placement = YAHOO.ext.SplitBar.BOTTOM;
11769         this.split.orientation = YAHOO.ext.SplitBar.VERTICAL;
11770         this.split.el.addClass('ylayout-split-v');
11771     }
11772     if(typeof config.initialSize != 'undefined'){
11773         this.el.setHeight(config.initialSize);
11774     }
11775 };
11776 YAHOO.extendX(YAHOO.ext.SouthLayoutRegion, YAHOO.ext.SplitLayoutRegion, {
11777     getBox : function(){
11778         if(this.collapsed){
11779             return this.collapsedEl.getBox();
11780         }
11781         var box = this.el.getBox();
11782         if(this.split){
11783             var sh = this.split.el.getHeight();
11784             box.height += sh;
11785             box.y -= sh;
11786         }
11787         return box;
11788     },
11789     
11790     updateBox : function(box){
11791         if(this.split && !this.collapsed){
11792             var sh = this.split.el.getHeight();
11793             box.height -= sh;
11794             box.y += sh;
11795             this.split.el.setLeft(box.x);
11796             this.split.el.setTop(box.y-sh);
11797             this.split.el.setWidth(box.width);
11798         }
11799         if(this.collapsed){
11800             this.el.setWidth(box.width);
11801             var bodyWidth = box.width - this.el.getBorderWidth('rl');
11802             this.bodyEl.setWidth(bodyWidth);
11803             if(this.activePanel && this.panelSize){
11804                 this.activePanel.setSize(bodyWidth, this.panelSize.height);
11805             }
11806         }
11807         YAHOO.ext.SouthLayoutRegion.superclass.updateBox.call(this, box);
11808     }
11809 });
11810
11811 YAHOO.ext.EastLayoutRegion = function(mgr, config){
11812     YAHOO.ext.EastLayoutRegion.superclass.constructor.call(this, mgr, config, 'east', 'e-resize');
11813     if(this.split){
11814         this.split.placement = YAHOO.ext.SplitBar.RIGHT;
11815         this.split.orientation = YAHOO.ext.SplitBar.HORIZONTAL;
11816         this.split.el.addClass('ylayout-split-h');
11817     }
11818     if(typeof config.initialSize != 'undefined'){
11819         this.el.setWidth(config.initialSize);
11820     }
11821 };
11822 YAHOO.extendX(YAHOO.ext.EastLayoutRegion, YAHOO.ext.SplitLayoutRegion, {
11823     getBox : function(){
11824         if(this.collapsed){
11825             return this.collapsedEl.getBox();
11826         }
11827         var box = this.el.getBox();
11828         if(this.split){
11829             var sw = this.split.el.getWidth();
11830             box.width += sw;
11831             box.x -= sw;
11832         }
11833         return box;
11834     },
11835     
11836     updateBox : function(box){
11837         if(this.split && !this.collapsed){
11838             var sw = this.split.el.getWidth();
11839             box.width -= sw;
11840             this.split.el.setLeft(box.x);
11841             this.split.el.setTop(box.y);
11842             this.split.el.setHeight(box.height);
11843             box.x += sw;
11844         }
11845         if(this.collapsed){
11846             this.el.setHeight(box.height);
11847             var bodyHeight = this.config.titlebar ? box.height - (this.titleEl.getHeight()||0) : box.height;
11848             bodyHeight -= this.el.getBorderWidth('tb');
11849             this.bodyEl.setHeight(bodyHeight);
11850             if(this.activePanel && this.panelSize){
11851                 this.activePanel.setSize(this.panelSize.width, bodyHeight);
11852             }
11853         }
11854         YAHOO.ext.EastLayoutRegion.superclass.updateBox.call(this, box);
11855     }
11856 });
11857
11858 YAHOO.ext.WestLayoutRegion = function(mgr, config){
11859     YAHOO.ext.WestLayoutRegion.superclass.constructor.call(this, mgr, config, 'west', 'w-resize');
11860     if(this.split){
11861         this.split.placement = YAHOO.ext.SplitBar.LEFT;
11862         this.split.orientation = YAHOO.ext.SplitBar.HORIZONTAL;
11863         this.split.el.addClass('ylayout-split-h');
11864     }
11865     if(typeof config.initialSize != 'undefined'){
11866         this.el.setWidth(config.initialSize);
11867     }
11868 };
11869 YAHOO.extendX(YAHOO.ext.WestLayoutRegion, YAHOO.ext.SplitLayoutRegion, {
11870     getBox : function(){
11871         if(this.collapsed){
11872             return this.collapsedEl.getBox();
11873         }
11874         var box = this.el.getBox();
11875         if(this.split){
11876             box.width += this.split.el.getWidth();
11877         }
11878         return box;
11879     },
11880     
11881     updateBox : function(box){
11882         if(this.split && !this.collapsed){
11883             var sw = this.split.el.getWidth();
11884             box.width -= sw;
11885             this.split.el.setLeft(box.x+box.width);
11886             this.split.el.setTop(box.y);
11887             this.split.el.setHeight(box.height);
11888         }
11889         if(this.collapsed){
11890             this.el.setHeight(box.height);
11891             var bodyHeight = this.config.titlebar ? box.height - (this.titleEl.getHeight()||0) : box.height;
11892             bodyHeight -= this.el.getBorderWidth('tb');
11893             this.bodyEl.setHeight(bodyHeight);
11894             if(this.activePanel && this.panelSize){
11895                 this.activePanel.setSize(this.panelSize.width, bodyHeight);
11896             }
11897         }
11898         YAHOO.ext.WestLayoutRegion.superclass.updateBox.call(this, box);
11899     }
11900 });
11901
11902
11903 YAHOO.ext.ContentPanel = function(el, config, content){
11904     YAHOO.ext.ContentPanel.superclass.constructor.call(this);
11905     this.el = getEl(el, true);
11906     if(!this.el && config && config.autoCreate){
11907         if(typeof config.autoCreate == 'object'){
11908             if(!config.autoCreate.id){
11909                 config.autoCreate.id = el;
11910             }
11911             this.el = YAHOO.ext.DomHelper.append(document.body,
11912                         config.autoCreate, true);
11913         }else{
11914             this.el = YAHOO.ext.DomHelper.append(document.body,
11915                         {tag: 'div', cls: 'ylayout-inactive-content', id: el}, true);
11916         }
11917     }
11918     this.closable = false;
11919     this.loaded = false;
11920     this.active = false;
11921     if(typeof config == 'string'){
11922         this.title = config;
11923     }else{
11924         YAHOO.ext.util.Config.apply(this, config);
11925     }
11926     if(this.resizeEl){
11927         this.resizeEl = getEl(this.resizeEl, true);
11928     }else{
11929         this.resizeEl = this.el;
11930     }
11931     this.events = {
11932         
11933         'activate' : new YAHOO.util.CustomEvent('activate'),
11934         
11935         'deactivate' : new YAHOO.util.CustomEvent('deactivate') 
11936     };
11937     if(this.autoScroll){
11938         this.el.setStyle('overflow', 'auto');
11939     }
11940     if(content){
11941         this.setContent(content);
11942     }
11943 };
11944
11945 YAHOO.extendX(YAHOO.ext.ContentPanel, YAHOO.ext.util.Observable, {
11946     setRegion : function(region){
11947         this.region = region;
11948         if(region){
11949            this.el.replaceClass('ylayout-inactive-content', 'ylayout-active-content'); 
11950         }else{
11951            this.el.replaceClass('ylayout-active-content', 'ylayout-inactive-content'); 
11952         } 
11953     },
11954     
11955     
11956     getToolbar : function(){
11957         return this.toolbar;
11958     },
11959     
11960     setActiveState : function(active){
11961         this.active = active;
11962         if(!active){
11963             this.fireEvent('deactivate', this);
11964         }else{
11965             this.fireEvent('activate', this);
11966         }
11967     },
11968     
11969     setContent : function(content, loadScripts){
11970         this.el.update(content, loadScripts);
11971     },
11972     
11973     
11974     getUpdateManager : function(){
11975         return this.el.getUpdateManager();
11976     },
11977     
11978     
11979     setUrl : function(url, params, loadOnce){
11980         if(this.refreshDelegate){
11981             this.removeListener('activate', this.refreshDelegate);
11982         }
11983         this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
11984         this.on('activate', this._handleRefresh.createDelegate(this, [url, params, loadOnce]));
11985         return this.el.getUpdateManager();
11986     },
11987     
11988     _handleRefresh : function(url, params, loadOnce){
11989         if(!loadOnce || !this.loaded){
11990             var updater = this.el.getUpdateManager();
11991             updater.update(url, params, this._setLoaded.createDelegate(this));
11992         }
11993     },
11994     
11995     _setLoaded : function(){
11996         this.loaded = true;
11997     }, 
11998     
11999     
12000     getId : function(){
12001         return this.el.id;
12002     },
12003     
12004     
12005     getEl : function(){
12006         return this.el;
12007     },
12008     
12009     adjustForComponents : function(width, height){
12010         if(this.toolbar){
12011             var te = this.toolbar.getEl();
12012             height -= te.getHeight();
12013             te.setWidth(width);
12014         }
12015         if(this.adjustments){
12016             width += this.adjustments[0];
12017             height += this.adjustments[1];
12018         }
12019         return {'width': width, 'height': height};
12020     },
12021     
12022     setSize : function(width, height){
12023         if(this.fitToFrame){
12024             var size = this.adjustForComponents(width, height);
12025             this.resizeEl.setSize(this.autoWidth ? 'auto' : size.width, size.height);
12026         }
12027     },
12028     
12029     
12030     getTitle : function(){
12031         return this.title;
12032     },
12033     
12034     
12035     setTitle : function(title){
12036         this.title = title;
12037         if(this.region){
12038             this.region.updatePanelTitle(this, title);
12039         }
12040     },
12041     
12042     
12043     isClosable : function(){
12044         return this.closable;
12045     },
12046     
12047     beforeSlide : function(){
12048         this.el.clip();
12049         this.resizeEl.clip();
12050     },
12051     
12052     afterSlide : function(){
12053         this.el.unclip();
12054         this.resizeEl.unclip();
12055     },
12056     
12057     
12058     refresh : function(){
12059         if(this.refreshDelegate){
12060            this.loaded = false;
12061            this.refreshDelegate();
12062         }
12063     },
12064     
12065     
12066     destroy : function(){
12067         this.el.removeAllListeners();
12068         var tempEl = document.createElement('span');
12069         tempEl.appendChild(this.el.dom);
12070         tempEl.innerHTML = '';
12071         this.el = null;
12072     }
12073 });
12074
12075
12076 YAHOO.ext.GridPanel = function(grid, config){
12077     this.wrapper = YAHOO.ext.DomHelper.append(document.body, 
12078         {tag: 'div', cls: 'ylayout-grid-wrapper ylayout-inactive-content'}, true);
12079     this.wrapper.dom.appendChild(grid.container.dom);
12080     YAHOO.ext.GridPanel.superclass.constructor.call(this, this.wrapper, config);
12081     if(this.toolbar){
12082         this.toolbar.el.insertBefore(this.wrapper.dom.firstChild);
12083     }
12084     grid.monitorWindowResize = false; 
12085     grid.autoHeight = false;
12086     grid.autoWidth = false;
12087     this.grid = grid;
12088     this.grid.container.replaceClass('ylayout-inactive-content', 'ylayout-component-panel');
12089 };
12090
12091 YAHOO.extendX(YAHOO.ext.GridPanel, YAHOO.ext.ContentPanel, {
12092     getId : function(){
12093         return this.grid.id;
12094     },
12095     
12096     
12097     getGrid : function(){
12098         return this.grid;    
12099     },
12100     
12101     setSize : function(width, height){
12102         var grid = this.grid;
12103         var size = this.adjustForComponents(width, height);
12104         grid.container.setSize(size.width, size.height);
12105         grid.autoSize();
12106     },
12107     
12108     beforeSlide : function(){
12109         this.grid.getView().wrapEl.clip();
12110     },
12111     
12112     afterSlide : function(){
12113         this.grid.getView().wrapEl.unclip();
12114     },
12115     
12116     destroy : function(){
12117         this.grid.getView().unplugDataModel(this.grid.getDataModel());
12118         this.grid.container.removeAllListeners();
12119         YAHOO.ext.GridPanel.superclass.destroy.call(this);
12120     }
12121 });
12122
12123
12124
12125 YAHOO.ext.NestedLayoutPanel = function(layout, config){
12126     YAHOO.ext.NestedLayoutPanel.superclass.constructor.call(this, layout.getEl(), config);
12127     layout.monitorWindowResize = false; 
12128     this.layout = layout;
12129     this.layout.getEl().addClass('ylayout-nested-layout');
12130 };
12131
12132 YAHOO.extendX(YAHOO.ext.NestedLayoutPanel, YAHOO.ext.ContentPanel, {
12133     setSize : function(width, height){
12134         var size = this.adjustForComponents(width, height);
12135         this.layout.getEl().setSize(size.width, size.height);
12136         this.layout.layout();
12137     },
12138     
12139     
12140     getLayout : function(){
12141         return this.layout;
12142     }
12143 });
12144
12145 YAHOO.ext.LayoutStateManager = function(layout){
12146      
12147      this.state = {
12148         north: {},
12149         south: {},
12150         east: {},
12151         west: {}       
12152     };
12153 };
12154
12155 YAHOO.ext.LayoutStateManager.prototype = {
12156     init : function(layout, provider){
12157         this.provider = provider;
12158         var state = provider.get(layout.id+'-layout-state');
12159         if(state){
12160             var wasUpdating = layout.isUpdating();
12161             if(!wasUpdating){
12162                 layout.beginUpdate();
12163             }
12164             for(var key in state){
12165                 if(typeof state[key] != 'function'){
12166                     var rstate = state[key];
12167                     var r = layout.getRegion(key);
12168                     if(r && rstate){
12169                         if(rstate.size){
12170                             r.resizeTo(rstate.size);
12171                         }
12172                         if(rstate.collapsed == true){
12173                             r.collapse(true);
12174                         }else{
12175                             r.expand(null, true);
12176                         }
12177                     }
12178                 }
12179             }
12180             if(!wasUpdating){
12181                 layout.endUpdate();
12182             }
12183             this.state = state; 
12184         }
12185         this.layout = layout;
12186         layout.on('regionresized', this.onRegionResized, this, true);
12187         layout.on('regioncollapsed', this.onRegionCollapsed, this, true);
12188         layout.on('regionexpanded', this.onRegionExpanded, this, true);
12189     },
12190     
12191     storeState : function(){
12192         this.provider.set(this.layout.id+'-layout-state', this.state);
12193     },
12194     
12195     onRegionResized : function(region, newSize){
12196         this.state[region.getPosition()].size = newSize;
12197         this.storeState();
12198     },
12199     
12200     onRegionCollapsed : function(region){
12201         this.state[region.getPosition()].collapsed = true;
12202         this.storeState();
12203     },
12204     
12205     onRegionExpanded : function(region){
12206         this.state[region.getPosition()].collapsed = false;
12207         this.storeState();
12208     }
12209 };
12210
12211 YAHOO.ext.BasicDialog = function(el, config){
12212     this.el = getEl(el);
12213     var dh = YAHOO.ext.DomHelper;
12214     if(!this.el && config && config.autoCreate){
12215         if(typeof config.autoCreate == 'object'){
12216             if(!config.autoCreate.id){
12217                 config.autoCreate.id = el;
12218             }
12219             this.el = dh.append(document.body,
12220                         config.autoCreate, true);
12221         }else{
12222             this.el = dh.append(document.body,
12223                         {tag: 'div', id: el}, true);
12224         }
12225     }
12226     el = this.el;
12227     el.setDisplayed(true);
12228     el.hide = this.hideAction;
12229     this.id = el.id;
12230     el.addClass('ydlg');
12231     this.shadowOffset = 3;
12232     this.minHeight = 80;
12233     this.minWidth = 200;
12234     this.minButtonWidth = 75;
12235     this.defaultButton = null;
12236     
12237     YAHOO.ext.util.Config.apply(this, config);
12238     
12239     this.proxy = el.createProxy('ydlg-proxy');
12240     this.proxy.hide = this.hideAction;
12241     this.proxy.setOpacity(.5);
12242     this.proxy.hide();
12243     
12244     if(config.width){
12245         el.setWidth(config.width);
12246     }
12247     if(config.height){
12248         el.setHeight(config.height);
12249     }
12250     this.size = el.getSize();
12251     if(typeof config.x != 'undefined' && typeof config.y != 'undefined'){
12252         this.xy = [config.x,config.y];
12253     }else{
12254         this.xy = el.getCenterXY(true);
12255     }
12256     
12257     var cn = el.dom.childNodes;
12258     for(var i = 0, len = cn.length; i < len; i++) {
12259         var node = cn[i];
12260         if(node && node.nodeType == 1){
12261             if(YAHOO.util.Dom.hasClass(node, 'ydlg-hd')){
12262                 this.header = getEl(node, true);
12263             }else if(YAHOO.util.Dom.hasClass(node, 'ydlg-bd')){
12264                 this.body = getEl(node, true);
12265             }else if(YAHOO.util.Dom.hasClass(node, 'ydlg-ft')){
12266                 
12267                 this.footer = getEl(node, true);
12268             }
12269         }
12270     }
12271     
12272     if(!this.header){
12273         
12274         this.header = dh.append(el.dom, {tag: 'div', cls:'ydlg-hd'}, true);
12275     }
12276     if(this.title){
12277         this.header.update(this.title);
12278     }
12279     if(!this.body){
12280         
12281         this.body = dh.append(el.dom, {tag: 'div', cls:'ydlg-bd'}, true);
12282     }
12283     
12284     var hl = dh.insertBefore(this.header.dom, {tag: 'div', cls:'ydlg-hd-left'});
12285     var hr = dh.append(hl, {tag: 'div', cls:'ydlg-hd-right'});
12286     hr.appendChild(this.header.dom);
12287     
12288     
12289     this.bwrap = dh.insertBefore(this.body.dom, {tag: 'div', cls:'ydlg-dlg-body'}, true);
12290     this.bwrap.dom.appendChild(this.body.dom);
12291     if(this.footer) this.bwrap.dom.appendChild(this.footer.dom);
12292     
12293     if(this.autoScroll !== false && !this.autoTabs){
12294         this.body.setStyle('overflow', 'auto');
12295     }
12296     if(this.closable !== false){
12297         this.el.addClass('ydlg-closable');
12298         this.close = dh.append(el.dom, {tag: 'div', cls:'ydlg-close'}, true);
12299         this.close.mon('click', function(){
12300             this.hide();
12301         }, this, true);
12302     }
12303     if(this.resizable !== false){
12304         this.el.addClass('ydlg-resizable');
12305         this.resizer = new YAHOO.ext.Resizable(el, {
12306             minWidth: this.minWidth || 80, 
12307             minHeight:this.minHeight || 80, 
12308             handles: 'all',
12309             pinned: true
12310         });
12311         this.resizer.on('beforeresize', this.beforeResize, this, true);
12312         this.resizer.on('resize', this.onResize, this, true);
12313     }
12314     if(this.draggable !== false){
12315         el.addClass('ydlg-draggable');
12316         if (!this.proxyDrag) {
12317             var dd = new YAHOO.util.DD(el.dom.id, 'WindowDrag');
12318         }
12319         else {
12320             var dd = new YAHOO.util.DDProxy(el.dom.id, 'WindowDrag', {dragElId: this.proxy.id});
12321         }
12322         dd.setHandleElId(this.header.id);
12323         dd.endDrag = this.endMove.createDelegate(this);
12324         dd.startDrag = this.startMove.createDelegate(this);
12325         dd.onDrag = this.onDrag.createDelegate(this);
12326         this.dd = dd;
12327     }
12328     if(this.modal){
12329         this.mask = dh.append(document.body, {tag: 'div', cls:'ydlg-mask'}, true);
12330         this.mask.enableDisplayMode('block');
12331         this.mask.hide();
12332     }
12333     if(this.shadow){
12334         this.shadow = el.createProxy({tag: 'div', cls:'ydlg-shadow'});
12335         this.shadow.setOpacity(.3);
12336         this.shadow.setVisibilityMode(YAHOO.ext.Element.VISIBILITY);
12337         this.shadow.setDisplayed('block');
12338         this.shadow.hide = this.hideAction;
12339         this.shadow.hide();
12340     }else{
12341         this.shadowOffset = 0;
12342     }
12343     if(this.shim){
12344         this.shim = this.el.createShim();
12345         this.shim.hide = this.hideAction;
12346         this.shim.hide();
12347     }
12348     if(this.autoTabs){
12349         var tabEls = YAHOO.util.Dom.getElementsByClassName('ydlg-tab', this.tabTag || 'div', el.dom);
12350         if(tabEls.length > 0){
12351             this.body.addClass(this.tabPosition == 'bottom' ? 'ytabs-bottom' : 'ytabs-top');
12352             this.tabs = new YAHOO.ext.TabPanel(this.body.dom, this.tabPosition == 'bottom');
12353             for(var i = 0, len = tabEls.length; i < len; i++) {
12354                 var tabEl = tabEls[i];
12355                 this.tabs.addTab(YAHOO.util.Dom.generateId(tabEl), tabEl.title);
12356                 tabEl.title = '';
12357             }
12358             this.tabs.activate(tabEls[0].id);
12359         }
12360     }
12361     this.syncBodyHeight();
12362     this.events = {
12363         
12364         'keydown' : true,
12365         
12366         'move' : true,
12367         
12368         'resize' : true,
12369         
12370         'beforehide' : true,
12371         
12372         'hide' : true,
12373         
12374         'beforeshow' : true,
12375         
12376         'show' : true
12377     };
12378     el.mon('keydown', this.onKeyDown, this, true);
12379     el.mon("mousedown", this.toFront, this, true);
12380
12381     YAHOO.ext.EventManager.onWindowResize(this.adjustViewport, this, true);
12382     this.el.hide();
12383     YAHOO.ext.DialogManager.register(this);
12384 };
12385
12386 YAHOO.extendX(YAHOO.ext.BasicDialog, YAHOO.ext.util.Observable, {
12387     
12388     setTitle : function(text){
12389         this.header.update(text);
12390         return this; 
12391     },
12392     
12393     beforeResize : function(){
12394         this.resizer.minHeight = Math.max(this.minHeight, this.getHeaderFooterHeight(true)+40);
12395     },
12396     
12397     onResize : function(){
12398         this.refreshSize();
12399         this.syncBodyHeight();
12400         this.adjustAssets();
12401         this.fireEvent('resize', this, this.size.width, this.size.height);
12402     },
12403     
12404     onKeyDown : function(e){
12405         this.fireEvent('keydown', this, e);
12406     },
12407     
12408     
12409     resizeTo : function(width, height){
12410         this.el.setSize(width, height);
12411         this.size = {width: width, height: height};
12412         this.syncBodyHeight();
12413         if(this.fixedcenter){
12414             this.center();
12415         }
12416         if(this.isVisible()){
12417             this.constrainXY();
12418             this.adjustAssets();
12419         }
12420         this.fireEvent('resize', this, width, height);
12421         return this;
12422     },
12423     
12424     
12425     addKeyListener : function(key, fn, scope){
12426         var keyCode, shift, ctrl, alt;
12427         if(typeof key == 'object' && !(key instanceof Array)){
12428             keyCode = key['key'];
12429             shift = key['shift'];
12430             ctrl = key['ctrl'];
12431             alt = key['alt'];
12432         }else{
12433             keyCode = key;
12434         }
12435         var handler = function(dlg, e){
12436             if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
12437                 var k = e.getKey();
12438                 if(keyCode instanceof Array){
12439                     for(var i = 0, len = keyCode.length; i < len; i++){
12440                         if(keyCode[i] == k){
12441                           fn.call(scope || window, dlg, k, e);
12442                           return;
12443                         }
12444                     }
12445                 }else{
12446                     if(k == keyCode){
12447                         fn.call(scope || window, dlg, k, e);
12448                     }
12449                 }
12450             }
12451         };
12452         this.on('keydown', handler);
12453         return this; 
12454     },
12455     
12456     
12457     getTabs : function(){
12458         if(!this.tabs){
12459             this.body.addClass(this.tabPosition == 'bottom' ? 'ytabs-bottom' : 'ytabs-top');
12460             this.tabs = new YAHOO.ext.TabPanel(this.body.dom, this.tabPosition == 'bottom');
12461         }
12462         return this.tabs;    
12463     },
12464     
12465     
12466     addButton : function(config, handler, scope){
12467         var dh = YAHOO.ext.DomHelper;
12468         if(!this.footer){
12469             this.footer = dh.append(this.bwrap.dom, {tag: 'div', cls:'ydlg-ft'}, true);
12470         }
12471         var bconfig = {
12472             handler: handler,
12473             scope: scope,
12474             minWidth: this.minButtonWidth
12475         };
12476         if(typeof config == 'string'){
12477             bconfig.text = config;
12478         }else{
12479             bconfig.dhconfig = config;
12480         }
12481         var btn = new YAHOO.ext.Button(this.footer, bconfig);
12482         this.syncBodyHeight();
12483         if(!this.buttons){
12484             this.buttons = [];
12485         }
12486         this.buttons.push(btn);
12487         return btn;
12488     },
12489     
12490     
12491     setDefaultButton : function(btn){
12492         this.defaultButton = btn;  
12493         return this;
12494     },
12495     
12496     getHeaderFooterHeight : function(safe){
12497         var height = 0;
12498         if(this.header){
12499            height += this.header.getHeight();
12500         }
12501         if(this.footer){
12502             var fm = this.footer.getMargins();
12503             height += (this.footer.getHeight()+fm.top+fm.bottom);
12504         }
12505         height += this.bwrap.getPadding('tb')+this.bwrap.getBorderWidth('tb');
12506         return height;
12507     },
12508     
12509     syncBodyHeight : function(){
12510         var height = this.size.height - this.getHeaderFooterHeight(false);
12511         var bm = this.body.getMargins();
12512         this.body.setHeight(height-(bm.top+bm.bottom));
12513         if(this.tabs){
12514             this.tabs.syncHeight();
12515         }
12516         this.bwrap.setHeight(this.size.height-this.header.getHeight());
12517         
12518         this.body.setWidth(this.el.getWidth(true)-this.bwrap.getBorderWidth('lr')-this.bwrap.getPadding('lr'));
12519     },
12520     
12521     
12522     restoreState : function(){
12523         var box = YAHOO.ext.state.Manager.get(this.el.id + '-state');
12524         if(box && box.width){
12525             this.xy = [box.x, box.y];
12526             this.resizeTo(box.width, box.height);
12527         }
12528         return this; 
12529     },
12530     
12531     beforeShow : function(){
12532         if(this.fixedcenter) {
12533             this.xy = this.el.getCenterXY(true);
12534         }
12535         if(this.modal){
12536             YAHOO.util.Dom.addClass(document.body, 'masked');
12537             this.mask.setSize(YAHOO.util.Dom.getDocumentWidth(), YAHOO.util.Dom.getDocumentHeight());
12538             this.mask.show();
12539         }
12540         this.constrainXY();
12541     },
12542     
12543     animShow : function(){
12544         var b = getEl(this.animateTarget, true).getBox();
12545         this.proxy.setSize(b.width, b.height);
12546         this.proxy.setLocation(b.x, b.y);
12547         this.proxy.show();
12548         this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height, 
12549                     true, .35, this.showEl.createDelegate(this));
12550     },
12551     
12552     
12553     show : function(animateTarget){
12554         if (this.fireEvent('beforeshow', this) === false){
12555             return;
12556         }
12557         if(this.syncHeightBeforeShow){
12558             this.syncBodyHeight();
12559         }
12560         this.animateTarget = animateTarget || this.animateTarget;
12561         if(!this.el.isVisible()){
12562             this.beforeShow();
12563             if(this.animateTarget){
12564                 this.animShow();
12565             }else{
12566                 this.showEl();
12567             }
12568         }
12569         return this; 
12570     },
12571     
12572     showEl : function(){
12573         this.proxy.hide();
12574         this.el.setXY(this.xy);
12575         this.el.show();
12576         this.adjustAssets(true);
12577         this.toFront();
12578         if(this.defaultButton){
12579             this.defaultButton.focus();
12580         }
12581         this.fireEvent('show', this);
12582     },
12583     
12584     constrainXY : function(){
12585         if(this.constraintoviewport !== false){
12586             if(!this.viewSize){
12587                 this.viewSize = [YAHOO.util.Dom.getViewportWidth(), YAHOO.util.Dom.getViewportHeight()];
12588             }
12589             var x = this.xy[0], y = this.xy[1];
12590             var w = this.size.width, h = this.size.height;
12591             var vw = this.viewSize[0], vh = this.viewSize[1];
12592             
12593             var moved = false;
12594             
12595             if(x + w > vw){
12596                 x = vw - w;
12597                 moved = true;
12598             }
12599             if(y + h > vh){
12600                 y = vh - h;
12601                 moved = true;
12602             }
12603             
12604             if(x < 0){
12605                 x = 0;
12606                 moved = true;
12607             }
12608             if(y < 0){
12609                 y = 0;
12610                 moved = true;
12611             }
12612             if(moved){
12613                 
12614                 this.xy = [x, y];
12615                 if(this.isVisible()){
12616                     this.el.setLocation(x, y);
12617                     this.adjustAssets();
12618                 }
12619             }
12620         }
12621     },
12622     
12623     onDrag : function(){
12624         if(!this.proxyDrag){
12625             this.xy = this.el.getXY();
12626             this.adjustAssets();
12627         }   
12628     },
12629     
12630     adjustAssets : function(doShow){
12631         var x = this.xy[0], y = this.xy[1];
12632         var w = this.size.width, h = this.size.height;
12633         if(doShow === true){
12634             if(this.shadow){
12635                 this.shadow.show();
12636             }
12637             if(this.shim){
12638                 this.shim.show();
12639             }
12640         }
12641         if(this.shadow && this.shadow.isVisible()){
12642             this.shadow.setBounds(x + this.shadowOffset, y + this.shadowOffset, w, h);
12643         }
12644         if(this.shim && this.shim.isVisible()){
12645             this.shim.setBounds(x, y, w, h);
12646         }
12647     },
12648     
12649     
12650     adjustViewport : function(w, h){
12651         if(!w || !h){
12652             w = YAHOO.util.Dom.getViewportWidth();
12653             h = YAHOO.util.Dom.getViewportHeight();
12654         }
12655         
12656         this.viewSize = [w, h];
12657         if(this.modal && this.mask.isVisible()){
12658             this.mask.setSize(w, h); 
12659             this.mask.setSize(YAHOO.util.Dom.getDocumentWidth(), YAHOO.util.Dom.getDocumentHeight());
12660         }
12661         if(this.isVisible()){
12662             this.constrainXY();
12663         }
12664     },
12665     
12666     
12667     destroy : function(removeEl){
12668         YAHOO.ext.EventManager.removeResizeListener(this.adjustViewport, this);
12669         if(this.tabs){
12670             this.tabs.destroy(removeEl);
12671         }
12672         if(removeEl === true){
12673             this.el.update('');
12674             this.el.remove();
12675         }
12676         YAHOO.ext.DialogManager.unregister(this);
12677     },
12678     
12679     startMove : function(){
12680         if(this.proxyDrag){
12681             this.proxy.show();
12682         }
12683         if(this.constraintoviewport !== false){
12684             this.dd.constrainTo(document.body, {right: this.shadowOffset, bottom: this.shadowOffset});
12685         }
12686     },
12687     
12688     endMove : function(){
12689         if(!this.proxyDrag){
12690             YAHOO.util.DD.prototype.endDrag.apply(this.dd, arguments);
12691         }else{
12692             YAHOO.util.DDProxy.prototype.endDrag.apply(this.dd, arguments);
12693             this.proxy.hide();
12694         }
12695         this.refreshSize();
12696         this.adjustAssets();
12697         this.fireEvent('move', this, this.xy[0], this.xy[1])
12698     },
12699     
12700     
12701     toFront : function(){
12702         YAHOO.ext.DialogManager.bringToFront(this);  
12703         return this; 
12704     },
12705     
12706     
12707     toBack : function(){
12708         YAHOO.ext.DialogManager.sendToBack(this);  
12709         return this; 
12710     },
12711     
12712     
12713     center : function(){
12714         this.moveTo(this.el.getCenterXY(true));
12715         return this; 
12716     },
12717     
12718     
12719     moveTo : function(x, y){
12720         this.xy = [x,y];
12721         if(this.isVisible()){
12722             this.el.setXY(this.xy);
12723             this.adjustAssets();
12724         }
12725         return this; 
12726     },
12727     
12728     
12729     isVisible : function(){
12730         return this.el.isVisible();    
12731     },
12732     
12733     animHide : function(callback){
12734         var b = getEl(this.animateTarget, true).getBox();
12735         this.proxy.show();
12736         this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height);
12737         this.el.hide();
12738         this.proxy.setBounds(b.x, b.y, b.width, b.height, true, .35, 
12739                     this.hideEl.createDelegate(this, [callback]));
12740     },
12741     
12742     
12743     hide : function(callback){
12744         if (this.fireEvent('beforehide', this) === false)
12745             return;
12746         
12747         if(this.shadow){
12748             this.shadow.hide();
12749         }
12750         if(this.shim) {
12751           this.shim.hide();
12752         }
12753         if(this.animateTarget){
12754            this.animHide(callback);
12755         }else{
12756             this.el.hide();
12757             this.hideEl(callback);
12758         }
12759         return this; 
12760     },
12761     
12762     hideEl : function(callback){
12763         this.proxy.hide();
12764         if(this.modal){
12765             this.mask.hide();
12766             YAHOO.util.Dom.removeClass(document.body, 'masked');
12767         }
12768         this.fireEvent('hide', this);
12769         if(typeof callback == 'function'){
12770             callback();
12771         }
12772     },
12773     
12774     hideAction : function(){
12775         this.setLeft('-10000px');  
12776         this.setTop('-10000px');
12777         this.setStyle('visibility', 'hidden'); 
12778     },
12779     
12780     refreshSize : function(){
12781         this.size = this.el.getSize();
12782         this.xy = this.el.getXY();
12783         YAHOO.ext.state.Manager.set(this.el.id + '-state', this.el.getBox());
12784     },
12785     
12786     setZIndex : function(index){
12787         if(this.modal){
12788             this.mask.setStyle('z-index', index);
12789         }
12790         if(this.shadow){
12791             this.shadow.setStyle('z-index', ++index);
12792         }
12793         if(this.shim){
12794             this.shim.setStyle('z-index', ++index);
12795         }
12796         this.el.setStyle('z-index', ++index);
12797         if(this.proxy){
12798             this.proxy.setStyle('z-index', ++index);
12799         }
12800         if(this.resizer){
12801             this.resizer.proxy.setStyle('z-index', ++index);
12802         }
12803         
12804         this.lastZIndex = index;
12805     },
12806     
12807     
12808     getEl : function(){
12809         return this.el;
12810     }
12811 });
12812
12813
12814 YAHOO.ext.DialogManager = function(){
12815     var list = {};
12816     var accessList = [];
12817     var front = null;
12818     
12819     var sortDialogs = function(d1, d2){
12820         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
12821     };
12822     
12823     var orderDialogs = function(){
12824         accessList.sort(sortDialogs);
12825         var seed = YAHOO.ext.DialogManager.zseed;
12826         for(var i = 0, len = accessList.length; i < len; i++){
12827             if(accessList[i]){
12828                 accessList[i].setZIndex(seed + (i*10));
12829             }  
12830         }
12831     };
12832     
12833     return {
12834         
12835         zseed : 10000,
12836         
12837         
12838         register : function(dlg){
12839             list[dlg.id] = dlg;
12840             accessList.push(dlg);
12841         },
12842         
12843         unregister : function(dlg){
12844             delete list[dlg.id];
12845             if(!accessList.indexOf){
12846                 for(var i = 0, len = accessList.length; i < len; i++){
12847                     accessList.splice(i, 1);
12848                     return;
12849                 }
12850             }else{
12851                 var i = accessList.indexOf(dlg);
12852                 if(i != -1){
12853                     accessList.splice(i, 1);
12854                 }
12855             }
12856         },
12857         
12858         
12859         get : function(id){
12860             return typeof id == 'object' ? id : list[id];
12861         },
12862         
12863         
12864         bringToFront : function(dlg){
12865             dlg = this.get(dlg);
12866             if(dlg != front){
12867                 front = dlg;
12868                 dlg._lastAccess = new Date().getTime();
12869                 orderDialogs();
12870             }
12871             return dlg;
12872         },
12873         
12874         
12875         sendToBack : function(dlg){
12876             dlg = this.get(dlg);
12877             dlg._lastAccess = -(new Date().getTime());
12878             orderDialogs();
12879             return dlg;
12880         }
12881     };
12882 }();
12883
12884
12885 YAHOO.ext.LayoutDialog = function(el, config){
12886     config.autoTabs = false;
12887     YAHOO.ext.LayoutDialog.superclass.constructor.call(this, el, config);
12888     this.body.setStyle({overflow:'hidden', position:'relative'});
12889     this.layout = new YAHOO.ext.BorderLayout(this.body.dom, config);
12890     this.layout.monitorWindowResize = false;
12891     
12892     this.center = YAHOO.ext.BasicDialog.prototype.center;
12893     this.on('show', this.layout.layout, this.layout, true);
12894 };
12895 YAHOO.extendX(YAHOO.ext.LayoutDialog, YAHOO.ext.BasicDialog, {
12896     
12897     endUpdate : function(){
12898         this.layout.endUpdate();
12899     },
12900     
12901     beginUpdate : function(){
12902         this.layout.beginUpdate();
12903     },
12904     
12905     getLayout : function(){
12906         return this.layout;
12907     },
12908     syncBodyHeight : function(){
12909         YAHOO.ext.LayoutDialog.superclass.syncBodyHeight.call(this);
12910         if(this.layout)this.layout.layout();
12911     }
12912 });
12913
12914 YAHOO.ext.Button = function(renderTo, config){
12915     YAHOO.ext.util.Config.apply(this, config);
12916     this.events = {
12917         
12918             'click' : true  
12919     };
12920     if(renderTo){
12921         this.render(renderTo);
12922     }
12923 };
12924
12925 YAHOO.extendX(YAHOO.ext.Button, YAHOO.ext.util.Observable, {
12926     render : function(renderTo){
12927         var btn;
12928         if(!this.dhconfig){
12929             if(!YAHOO.ext.Button.buttonTemplate){
12930                 
12931                 YAHOO.ext.Button.buttonTemplate = new YAHOO.ext.DomHelper.Template('<a href="#" class="ybtn-focus"><table border="0" cellpadding="0" cellspacing="0" class="ybtn-wrap"><tbody><tr><td class="ybtn-left">&#160;</td><td class="ybtn-center" unselectable="on">{0}</td><td class="ybtn-right">&#160;</td></tr></tbody></table></a>');
12932             }
12933             btn = YAHOO.ext.Button.buttonTemplate.append(
12934                getEl(renderTo).dom, [this.text], true);
12935             this.tbl = getEl(btn.dom.firstChild, true);
12936         }else{
12937             btn = YAHOO.ext.DomHelper.append(this.footer.dom, this.dhconfig, true);
12938         }
12939         this.el = btn;
12940         this.autoWidth();
12941         btn.addClass('ybtn');
12942         btn.mon('click', this.onClick, this, true);
12943         btn.on('mouseover', this.onMouseOver, this, true);
12944         btn.on('mouseout', this.onMouseOut, this, true);
12945         btn.on('mousedown', this.onMouseDown, this, true);
12946         btn.on('mouseup', this.onMouseUp, this, true);
12947     },
12948     
12949     getEl : function(){
12950         return this.el;  
12951     },
12952     
12953     autoWidth : function(){
12954         if(this.tbl){
12955             this.el.setWidth('auto');
12956             this.tbl.setWidth('auto');
12957             if(this.minWidth){
12958                  if(this.tbl.getWidth() < this.minWidth){
12959                      this.tbl.setWidth(this.minWidth);
12960                  }
12961             }
12962             this.el.setWidth(this.tbl.getWidth());
12963         } 
12964     },
12965     
12966     setHandler : function(handler, scope){
12967         this.handler = handler;
12968         this.scope = scope;  
12969     },
12970     
12971     
12972     setText : function(text){
12973         this.el.dom.firstChild.firstChild.firstChild.childNodes[1].innerHTML = text;
12974         this.autoWidth();
12975     },
12976     
12977     
12978     show: function(){
12979         this.el.setStyle('display', '');
12980     },
12981     
12982     
12983     hide: function(){
12984         this.el.setStyle('display', 'none'); 
12985     },
12986     
12987     
12988     setVisible: function(visible){
12989         if(visible) {
12990             this.show();
12991         }else{
12992             this.hide();
12993         }
12994     },
12995     
12996     
12997     focus : function(){
12998         this.el.focus();    
12999     },
13000     
13001     
13002     disable : function(){
13003         this.el.addClass('ybtn-disabled');
13004         this.disabled = true;
13005     },
13006     
13007     
13008     enable : function(){
13009         this.el.removeClass('ybtn-disabled');
13010         this.disabled = false;
13011     },
13012     
13013     onClick : function(e){
13014         e.preventDefault();
13015         if(!this.disabled){
13016             this.fireEvent('click', this, e);
13017             this.handler.call(this.scope || window, this, e);
13018         }
13019     },
13020     onMouseOver : function(e){
13021         if(!this.disabled){
13022             this.el.addClass('ybtn-over');
13023         }
13024     },
13025     onMouseOut : function(e){
13026         this.el.removeClass('ybtn-over');
13027     },
13028     onMouseDown : function(){
13029         if(!this.disabled){
13030             this.el.addClass('ybtn-click');
13031         }
13032     },
13033     onMouseUp : function(){
13034         this.el.removeClass('ybtn-click');
13035     }    
13036 });
13037
13038 YAHOO.ext.View = function(container, tpl, dataModel, config){
13039     this.el = getEl(container, true);
13040     this.nodes = this.el.dom.childNodes;
13041     if(typeof tpl == 'string'){
13042         tpl = new YAHOO.ext.Template(tpl);
13043     }
13044     tpl.compile();
13045     
13046     this.tpl = tpl;
13047     this.setDataModel(dataModel);
13048     var CE = YAHOO.util.CustomEvent;
13049         
13050         this.events = {
13051             
13052         'click' : true,
13053             
13054         'dblclick' : true,
13055             
13056         'contextmenu' : true,
13057             
13058         'selectionchange' : true,
13059         
13060         
13061         'beforeselect' : true
13062         };
13063         this.el.mon("click", this.onClick, this, true);
13064     this.el.mon("dblclick", this.onDblClick, this, true);
13065     this.el.mon("contextmenu", this.onContextMenu, this, true);
13066     
13067     
13068     this.selectedClass = 'ydataview-selected';
13069     
13070     this.emptyText = '';
13071     
13072     this.selections = [];
13073     this.lastSelection = null;
13074     
13075     
13076     this.jsonRoot = null;
13077     YAHOO.ext.util.Config.apply(this, config);
13078     if(this.renderUpdates || this.jsonRoot){
13079         var um = this.el.getUpdateManager();
13080         um.setRenderer(this);
13081     }
13082 };
13083
13084 YAHOO.extendX(YAHOO.ext.View, YAHOO.ext.util.Observable, {
13085     
13086     getEl : function(){
13087         return this.el;  
13088     },
13089     
13090     render : function(el, response){
13091         this.clearSelections();
13092         this.el.update('');
13093         var o;
13094         try{
13095             o = YAHOO.ext.util.JSON.decode(response.responseText);
13096             if(this.jsonRoot){
13097                 o = eval('o.' + this.jsonRoot);
13098             }
13099         }catch(e){}
13100         
13101         this.jsonData = o;
13102         this.beforeRender();
13103         this.refresh();
13104     },
13105     
13106     beforeRender : function(){
13107         
13108     },
13109     
13110     
13111      refresh : function(){
13112         this.clearSelections();
13113         this.el.update('');
13114         this.html = [];
13115         if(this.renderUpdates || this.jsonRoot){
13116             var o = this.jsonData;
13117             if(o){
13118                 for(var i = 0, len = o.length; i < len; i++) {
13119                         this.renderEach(o[i]);
13120                 }
13121             }
13122         }else{
13123            this.dataModel.each(this.renderEach, this);
13124         }
13125         var strHtml;
13126         if(this.html.length > 0){
13127             strHtml = this.html.join('');
13128         }else{
13129             strHtml = this.emptyText;
13130         }
13131         this.el.update(strHtml);
13132         this.html = null;
13133         this.nodes = this.el.dom.childNodes;
13134         this.updateIndexes(0);
13135     },
13136     
13137     
13138     prepareData : function(data, index){
13139         return data;  
13140     },
13141     
13142     renderEach : function(data){
13143         this.html[this.html.length] = this.tpl.applyTemplate(this.prepareData(data));
13144     },
13145     
13146     
13147     refreshNode : function(index){
13148         this.refreshNodes(index, index);
13149     },
13150     
13151     refreshNodes : function(dm, startIndex, endIndex){
13152         this.clearSelections();
13153         var dm = this.dataModel;
13154         var ns = this.nodes;
13155         for(var i = startIndex; i <= endIndex; i++){
13156             var d = this.prepareData(dm.getRow(i), i);
13157             if(i < ns.length-1){
13158                 var old = ns[i];
13159                 this.tpl.insertBefore(old, d);
13160                 this.el.dom.removeChild(old);
13161             }else{
13162                 this.tpl.append(this.el.dom, d);
13163             }
13164         }
13165         this.updateIndexes(startIndex, endIndex);
13166     },
13167     
13168     deleteNodes : function(dm, startIndex, endIndex){
13169         this.clearSelections();
13170         if(startIndex == 0 && endIndex >= this.nodes.length-1){
13171             this.el.update('');
13172         }else{
13173             var el = this.el.dom;
13174             for(var i = startIndex; i <= endIndex; i++){
13175                 el.removeChild(this.nodes[startIndex]);
13176             }
13177             this.updateIndexes(startIndex);
13178         }
13179     },
13180     
13181     insertNodes : function(dm, startIndex, endIndex){
13182         if(this.nodes.length == 0){
13183             this.refresh();
13184         }else{
13185             this.clearSelections();
13186             var t = this.tpl;
13187             var before = this.nodes[startIndex];
13188             var dm = this.dataModel;
13189             if(before){
13190                 for(var i = startIndex; i <= endIndex; i++){
13191                     t.insertBefore(before, this.prepareData(dm.getRow(i), i));
13192                 }
13193             }else{
13194                 var el = this.el.dom;
13195                 for(var i = startIndex; i <= endIndex; i++){
13196                     t.append(el, this.prepareData(dm.getRow(i), i));
13197                 }
13198             }
13199             this.updateIndexes(startIndex);
13200         }
13201     },
13202     
13203     updateIndexes : function(dm, startIndex, endIndex){
13204         var ns = this.nodes;
13205         startIndex = startIndex || 0;
13206         endIndex = endIndex || ns.length-1;
13207         for(var i = startIndex; i <= endIndex; i++){
13208             ns[i].nodeIndex = i;
13209         }
13210     },
13211     
13212     
13213      setDataModel : function(dm){
13214         if(!dm) return;
13215         this.unplugDataModel(this.dataModel);
13216         this.dataModel = dm;
13217         dm.on('cellupdated', this.refreshNode, this, true);
13218         dm.on('datachanged', this.refresh, this, true);
13219         dm.on('rowsdeleted', this.deleteNodes, this, true);
13220         dm.on('rowsinserted', this.insertNodes, this, true);
13221         dm.on('rowsupdated', this.refreshNodes, this, true);
13222         dm.on('rowssorted', this.refresh, this, true);
13223         this.refresh();
13224     },
13225     
13226     
13227     unplugDataModel : function(dm){
13228         if(!dm) return;
13229         dm.removeListener('cellupdated', this.refreshNode, this);
13230         dm.removeListener('datachanged', this.refresh, this);
13231         dm.removeListener('rowsdeleted', this.deleteNodes, this);
13232         dm.removeListener('rowsinserted', this.insertNodes, this);
13233         dm.removeListener('rowsupdated', this.refreshNodes, this);
13234         dm.removeListener('rowssorted', this.refresh, this);
13235         this.dataModel = null;
13236     },
13237     
13238     
13239     findItemFromChild : function(node){
13240         var el = this.el.dom;
13241         if(!node || node.parentNode == el){
13242                     return node;
13243             }
13244             var p = node.parentNode;
13245             while(p && p != el){
13246             if(p.parentNode == el){
13247                 return p;
13248             }
13249             p = p.parentNode;
13250         }
13251             return null;
13252     },
13253     
13254     
13255     onClick : function(e){
13256         var item = this.findItemFromChild(e.getTarget());
13257         if(item){
13258             var index = this.indexOf(item);
13259             this.onItemClick(item, index, e);
13260             this.fireEvent('click', this, index, item, e);
13261         }else{
13262             this.clearSelections();
13263         }
13264     },
13265
13266     
13267     onContextMenu : function(e){
13268         var item = this.findItemFromChild(e.getTarget());
13269         if(item){
13270             this.fireEvent('contextmenu', this, this.indexOf(item), item, e);
13271         }
13272     },
13273
13274     
13275     onDblClick : function(e){
13276         var item = this.findItemFromChild(e.getTarget());
13277         if(item){
13278             this.fireEvent('dblclick', this, this.indexOf(item), item, e);
13279         }
13280     },
13281     
13282     onItemClick : function(item, index, e){
13283         if(this.multiSelect || this.singleSelect){
13284             if(this.multiSelect && e.shiftKey && this.lastSelection){
13285                 this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
13286             }else{
13287                 this.select(item, this.multiSelect && e.ctrlKey);
13288                 this.lastSelection = item;
13289             }
13290         }
13291     },
13292     
13293     
13294      getSelectionCount : function(){
13295         return this.selections.length;
13296     },
13297     
13298     
13299     getSelectedNodes : function(){
13300         return this.selections;
13301     },
13302     
13303     
13304     getSelectedIndexes : function(){
13305         var indexes = [];
13306         for(var i = 0, len = this.selections.length; i < len; i++) {
13307                 indexes.push(this.selections[i].nodeIndex);
13308         }
13309         return indexes;
13310     },
13311     
13312     
13313     clearSelections : function(suppressEvent){
13314         if(this.multiSelect || this.singleSelect){
13315             YAHOO.util.Dom.removeClass(this.selections, this.selectedClass);
13316             this.selections = [];
13317             if(!suppressEvent){
13318                 this.fireEvent('selectionchange', this, this.selections);
13319             }
13320         }
13321     },
13322     
13323     
13324     select : function(nodeInfo, keepExisting, suppressEvent){
13325         if(!keepExisting){
13326             this.clearSelections(true);
13327         }
13328         if(nodeInfo instanceof Array){
13329             for(var i = 0, len = nodeInfo.length; i < len; i++) {
13330                 this.select(nodeInfo[i], true, true);
13331             }
13332         }else{
13333             var node = this.getNode(nodeInfo);
13334             if(node){
13335                 if(this.fireEvent('beforeselect', this, node, this.selections) !== false){
13336                     YAHOO.util.Dom.addClass(node, this.selectedClass);
13337                     this.selections.push(node);
13338                 }
13339             }
13340         }
13341         if(!suppressEvent){
13342             this.fireEvent('selectionchange', this, this.selections);
13343         }
13344     },
13345     
13346     
13347      getNode : function(nodeInfo){
13348         if(typeof nodeInfo == 'object'){
13349             return nodeInfo;
13350         }else if(typeof nodeInfo == 'string'){
13351             return document.getElementById(nodeInfo);
13352         }else if(typeof nodeInfo == 'number'){
13353             return this.nodes[nodeInfo];
13354         }
13355         return null;
13356     },
13357     
13358     
13359     getNodes : function(start, end){
13360         var ns = this.nodes;
13361         startIndex = startIndex || 0;
13362         endIndex = typeof endIndex == 'undefined' ? ns.length-1 : endIndex;
13363         var nodes = [];
13364         for(var i = start; i <= end; i++) {
13365                 nodes.push(ns[i]);
13366         }
13367         return nodes;
13368     },
13369     
13370     
13371      indexOf : function(node){
13372         node = this.getNode(node);
13373         if(typeof node.nodeIndex == 'number'){
13374             return node.nodeIndex;
13375         }
13376         var ns = this.nodes;
13377         for(var i = 0, len = ns.length; i < len; i++) {
13378                 if(ns[i] == node){
13379                     return i;
13380                 }
13381         }
13382         return -1;
13383     }
13384 });
13385
13386  
13387 YAHOO.ext.JsonView = function(container, tpl, config){
13388     var cfg = config || {};
13389     cfg.renderUpdates = true;
13390     YAHOO.ext.JsonView.superclass.constructor.call(this, container, tpl, null, cfg);        
13391     
13392      this.events['beforerender'] = true;
13393      
13394      this.events['load'] = true;
13395      
13396      this.events['loadexception'] = true;
13397      this.el.getUpdateManager().on('update', this.onLoad, this, true);
13398      this.el.getUpdateManager().on('failure', this.onLoadException, this, true);
13399 };
13400 YAHOO.extendX(YAHOO.ext.JsonView, YAHOO.ext.View, {
13401     
13402     load : function(){
13403         var um = this.el.getUpdateManager();
13404         um.update.apply(um, arguments);
13405     },
13406     
13407     
13408     getCount : function(){
13409         return this.jsonData ? this.jsonData.length : 0;  
13410     },
13411     
13412     beforeRender : function(){
13413         this.snapshot = this.jsonData;    
13414         if(this.sortInfo){
13415             this.sort.apply(this, this.sortInfo);    
13416         }
13417         this.fireEvent('beforerender', this, this.jsonData);
13418     },
13419     
13420     onLoad : function(el, o){
13421        this.fireEvent('load', this, this.jsonData, o);
13422     },
13423     
13424     onLoadException : function(el, o){
13425        this.fireEvent('loadexception', this, o);
13426     },
13427     
13428     
13429     filter : function(property, value){
13430         if(this.jsonData){
13431             var data = [];
13432             var ss = this.snapshot;
13433             if(typeof value == 'string'){
13434                 var vlen = value.length;
13435                 if(vlen == 0){
13436                     this.clearFilter();
13437                     return;
13438                 }
13439                 for(var i = 0, len = ss.length; i < len; i++){
13440                                 var o = ss[i];
13441                                 if(o[property].substr(0, vlen) == value){
13442                                         data.push(o);
13443                                 }
13444                         }
13445             }else if(value.exec){ 
13446                 for(var i = 0, len = ss.length; i < len; i++){
13447                                 var o = ss[i];
13448                                 if(value.test(o[property])){
13449                                         data.push(o);
13450                                 }
13451                         }
13452             }else{
13453                 return;
13454             }
13455             this.jsonData = data;
13456                 this.refresh();
13457         }
13458         },
13459     
13460     
13461     filterBy : function(fn, scope){
13462         if(this.jsonData){
13463             var data = [];
13464             var ss = this.snapshot;
13465             for(var i = 0, len = ss.length; i < len; i++){
13466                         var o = ss[i];
13467                         if(fn.call(scope|| this, o)){
13468                                 data.push(o);
13469                         }
13470                 }
13471                 this.jsonData = data;
13472                 this.refresh();
13473         }
13474     },
13475     
13476     
13477     clearFilter : function(){
13478         if(this.snapshot && this.jsonData != this.snapshot){
13479             this.jsonData = this.snapshot;
13480             this.refresh();
13481         }   
13482     },
13483     
13484     
13485     
13486     sort : function(property, dir, sortType){
13487         this.sortInfo = Array.prototype.slice.call(arguments, 0);
13488         if(this.jsonData){
13489             var p = property;
13490             var dsc = dir && dir.toLowerCase() == 'desc';
13491             var f = function(o1, o2){
13492                 var v1 = sortType ? sortType(o1[p]) : o1[p];
13493                 var v2 = sortType ? sortType(o2[p]) : o2[p];;
13494                 if(v1 < v2){
13495                                 return dsc ? +1 : -1;
13496                         }else if(v1 > v2){
13497                                 return dsc ? -1 : +1;
13498                 }else{
13499                         return 0;
13500                 }
13501             };
13502             this.jsonData.sort(f);
13503             this.refresh();
13504             if(this.jsonData != this.snapshot){
13505                 this.snapshot.sort(f);
13506             }
13507         }
13508     }
13509 });