3befa7e76f8906f83d882ad6bcd50c0d69f21f52
[extjs.git] / ext-all-debug.js
1
2
3 Ext.DomHelper = function(){
4     var tempTableEl = null,
5         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
6         tableRe = /^table|tbody|tr|td$/i,
7         confRe = /tag|children|cn|html$/i,
8         tableElRe = /td|tr|tbody/i,
9         cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
10         endRe = /end/i,
11         pub,
12         
13         afterbegin = 'afterbegin',
14         afterend = 'afterend',
15         beforebegin = 'beforebegin',
16         beforeend = 'beforeend',
17         ts = '<table>',
18         te = '</table>',
19         tbs = ts+'<tbody>',
20         tbe = '</tbody>'+te,
21         trs = tbs + '<tr>',
22         tre = '</tr>'+tbe;
23
24     
25     function doInsert(el, o, returnElement, pos, sibling, append){
26         var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
27         return returnElement ? Ext.get(newNode, true) : newNode;
28     }
29
30     
31     function createHtml(o){
32         var b = '',
33             attr,
34             val,
35             key,
36             keyVal,
37             cn;
38
39         if(typeof o == "string"){
40             b = o;
41         } else if (Ext.isArray(o)) {
42             for (var i=0; i < o.length; i++) {
43                 if(o[i]) {
44                     b += createHtml(o[i]);
45                 }
46             };
47         } else {
48             b += '<' + (o.tag = o.tag || 'div');
49             for (attr in o) {
50                 val = o[attr];
51                 if(!confRe.test(attr)){
52                     if (typeof val == "object") {
53                         b += ' ' + attr + '="';
54                         for (key in val) {
55                             b += key + ':' + val[key] + ';';
56                         };
57                         b += '"';
58                     }else{
59                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
60                     }
61                 }
62             };
63             
64             if (emptyTags.test(o.tag)) {
65                 b += '/>';
66             } else {
67                 b += '>';
68                 if ((cn = o.children || o.cn)) {
69                     b += createHtml(cn);
70                 } else if(o.html){
71                     b += o.html;
72                 }
73                 b += '</' + o.tag + '>';
74             }
75         }
76         return b;
77     }
78
79     function ieTable(depth, s, h, e){
80         tempTableEl.innerHTML = [s, h, e].join('');
81         var i = -1,
82             el = tempTableEl,
83             ns;
84         while(++i < depth){
85             el = el.firstChild;
86         }
87
88         if(ns = el.nextSibling){
89             var df = document.createDocumentFragment();
90             while(el){
91                 ns = el.nextSibling;
92                 df.appendChild(el);
93                 el = ns;
94             }
95             el = df;
96         }
97         return el;
98     }
99
100     
101     function insertIntoTable(tag, where, el, html) {
102         var node,
103             before;
104
105         tempTableEl = tempTableEl || document.createElement('div');
106
107         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
108            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
109             return;
110         }
111         before = where == beforebegin ? el :
112                  where == afterend ? el.nextSibling :
113                  where == afterbegin ? el.firstChild : null;
114
115         if (where == beforebegin || where == afterend) {
116             el = el.parentNode;
117         }
118
119         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
120             node = ieTable(4, trs, html, tre);
121         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
122                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
123             node = ieTable(3, tbs, html, tbe);
124         } else {
125             node = ieTable(2, ts, html, te);
126         }
127         el.insertBefore(node, before);
128         return node;
129     }
130
131
132     pub = {
133         
134         markup : function(o){
135             return createHtml(o);
136         },
137
138         
139         applyStyles : function(el, styles){
140             if(styles){
141                 var i = 0,
142                     len,
143                     style,
144                     matches;
145
146                 el = Ext.fly(el);
147                 if(typeof styles == "function"){
148                     styles = styles.call();
149                 }
150                 if(typeof styles == "string"){
151                     while((matches = cssRe.exec(styles))){
152                         el.setStyle(matches[1], matches[2]);
153                     }
154                 }else if (typeof styles == "object"){
155                     el.setStyle(styles);
156                 }
157             }
158         },
159
160         
161         insertHtml : function(where, el, html){
162             var hash = {},
163                 hashVal,
164                 setStart,
165                 range,
166                 frag,
167                 rangeEl,
168                 rs;
169
170             where = where.toLowerCase();
171             
172             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
173             hash[afterend] = ['AfterEnd', 'nextSibling'];
174
175             if (el.insertAdjacentHTML) {
176                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
177                     return rs;
178                 }
179                 
180                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
181                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
182                 if ((hashVal = hash[where])) {
183                     el.insertAdjacentHTML(hashVal[0], html);
184                     return el[hashVal[1]];
185                 }
186             } else {
187                 range = el.ownerDocument.createRange();
188                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
189                 if (hash[where]) {
190                     range[setStart](el);
191                     frag = range.createContextualFragment(html);
192                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
193                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
194                 } else {
195                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
196                     if (el.firstChild) {
197                         range[setStart](el[rangeEl]);
198                         frag = range.createContextualFragment(html);
199                         if(where == afterbegin){
200                             el.insertBefore(frag, el.firstChild);
201                         }else{
202                             el.appendChild(frag);
203                         }
204                     } else {
205                         el.innerHTML = html;
206                     }
207                     return el[rangeEl];
208                 }
209             }
210             throw 'Illegal insertion point -> "' + where + '"';
211         },
212
213         
214         insertBefore : function(el, o, returnElement){
215             return doInsert(el, o, returnElement, beforebegin);
216         },
217
218         
219         insertAfter : function(el, o, returnElement){
220             return doInsert(el, o, returnElement, afterend, 'nextSibling');
221         },
222
223         
224         insertFirst : function(el, o, returnElement){
225             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
226         },
227
228         
229         append : function(el, o, returnElement){
230             return doInsert(el, o, returnElement, beforeend, '', true);
231         },
232
233         
234         overwrite : function(el, o, returnElement){
235             el = Ext.getDom(el);
236             el.innerHTML = createHtml(o);
237             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
238         },
239
240         createHtml : createHtml
241     };
242     return pub;
243 }();
244
245 Ext.apply(Ext.DomHelper,
246 function(){
247     var pub,
248         afterbegin = 'afterbegin',
249         afterend = 'afterend',
250         beforebegin = 'beforebegin',
251         beforeend = 'beforeend',
252         confRe = /tag|children|cn|html$/i;
253
254     
255     function doInsert(el, o, returnElement, pos, sibling, append){
256         el = Ext.getDom(el);
257         var newNode;
258         if (pub.useDom) {
259             newNode = createDom(o, null);
260             if (append) {
261                 el.appendChild(newNode);
262             } else {
263                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
264             }
265         } else {
266             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
267         }
268         return returnElement ? Ext.get(newNode, true) : newNode;
269     }
270
271     
272     
273     function createDom(o, parentNode){
274         var el,
275             doc = document,
276             useSet,
277             attr,
278             val,
279             cn;
280
281         if (Ext.isArray(o)) {                       
282             el = doc.createDocumentFragment(); 
283             for (var i = 0, l = o.length; i < l; i++) {
284                 createDom(o[i], el);
285             }
286         } else if (typeof o == 'string') {         
287             el = doc.createTextNode(o);
288         } else {
289             el = doc.createElement( o.tag || 'div' );
290             useSet = !!el.setAttribute; 
291             for (var attr in o) {
292                 if(!confRe.test(attr)){
293                     val = o[attr];
294                     if(attr == 'cls'){
295                         el.className = val;
296                     }else{
297                         if(useSet){
298                             el.setAttribute(attr, val);
299                         }else{
300                             el[attr] = val;
301                         }
302                     }
303                 }
304             }
305             Ext.DomHelper.applyStyles(el, o.style);
306
307             if ((cn = o.children || o.cn)) {
308                 createDom(cn, el);
309             } else if (o.html) {
310                 el.innerHTML = o.html;
311             }
312         }
313         if(parentNode){
314            parentNode.appendChild(el);
315         }
316         return el;
317     }
318
319     pub = {
320         
321         createTemplate : function(o){
322             var html = Ext.DomHelper.createHtml(o);
323             return new Ext.Template(html);
324         },
325
326         
327         useDom : false,
328
329         
330         insertBefore : function(el, o, returnElement){
331             return doInsert(el, o, returnElement, beforebegin);
332         },
333
334         
335         insertAfter : function(el, o, returnElement){
336             return doInsert(el, o, returnElement, afterend, 'nextSibling');
337         },
338
339         
340         insertFirst : function(el, o, returnElement){
341             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
342         },
343
344         
345         append: function(el, o, returnElement){
346             return doInsert(el, o, returnElement, beforeend, '', true);
347         },
348
349         
350         createDom: createDom
351     };
352     return pub;
353 }());
354
355 Ext.Template = function(html){
356     var me = this,
357         a = arguments,
358         buf = [],
359         v;
360
361     if (Ext.isArray(html)) {
362         html = html.join("");
363     } else if (a.length > 1) {
364         for(var i = 0, len = a.length; i < len; i++){
365             v = a[i];
366             if(typeof v == 'object'){
367                 Ext.apply(me, v);
368             } else {
369                 buf.push(v);
370             }
371         };
372         html = buf.join('');
373     }
374
375     
376     me.html = html;
377     
378     if (me.compiled) {
379         me.compile();
380     }
381 };
382 Ext.Template.prototype = {
383     
384     re : /\{([\w-]+)\}/g,
385     
386
387     
388     applyTemplate : function(values){
389         var me = this;
390
391         return me.compiled ?
392                 me.compiled(values) :
393                 me.html.replace(me.re, function(m, name){
394                     return values[name] !== undefined ? values[name] : "";
395                 });
396     },
397
398     
399     set : function(html, compile){
400         var me = this;
401         me.html = html;
402         me.compiled = null;
403         return compile ? me.compile() : me;
404     },
405
406     
407     compile : function(){
408         var me = this,
409             sep = Ext.isGecko ? "+" : ",";
410
411         function fn(m, name){
412             name = "values['" + name + "']";
413             return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
414         }
415
416         eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
417              me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
418              (Ext.isGecko ?  "';};" : "'].join('');};"));
419         return me;
420     },
421
422     
423     insertFirst: function(el, values, returnElement){
424         return this.doInsert('afterBegin', el, values, returnElement);
425     },
426
427     
428     insertBefore: function(el, values, returnElement){
429         return this.doInsert('beforeBegin', el, values, returnElement);
430     },
431
432     
433     insertAfter : function(el, values, returnElement){
434         return this.doInsert('afterEnd', el, values, returnElement);
435     },
436
437     
438     append : function(el, values, returnElement){
439         return this.doInsert('beforeEnd', el, values, returnElement);
440     },
441
442     doInsert : function(where, el, values, returnEl){
443         el = Ext.getDom(el);
444         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
445         return returnEl ? Ext.get(newNode, true) : newNode;
446     },
447
448     
449     overwrite : function(el, values, returnElement){
450         el = Ext.getDom(el);
451         el.innerHTML = this.applyTemplate(values);
452         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
453     }
454 };
455
456 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
457
458
459 Ext.Template.from = function(el, config){
460     el = Ext.getDom(el);
461     return new Ext.Template(el.value || el.innerHTML, config || '');
462 };
463
464 Ext.apply(Ext.Template.prototype, {
465     
466     disableFormats : false,
467     
468
469     
470     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
471     argsRe : /^\s*['"](.*)["']\s*$/,
472     compileARe : /\\/g,
473     compileBRe : /(\r\n|\n)/g,
474     compileCRe : /'/g,
475
476     /**
477      * Returns an HTML fragment of this template with the specified values applied.
478      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
479      * @return {String} The HTML fragment
480      * @hide repeat doc
481      */
482     applyTemplate : function(values){
483         var me = this,
484             useF = me.disableFormats !== true,
485             fm = Ext.util.Format,
486             tpl = me;
487
488         if(me.compiled){
489             return me.compiled(values);
490         }
491         function fn(m, name, format, args){
492             if (format && useF) {
493                 if (format.substr(0, 5) == "this.") {
494                     return tpl.call(format.substr(5), values[name], values);
495                 } else {
496                     if (args) {
497                         // quoted values are required for strings in compiled templates,
498                         // but for non compiled we need to strip them
499                         // quoted reversed for jsmin
500                         var re = me.argsRe;
501                         args = args.split(',');
502                         for(var i = 0, len = args.length; i < len; i++){
503                             args[i] = args[i].replace(re, "$1");
504                         }
505                         args = [values[name]].concat(args);
506                     } else {
507                         args = [values[name]];
508                     }
509                     return fm[format].apply(fm, args);
510                 }
511             } else {
512                 return values[name] !== undefined ? values[name] : "";
513             }
514         }
515         return me.html.replace(me.re, fn);
516     },
517
518     /**
519      * Compiles the template into an internal function, eliminating the RegEx overhead.
520      * @return {Ext.Template} this
521      * @hide repeat doc
522      */
523     compile : function(){
524         var me = this,
525             fm = Ext.util.Format,
526             useF = me.disableFormats !== true,
527             sep = Ext.isGecko ? "+" : ",",
528             body;
529
530         function fn(m, name, format, args){
531             if(format && useF){
532                 args = args ? ',' + args : "";
533                 if(format.substr(0, 5) != "this."){
534                     format = "fm." + format + '(';
535                 }else{
536                     format = 'this.call("'+ format.substr(5) + '", ';
537                     args = ", values";
538                 }
539             }else{
540                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
541             }
542             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
543         }
544
545         // branched to use + in gecko and [].join() in others
546         if(Ext.isGecko){
547             body = "this.compiled = function(values){ return '" +
548                    me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
549                     "';};";
550         }else{
551             body = ["this.compiled = function(values){ return ['"];
552             body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
553             body.push("'].join('');};");
554             body = body.join('');
555         }
556         eval(body);
557         return me;
558     },
559
560     // private function used to call members
561     call : function(fnName, value, allValues){
562         return this[fnName](value, allValues);
563     }
564 });
565 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
566 /*
567  * This is code is also distributed under MIT license for use
568  * with jQuery and prototype JavaScript libraries.
569  */
570 /**
571  * @class Ext.DomQuery
572 Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
573 <p>
574 DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#selectors">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
575
576 <p>
577 All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
578 </p>
579 <h4>Element Selectors:</h4>
580 <ul class="list">
581     <li> <b>*</b> any element</li>
582     <li> <b>E</b> an element with the tag E</li>
583     <li> <b>E F</b> All descendent elements of E that have the tag F</li>
584     <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
585     <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
586     <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
587 </ul>
588 <h4>Attribute Selectors:</h4>
589 <p>The use of &#64; and quotes are optional. For example, div[&#64;foo='bar'] is also a valid attribute selector.</p>
590 <ul class="list">
591     <li> <b>E[foo]</b> has an attribute "foo"</li>
592     <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
593     <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
594     <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
595     <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
596     <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
597     <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
598 </ul>
599 <h4>Pseudo Classes:</h4>
600 <ul class="list">
601     <li> <b>E:first-child</b> E is the first child of its parent</li>
602     <li> <b>E:last-child</b> E is the last child of its parent</li>
603     <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
604     <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
605     <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
606     <li> <b>E:only-child</b> E is the only child of its parent</li>
607     <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
608     <li> <b>E:first</b> the first E in the resultset</li>
609     <li> <b>E:last</b> the last E in the resultset</li>
610     <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
611     <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
612     <li> <b>E:even</b> shortcut for :nth-child(even)</li>
613     <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
614     <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
615     <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
616     <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
617     <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
618     <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
619     <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3
620 </ul>
621 <h4>CSS Value Selectors:</h4>
622 <ul class="list">
623     <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
624     <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
625     <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
626     <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
627     <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
628     <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
629 </ul>
630  * @singleton
631  */
632 Ext.DomQuery = function(){
633     var cache = {}, 
634         simpleCache = {}, 
635         valueCache = {},
636         nonSpace = /\S/,
637         trimRe = /^\s+|\s+$/g,
638         tplRe = /\{(\d+)\}/g,
639         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
640         tagTokenRe = /^(#)?([\w-\*]+)/,
641         nthRe = /(\d*)n\+?(\d*)/, 
642         nthRe2 = /\D/,
643         
644         
645         
646         isIE = window.ActiveXObject ? true : false,
647         key = 30803;
648     
649     
650     
651     eval("var batch = 30803;");         
652
653     
654     
655     function child(parent, index){
656         var i = 0,
657             n = parent.firstChild;
658         while(n){
659             if(n.nodeType == 1){
660                if(++i == index){
661                    return n;
662                }
663             }
664             n = n.nextSibling;
665         }
666         return null;
667     }
668
669     
670     function next(n){   
671         while((n = n.nextSibling) && n.nodeType != 1);
672         return n;
673     }
674
675     
676     function prev(n){
677         while((n = n.previousSibling) && n.nodeType != 1);
678         return n;
679     }
680
681     
682     
683     function children(parent){
684         var n = parent.firstChild,
685             nodeIndex = -1,
686             nextNode;
687         while(n){
688             nextNode = n.nextSibling;
689             
690             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
691                 parent.removeChild(n);
692             }else{
693                 
694                 n.nodeIndex = ++nodeIndex;
695             }
696             n = nextNode;
697         }
698         return this;
699     }
700
701
702     
703     
704     function byClassName(nodeSet, cls){
705         if(!cls){
706             return nodeSet;
707         }
708         var result = [], ri = -1;
709         for(var i = 0, ci; ci = nodeSet[i]; i++){
710             if((' '+ci.className+' ').indexOf(cls) != -1){
711                 result[++ri] = ci;
712             }
713         }
714         return result;
715     };
716
717     function attrValue(n, attr){
718         
719         if(!n.tagName && typeof n.length != "undefined"){
720             n = n[0];
721         }
722         if(!n){
723             return null;
724         }
725
726         if(attr == "for"){
727             return n.htmlFor;
728         }
729         if(attr == "class" || attr == "className"){
730             return n.className;
731         }
732         return n.getAttribute(attr) || n[attr];
733
734     };
735
736
737     
738     
739     
740     function getNodes(ns, mode, tagName){
741         var result = [], ri = -1, cs;
742         if(!ns){
743             return result;
744         }
745         tagName = tagName || "*";
746         
747         if(typeof ns.getElementsByTagName != "undefined"){
748             ns = [ns];
749         }
750         
751         
752         
753         if(!mode){
754             for(var i = 0, ni; ni = ns[i]; i++){
755                 cs = ni.getElementsByTagName(tagName);
756                 for(var j = 0, ci; ci = cs[j]; j++){
757                     result[++ri] = ci;
758                 }
759             }
760         
761         
762         } else if(mode == "/" || mode == ">"){
763             var utag = tagName.toUpperCase();
764             for(var i = 0, ni, cn; ni = ns[i]; i++){
765                 cn = ni.childNodes;
766                 for(var j = 0, cj; cj = cn[j]; j++){
767                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
768                         result[++ri] = cj;
769                     }
770                 }
771             }
772         
773         
774         }else if(mode == "+"){
775             var utag = tagName.toUpperCase();
776             for(var i = 0, n; n = ns[i]; i++){
777                 while((n = n.nextSibling) && n.nodeType != 1);
778                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
779                     result[++ri] = n;
780                 }
781             }
782         
783         
784         }else if(mode == "~"){
785             var utag = tagName.toUpperCase();
786             for(var i = 0, n; n = ns[i]; i++){
787                 while((n = n.nextSibling)){
788                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
789                         result[++ri] = n;
790                     }
791                 }
792             }
793         }
794         return result;
795     }
796
797     function concat(a, b){
798         if(b.slice){
799             return a.concat(b);
800         }
801         for(var i = 0, l = b.length; i < l; i++){
802             a[a.length] = b[i];
803         }
804         return a;
805     }
806
807     function byTag(cs, tagName){
808         if(cs.tagName || cs == document){
809             cs = [cs];
810         }
811         if(!tagName){
812             return cs;
813         }
814         var result = [], ri = -1;
815         tagName = tagName.toLowerCase();
816         for(var i = 0, ci; ci = cs[i]; i++){
817             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
818                 result[++ri] = ci;
819             }
820         }
821         return result;
822     }
823
824     function byId(cs, id){
825         if(cs.tagName || cs == document){
826             cs = [cs];
827         }
828         if(!id){
829             return cs;
830         }
831         var result = [], ri = -1;
832         for(var i = 0, ci; ci = cs[i]; i++){
833             if(ci && ci.id == id){
834                 result[++ri] = ci;
835                 return result;
836             }
837         }
838         return result;
839     }
840
841     
842     
843     function byAttribute(cs, attr, value, op, custom){
844         var result = [], 
845             ri = -1, 
846             useGetStyle = custom == "{",            
847             fn = Ext.DomQuery.operators[op],        
848             a,      
849             innerHTML;
850         for(var i = 0, ci; ci = cs[i]; i++){
851             
852             if(ci.nodeType != 1){
853                 continue;
854             }
855             
856             innerHTML = ci.innerHTML;
857             
858             if(innerHTML !== null && innerHTML !== undefined){
859                 if(useGetStyle){
860                     a = Ext.DomQuery.getStyle(ci, attr);
861                 } else if (attr == "class" || attr == "className"){
862                     a = ci.className;
863                 } else if (attr == "for"){
864                     a = ci.htmlFor;
865                 } else if (attr == "href"){
866                     
867                     
868                     a = ci.getAttribute("href", 2);
869                 } else{
870                     a = ci.getAttribute(attr);
871                 }
872             }else{
873                 a = ci.getAttribute(attr);
874             }
875             if((fn && fn(a, value)) || (!fn && a)){
876                 result[++ri] = ci;
877             }
878         }
879         return result;
880     }
881
882     function byPseudo(cs, name, value){
883         return Ext.DomQuery.pseudos[name](cs, value);
884     }
885
886     function nodupIEXml(cs){
887         var d = ++key, 
888             r;
889         cs[0].setAttribute("_nodup", d);
890         r = [cs[0]];
891         for(var i = 1, len = cs.length; i < len; i++){
892             var c = cs[i];
893             if(!c.getAttribute("_nodup") != d){
894                 c.setAttribute("_nodup", d);
895                 r[r.length] = c;
896             }
897         }
898         for(var i = 0, len = cs.length; i < len; i++){
899             cs[i].removeAttribute("_nodup");
900         }
901         return r;
902     }
903
904     function nodup(cs){
905         if(!cs){
906             return [];
907         }
908         var len = cs.length, c, i, r = cs, cj, ri = -1;
909         if(!len || typeof cs.nodeType != "undefined" || len == 1){
910             return cs;
911         }
912         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
913             return nodupIEXml(cs);
914         }
915         var d = ++key;
916         cs[0]._nodup = d;
917         for(i = 1; c = cs[i]; i++){
918             if(c._nodup != d){
919                 c._nodup = d;
920             }else{
921                 r = [];
922                 for(var j = 0; j < i; j++){
923                     r[++ri] = cs[j];
924                 }
925                 for(j = i+1; cj = cs[j]; j++){
926                     if(cj._nodup != d){
927                         cj._nodup = d;
928                         r[++ri] = cj;
929                     }
930                 }
931                 return r;
932             }
933         }
934         return r;
935     }
936
937     function quickDiffIEXml(c1, c2){
938         var d = ++key,
939             r = [];
940         for(var i = 0, len = c1.length; i < len; i++){
941             c1[i].setAttribute("_qdiff", d);
942         }        
943         for(var i = 0, len = c2.length; i < len; i++){
944             if(c2[i].getAttribute("_qdiff") != d){
945                 r[r.length] = c2[i];
946             }
947         }
948         for(var i = 0, len = c1.length; i < len; i++){
949            c1[i].removeAttribute("_qdiff");
950         }
951         return r;
952     }
953
954     function quickDiff(c1, c2){
955         var len1 = c1.length,
956                 d = ++key,
957                 r = [];
958         if(!len1){
959             return c2;
960         }
961         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
962             return quickDiffIEXml(c1, c2);
963         }        
964         for(var i = 0; i < len1; i++){
965             c1[i]._qdiff = d;
966         }        
967         for(var i = 0, len = c2.length; i < len; i++){
968             if(c2[i]._qdiff != d){
969                 r[r.length] = c2[i];
970             }
971         }
972         return r;
973     }
974
975     function quickId(ns, mode, root, id){
976         if(ns == root){
977            var d = root.ownerDocument || root;
978            return d.getElementById(id);
979         }
980         ns = getNodes(ns, mode, "*");
981         return byId(ns, id);
982     }
983
984     return {
985         getStyle : function(el, name){
986             return Ext.fly(el).getStyle(name);
987         },
988         
989         compile : function(path, type){
990             type = type || "select";
991
992             
993             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
994                 mode,           
995                 lastPath,
996                 matchers = Ext.DomQuery.matchers,
997                 matchersLn = matchers.length,
998                 modeMatch,
999                 
1000                 lmode = path.match(modeRe);
1001             
1002             if(lmode && lmode[1]){
1003                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
1004                 path = path.replace(lmode[1], "");
1005             }
1006             
1007             
1008             while(path.substr(0, 1)=="/"){
1009                 path = path.substr(1);
1010             }
1011
1012             while(path && lastPath != path){
1013                 lastPath = path;
1014                 var tokenMatch = path.match(tagTokenRe);
1015                 if(type == "select"){
1016                     if(tokenMatch){
1017                         
1018                         if(tokenMatch[1] == "#"){
1019                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                 
1020                         }else{
1021                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
1022                         }
1023                         path = path.replace(tokenMatch[0], "");
1024                     }else if(path.substr(0, 1) != '@'){
1025                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
1026                     }
1027                 
1028                 }else{
1029                     if(tokenMatch){
1030                         if(tokenMatch[1] == "#"){
1031                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
1032                         }else{
1033                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
1034                         }
1035                         path = path.replace(tokenMatch[0], "");
1036                     }
1037                 }
1038                 while(!(modeMatch = path.match(modeRe))){
1039                     var matched = false;
1040                     for(var j = 0; j < matchersLn; j++){
1041                         var t = matchers[j];
1042                         var m = path.match(t.re);
1043                         if(m){
1044                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
1045                                 return m[i];
1046                             });
1047                             path = path.replace(m[0], "");
1048                             matched = true;
1049                             break;
1050                         }
1051                     }
1052                     
1053                     if(!matched){
1054                         throw 'Error parsing selector, parsing failed at "' + path + '"';
1055                     }
1056                 }
1057                 if(modeMatch[1]){
1058                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
1059                     path = path.replace(modeMatch[1], "");
1060                 }
1061             }
1062             
1063             fn[fn.length] = "return nodup(n);\n}";
1064             
1065             
1066             eval(fn.join(""));
1067             return f;
1068         },
1069
1070         
1071         jsSelect: function(path, root, type){
1072             
1073             root = root || document;
1074             
1075             if(typeof root == "string"){
1076                 root = document.getElementById(root);
1077             }
1078             var paths = path.split(","),
1079                 results = [];
1080                 
1081             
1082             for(var i = 0, len = paths.length; i < len; i++){           
1083                 var subPath = paths[i].replace(trimRe, "");
1084                 
1085                 if(!cache[subPath]){
1086                     cache[subPath] = Ext.DomQuery.compile(subPath);
1087                     if(!cache[subPath]){
1088                         throw subPath + " is not a valid selector";
1089                     }
1090                 }
1091                 var result = cache[subPath](root);
1092                 if(result && result != document){
1093                     results = results.concat(result);
1094                 }
1095             }
1096             
1097             
1098             
1099             if(paths.length > 1){
1100                 return nodup(results);
1101             }
1102             return results;
1103         },
1104         isXml: function(el) {
1105             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
1106             return docEl ? docEl.nodeName !== "HTML" : false;
1107         },
1108         select : document.querySelectorAll ? function(path, root, type) {
1109             root = root || document;
1110             if (!Ext.DomQuery.isXml(root)) {
1111                 try {
1112                     var cs = root.querySelectorAll(path);
1113                     return Ext.toArray(cs);
1114                 }
1115                 catch (ex) {}           
1116             }       
1117             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1118         } : function(path, root, type) {
1119             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1120         },
1121
1122         
1123         selectNode : function(path, root){
1124             return Ext.DomQuery.select(path, root)[0];
1125         },
1126
1127         
1128         selectValue : function(path, root, defaultValue){
1129             path = path.replace(trimRe, "");
1130             if(!valueCache[path]){
1131                 valueCache[path] = Ext.DomQuery.compile(path, "select");
1132             }
1133             var n = valueCache[path](root), v;
1134             n = n[0] ? n[0] : n;
1135                     
1136             
1137             
1138             
1139             
1140             if (typeof n.normalize == 'function') n.normalize();
1141             
1142             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
1143             return ((v === null||v === undefined||v==='') ? defaultValue : v);
1144         },
1145
1146         
1147         selectNumber : function(path, root, defaultValue){
1148             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
1149             return parseFloat(v);
1150         },
1151
1152         
1153         is : function(el, ss){
1154             if(typeof el == "string"){
1155                 el = document.getElementById(el);
1156             }
1157             var isArray = Ext.isArray(el),
1158                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
1159             return isArray ? (result.length == el.length) : (result.length > 0);
1160         },
1161
1162         
1163         filter : function(els, ss, nonMatches){
1164             ss = ss.replace(trimRe, "");
1165             if(!simpleCache[ss]){
1166                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
1167             }
1168             var result = simpleCache[ss](els);
1169             return nonMatches ? quickDiff(result, els) : result;
1170         },
1171
1172         
1173         matchers : [{
1174                 re: /^\.([\w-]+)/,
1175                 select: 'n = byClassName(n, " {1} ");'
1176             }, {
1177                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
1178                 select: 'n = byPseudo(n, "{1}", "{2}");'
1179             },{
1180                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
1181                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
1182             }, {
1183                 re: /^#([\w-]+)/,
1184                 select: 'n = byId(n, "{1}");'
1185             },{
1186                 re: /^@([\w-]+)/,
1187                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
1188             }
1189         ],
1190
1191         
1192         operators : {
1193             "=" : function(a, v){
1194                 return a == v;
1195             },
1196             "!=" : function(a, v){
1197                 return a != v;
1198             },
1199             "^=" : function(a, v){
1200                 return a && a.substr(0, v.length) == v;
1201             },
1202             "$=" : function(a, v){
1203                 return a && a.substr(a.length-v.length) == v;
1204             },
1205             "*=" : function(a, v){
1206                 return a && a.indexOf(v) !== -1;
1207             },
1208             "%=" : function(a, v){
1209                 return (a % v) == 0;
1210             },
1211             "|=" : function(a, v){
1212                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
1213             },
1214             "~=" : function(a, v){
1215                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
1216             }
1217         },
1218
1219         
1220         pseudos : {
1221             "first-child" : function(c){
1222                 var r = [], ri = -1, n;
1223                 for(var i = 0, ci; ci = n = c[i]; i++){
1224                     while((n = n.previousSibling) && n.nodeType != 1);
1225                     if(!n){
1226                         r[++ri] = ci;
1227                     }
1228                 }
1229                 return r;
1230             },
1231
1232             "last-child" : function(c){
1233                 var r = [], ri = -1, n;
1234                 for(var i = 0, ci; ci = n = c[i]; i++){
1235                     while((n = n.nextSibling) && n.nodeType != 1);
1236                     if(!n){
1237                         r[++ri] = ci;
1238                     }
1239                 }
1240                 return r;
1241             },
1242
1243             "nth-child" : function(c, a) {
1244                 var r = [], ri = -1,
1245                         m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
1246                         f = (m[1] || 1) - 0, l = m[2] - 0;
1247                 for(var i = 0, n; n = c[i]; i++){
1248                     var pn = n.parentNode;
1249                     if (batch != pn._batch) {
1250                         var j = 0;
1251                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1252                             if(cn.nodeType == 1){
1253                                cn.nodeIndex = ++j;
1254                             }
1255                         }
1256                         pn._batch = batch;
1257                     }
1258                     if (f == 1) {
1259                         if (l == 0 || n.nodeIndex == l){
1260                             r[++ri] = n;
1261                         }
1262                     } else if ((n.nodeIndex + l) % f == 0){
1263                         r[++ri] = n;
1264                     }
1265                 }
1266
1267                 return r;
1268             },
1269
1270             "only-child" : function(c){
1271                 var r = [], ri = -1;;
1272                 for(var i = 0, ci; ci = c[i]; i++){
1273                     if(!prev(ci) && !next(ci)){
1274                         r[++ri] = ci;
1275                     }
1276                 }
1277                 return r;
1278             },
1279
1280             "empty" : function(c){
1281                 var r = [], ri = -1;
1282                 for(var i = 0, ci; ci = c[i]; i++){
1283                     var cns = ci.childNodes, j = 0, cn, empty = true;
1284                     while(cn = cns[j]){
1285                         ++j;
1286                         if(cn.nodeType == 1 || cn.nodeType == 3){
1287                             empty = false;
1288                             break;
1289                         }
1290                     }
1291                     if(empty){
1292                         r[++ri] = ci;
1293                     }
1294                 }
1295                 return r;
1296             },
1297
1298             "contains" : function(c, v){
1299                 var r = [], ri = -1;
1300                 for(var i = 0, ci; ci = c[i]; i++){
1301                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1302                         r[++ri] = ci;
1303                     }
1304                 }
1305                 return r;
1306             },
1307
1308             "nodeValue" : function(c, v){
1309                 var r = [], ri = -1;
1310                 for(var i = 0, ci; ci = c[i]; i++){
1311                     if(ci.firstChild && ci.firstChild.nodeValue == v){
1312                         r[++ri] = ci;
1313                     }
1314                 }
1315                 return r;
1316             },
1317
1318             "checked" : function(c){
1319                 var r = [], ri = -1;
1320                 for(var i = 0, ci; ci = c[i]; i++){
1321                     if(ci.checked == true){
1322                         r[++ri] = ci;
1323                     }
1324                 }
1325                 return r;
1326             },
1327
1328             "not" : function(c, ss){
1329                 return Ext.DomQuery.filter(c, ss, true);
1330             },
1331
1332             "any" : function(c, selectors){
1333                 var ss = selectors.split('|'),
1334                         r = [], ri = -1, s;
1335                 for(var i = 0, ci; ci = c[i]; i++){
1336                     for(var j = 0; s = ss[j]; j++){
1337                         if(Ext.DomQuery.is(ci, s)){
1338                             r[++ri] = ci;
1339                             break;
1340                         }
1341                     }
1342                 }
1343                 return r;
1344             },
1345
1346             "odd" : function(c){
1347                 return this["nth-child"](c, "odd");
1348             },
1349
1350             "even" : function(c){
1351                 return this["nth-child"](c, "even");
1352             },
1353
1354             "nth" : function(c, a){
1355                 return c[a-1] || [];
1356             },
1357
1358             "first" : function(c){
1359                 return c[0] || [];
1360             },
1361
1362             "last" : function(c){
1363                 return c[c.length-1] || [];
1364             },
1365
1366             "has" : function(c, ss){
1367                 var s = Ext.DomQuery.select,
1368                         r = [], ri = -1;
1369                 for(var i = 0, ci; ci = c[i]; i++){
1370                     if(s(ss, ci).length > 0){
1371                         r[++ri] = ci;
1372                     }
1373                 }
1374                 return r;
1375             },
1376
1377             "next" : function(c, ss){
1378                 var is = Ext.DomQuery.is,
1379                         r = [], ri = -1;
1380                 for(var i = 0, ci; ci = c[i]; i++){
1381                     var n = next(ci);
1382                     if(n && is(n, ss)){
1383                         r[++ri] = ci;
1384                     }
1385                 }
1386                 return r;
1387             },
1388
1389             "prev" : function(c, ss){
1390                 var is = Ext.DomQuery.is,
1391                         r = [], ri = -1;
1392                 for(var i = 0, ci; ci = c[i]; i++){
1393                     var n = prev(ci);
1394                     if(n && is(n, ss)){
1395                         r[++ri] = ci;
1396                     }
1397                 }
1398                 return r;
1399             }
1400         }
1401     };
1402 }();
1403
1404
1405 Ext.query = Ext.DomQuery.select;
1406
1407 Ext.util.DelayedTask = function(fn, scope, args){
1408     var me = this,
1409         id,     
1410         call = function(){
1411                 clearInterval(id);
1412                 id = null;
1413                 fn.apply(scope, args || []);
1414             };
1415             
1416     
1417     me.delay = function(delay, newFn, newScope, newArgs){
1418         me.cancel();
1419         fn = newFn || fn;
1420         scope = newScope || scope;
1421         args = newArgs || args;
1422         id = setInterval(call, delay);
1423     };
1424
1425     
1426     me.cancel = function(){
1427         if(id){
1428             clearInterval(id);
1429             id = null;
1430         }
1431     };
1432 };(function(){
1433
1434 var EXTUTIL = Ext.util,
1435     EACH = Ext.each,
1436     TRUE = true,
1437     FALSE = false;
1438
1439 EXTUTIL.Observable = function(){
1440     
1441     var me = this, e = me.events;
1442     if(me.listeners){
1443         me.on(me.listeners);
1444         delete me.listeners;
1445     }
1446     me.events = e || {};
1447 };
1448
1449 EXTUTIL.Observable.prototype = {
1450     
1451     filterOptRe : /^(?:scope|delay|buffer|single)$/,
1452
1453     
1454     fireEvent : function(){
1455         var a = Array.prototype.slice.call(arguments, 0),
1456             ename = a[0].toLowerCase(),
1457             me = this,
1458             ret = TRUE,
1459             ce = me.events[ename],
1460             cc,
1461             q,
1462             c;
1463         if (me.eventsSuspended === TRUE) {
1464             if (q = me.eventQueue) {
1465                 q.push(a);
1466             }
1467         }
1468         else if(typeof ce == 'object') {
1469             if (ce.bubble){
1470                 if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
1471                     return FALSE;
1472                 }
1473                 c = me.getBubbleTarget && me.getBubbleTarget();
1474                 if(c && c.enableBubble) {
1475                     cc = c.events[ename];
1476                     if(!cc || typeof cc != 'object' || !cc.bubble) {
1477                         c.enableBubble(ename);
1478                     }
1479                     return c.fireEvent.apply(c, a);
1480                 }
1481             }
1482             else {
1483                 a.shift();
1484                 ret = ce.fire.apply(ce, a);
1485             }
1486         }
1487         return ret;
1488     },
1489
1490     
1491     addListener : function(eventName, fn, scope, o){
1492         var me = this,
1493             e,
1494             oe,
1495             isF,
1496         ce;
1497         if (typeof eventName == 'object') {
1498             o = eventName;
1499             for (e in o){
1500                 oe = o[e];
1501                 if (!me.filterOptRe.test(e)) {
1502                     me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
1503                 }
1504             }
1505         } else {
1506             eventName = eventName.toLowerCase();
1507             ce = me.events[eventName] || TRUE;
1508             if (typeof ce == 'boolean') {
1509                 me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
1510             }
1511             ce.addListener(fn, scope, typeof o == 'object' ? o : {});
1512         }
1513     },
1514
1515     
1516     removeListener : function(eventName, fn, scope){
1517         var ce = this.events[eventName.toLowerCase()];
1518         if (typeof ce == 'object') {
1519             ce.removeListener(fn, scope);
1520         }
1521     },
1522
1523     
1524     purgeListeners : function(){
1525         var events = this.events,
1526             evt,
1527             key;
1528         for(key in events){
1529             evt = events[key];
1530             if(typeof evt == 'object'){
1531                 evt.clearListeners();
1532             }
1533         }
1534     },
1535
1536     
1537     addEvents : function(o){
1538         var me = this;
1539         me.events = me.events || {};
1540         if (typeof o == 'string') {
1541             var a = arguments,
1542                 i = a.length;
1543             while(i--) {
1544                 me.events[a[i]] = me.events[a[i]] || TRUE;
1545             }
1546         } else {
1547             Ext.applyIf(me.events, o);
1548         }
1549     },
1550
1551     
1552     hasListener : function(eventName){
1553         var e = this.events[eventName.toLowerCase()];
1554         return typeof e == 'object' && e.listeners.length > 0;
1555     },
1556
1557     
1558     suspendEvents : function(queueSuspended){
1559         this.eventsSuspended = TRUE;
1560         if(queueSuspended && !this.eventQueue){
1561             this.eventQueue = [];
1562         }
1563     },
1564
1565     
1566     resumeEvents : function(){
1567         var me = this,
1568             queued = me.eventQueue || [];
1569         me.eventsSuspended = FALSE;
1570         delete me.eventQueue;
1571         EACH(queued, function(e) {
1572             me.fireEvent.apply(me, e);
1573         });
1574     }
1575 };
1576
1577 var OBSERVABLE = EXTUTIL.Observable.prototype;
1578
1579 OBSERVABLE.on = OBSERVABLE.addListener;
1580
1581 OBSERVABLE.un = OBSERVABLE.removeListener;
1582
1583
1584 EXTUTIL.Observable.releaseCapture = function(o){
1585     o.fireEvent = OBSERVABLE.fireEvent;
1586 };
1587
1588 function createTargeted(h, o, scope){
1589     return function(){
1590         if(o.target == arguments[0]){
1591             h.apply(scope, Array.prototype.slice.call(arguments, 0));
1592         }
1593     };
1594 };
1595
1596 function createBuffered(h, o, l, scope){
1597     l.task = new EXTUTIL.DelayedTask();
1598     return function(){
1599         l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
1600     };
1601 };
1602
1603 function createSingle(h, e, fn, scope){
1604     return function(){
1605         e.removeListener(fn, scope);
1606         return h.apply(scope, arguments);
1607     };
1608 };
1609
1610 function createDelayed(h, o, l, scope){
1611     return function(){
1612         var task = new EXTUTIL.DelayedTask();
1613         if(!l.tasks) {
1614             l.tasks = [];
1615         }
1616         l.tasks.push(task);
1617         task.delay(o.delay || 10, h, scope, Array.prototype.slice.call(arguments, 0));
1618     };
1619 };
1620
1621 EXTUTIL.Event = function(obj, name){
1622     this.name = name;
1623     this.obj = obj;
1624     this.listeners = [];
1625 };
1626
1627 EXTUTIL.Event.prototype = {
1628     addListener : function(fn, scope, options){
1629         var me = this,
1630             l;
1631         scope = scope || me.obj;
1632         if(!me.isListening(fn, scope)){
1633             l = me.createListener(fn, scope, options);
1634             if(me.firing){ 
1635                 me.listeners = me.listeners.slice(0);
1636             }
1637             me.listeners.push(l);
1638         }
1639     },
1640
1641     createListener: function(fn, scope, o){
1642         o = o || {}, scope = scope || this.obj;
1643         var l = {
1644             fn: fn,
1645             scope: scope,
1646             options: o
1647         }, h = fn;
1648         if(o.target){
1649             h = createTargeted(h, o, scope);
1650         }
1651         if(o.delay){
1652             h = createDelayed(h, o, l, scope);
1653         }
1654         if(o.single){
1655             h = createSingle(h, this, fn, scope);
1656         }
1657         if(o.buffer){
1658             h = createBuffered(h, o, l, scope);
1659         }
1660         l.fireFn = h;
1661         return l;
1662     },
1663
1664     findListener : function(fn, scope){
1665         var list = this.listeners,
1666             i = list.length,
1667             l;
1668
1669         scope = scope || this.obj;
1670         while(i--){
1671             l = list[i];
1672             if(l){
1673                 if(l.fn == fn && l.scope == scope){
1674                     return i;
1675                 }
1676             }
1677         }
1678         return -1;
1679     },
1680
1681     isListening : function(fn, scope){
1682         return this.findListener(fn, scope) != -1;
1683     },
1684
1685     removeListener : function(fn, scope){
1686         var index,
1687             l,
1688             k,
1689             me = this,
1690             ret = FALSE;
1691         if((index = me.findListener(fn, scope)) != -1){
1692             if (me.firing) {
1693                 me.listeners = me.listeners.slice(0);
1694             }
1695             l = me.listeners[index];
1696             if(l.task) {
1697                 l.task.cancel();
1698                 delete l.task;
1699             }
1700             k = l.tasks && l.tasks.length;
1701             if(k) {
1702                 while(k--) {
1703                     l.tasks[k].cancel();
1704                 }
1705                 delete l.tasks;
1706             }
1707             me.listeners.splice(index, 1);
1708             ret = TRUE;
1709         }
1710         return ret;
1711     },
1712
1713     
1714     clearListeners : function(){
1715         var me = this,
1716             l = me.listeners,
1717             i = l.length;
1718         while(i--) {
1719             me.removeListener(l[i].fn, l[i].scope);
1720         }
1721     },
1722
1723     fire : function(){
1724         var me = this,
1725             listeners = me.listeners,
1726             len = listeners.length,
1727             i = 0,
1728             l;
1729
1730         if(len > 0){
1731             me.firing = TRUE;
1732             var args = Array.prototype.slice.call(arguments, 0);
1733             for (; i < len; i++) {
1734                 l = listeners[i];
1735                 if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
1736                     return (me.firing = FALSE);
1737                 }
1738             }
1739         }
1740         me.firing = FALSE;
1741         return TRUE;
1742     }
1743
1744 };
1745 })();
1746
1747 Ext.apply(Ext.util.Observable.prototype, function(){
1748     
1749     
1750     
1751     function getMethodEvent(method){
1752         var e = (this.methodEvents = this.methodEvents ||
1753         {})[method], returnValue, v, cancel, obj = this;
1754
1755         if (!e) {
1756             this.methodEvents[method] = e = {};
1757             e.originalFn = this[method];
1758             e.methodName = method;
1759             e.before = [];
1760             e.after = [];
1761
1762             var makeCall = function(fn, scope, args){
1763                 if((v = fn.apply(scope || obj, args)) !== undefined){
1764                     if (typeof v == 'object') {
1765                         if(v.returnValue !== undefined){
1766                             returnValue = v.returnValue;
1767                         }else{
1768                             returnValue = v;
1769                         }
1770                         cancel = !!v.cancel;
1771                     }
1772                     else
1773                         if (v === false) {
1774                             cancel = true;
1775                         }
1776                         else {
1777                             returnValue = v;
1778                         }
1779                 }
1780             };
1781
1782             this[method] = function(){
1783                 var args = Array.prototype.slice.call(arguments, 0),
1784                     b;
1785                 returnValue = v = undefined;
1786                 cancel = false;
1787
1788                 for(var i = 0, len = e.before.length; i < len; i++){
1789                     b = e.before[i];
1790                     makeCall(b.fn, b.scope, args);
1791                     if (cancel) {
1792                         return returnValue;
1793                     }
1794                 }
1795
1796                 if((v = e.originalFn.apply(obj, args)) !== undefined){
1797                     returnValue = v;
1798                 }
1799
1800                 for(var i = 0, len = e.after.length; i < len; i++){
1801                     b = e.after[i];
1802                     makeCall(b.fn, b.scope, args);
1803                     if (cancel) {
1804                         return returnValue;
1805                     }
1806                 }
1807                 return returnValue;
1808             };
1809         }
1810         return e;
1811     }
1812
1813     return {
1814         
1815         
1816         
1817         beforeMethod : function(method, fn, scope){
1818             getMethodEvent.call(this, method).before.push({
1819                 fn: fn,
1820                 scope: scope
1821             });
1822         },
1823
1824         
1825         afterMethod : function(method, fn, scope){
1826             getMethodEvent.call(this, method).after.push({
1827                 fn: fn,
1828                 scope: scope
1829             });
1830         },
1831
1832         removeMethodListener: function(method, fn, scope){
1833             var e = this.getMethodEvent(method);
1834             for(var i = 0, len = e.before.length; i < len; i++){
1835                 if(e.before[i].fn == fn && e.before[i].scope == scope){
1836                     e.before.splice(i, 1);
1837                     return;
1838                 }
1839             }
1840             for(var i = 0, len = e.after.length; i < len; i++){
1841                 if(e.after[i].fn == fn && e.after[i].scope == scope){
1842                     e.after.splice(i, 1);
1843                     return;
1844                 }
1845             }
1846         },
1847
1848         
1849         relayEvents : function(o, events){
1850             var me = this;
1851             function createHandler(ename){
1852                 return function(){
1853                     return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
1854                 };
1855             }
1856             for(var i = 0, len = events.length; i < len; i++){
1857                 var ename = events[i];
1858                 me.events[ename] = me.events[ename] || true;
1859                 o.on(ename, createHandler(ename), me);
1860             }
1861         },
1862
1863         
1864         enableBubble : function(events){
1865             var me = this;
1866             if(!Ext.isEmpty(events)){
1867                 events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
1868                 for(var i = 0, len = events.length; i < len; i++){
1869                     var ename = events[i];
1870                     ename = ename.toLowerCase();
1871                     var ce = me.events[ename] || true;
1872                     if (typeof ce == 'boolean') {
1873                         ce = new Ext.util.Event(me, ename);
1874                         me.events[ename] = ce;
1875                     }
1876                     ce.bubble = true;
1877                 }
1878             }
1879         }
1880     };
1881 }());
1882
1883
1884
1885 Ext.util.Observable.capture = function(o, fn, scope){
1886     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
1887 };
1888
1889
1890
1891 Ext.util.Observable.observeClass = function(c, listeners){
1892     if(c){
1893       if(!c.fireEvent){
1894           Ext.apply(c, new Ext.util.Observable());
1895           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
1896       }
1897       if(typeof listeners == 'object'){
1898           c.on(listeners);
1899       }
1900       return c;
1901    }
1902 };
1903
1904
1905 Ext.EventManager = function(){
1906     var docReadyEvent,
1907         docReadyProcId,
1908         docReadyState = false,
1909         DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
1910         E = Ext.lib.Event,
1911         D = Ext.lib.Dom,
1912         DOC = document,
1913         WINDOW = window,
1914         DOMCONTENTLOADED = "DOMContentLoaded",
1915         COMPLETE = 'complete',
1916         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
1917         
1918         specialElCache = [];
1919
1920      function getId(el){
1921         var id = false,
1922             i = 0,
1923             len = specialElCache.length,
1924             id = false,
1925             skip = false,
1926             o;
1927         if(el){
1928             if(el.getElementById || el.navigator){
1929                 
1930                 for(; i < len; ++i){
1931                     o = specialElCache[i];
1932                     if(o.el === el){
1933                         id = o.id;
1934                         break;
1935                     }
1936                 }
1937                 if(!id){
1938                     
1939                     id = Ext.id(el);
1940                     specialElCache.push({
1941                         id: id,
1942                         el: el
1943                     });
1944                     skip = true;
1945                 }
1946             }else{
1947                 id = Ext.id(el);
1948             }
1949             if(!Ext.elCache[id]){
1950                 Ext.Element.addToCache(new Ext.Element(el), id);
1951                 if(skip){
1952                     Ext.elCache[id].skipGC = true;
1953                 }
1954             }
1955         }
1956         return id;
1957      };
1958
1959     
1960     function addListener(el, ename, fn, task, wrap, scope){
1961         el = Ext.getDom(el);
1962         var id = getId(el),
1963             es = Ext.elCache[id].events,
1964             wfn;
1965
1966         wfn = E.on(el, ename, wrap);
1967         es[ename] = es[ename] || [];
1968
1969         
1970         es[ename].push([fn, wrap, scope, wfn, task]);
1971
1972         
1973         
1974
1975         
1976         if(el.addEventListener && ename == "mousewheel"){
1977             var args = ["DOMMouseScroll", wrap, false];
1978             el.addEventListener.apply(el, args);
1979             Ext.EventManager.addListener(WINDOW, 'unload', function(){
1980                 el.removeEventListener.apply(el, args);
1981             });
1982         }
1983
1984         
1985         if(el == DOC && ename == "mousedown"){
1986             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
1987         }
1988     };
1989
1990     function doScrollChk(){
1991         
1992         if(window != top){
1993             return false;
1994         }
1995
1996         try{
1997             DOC.documentElement.doScroll('left');
1998         }catch(e){
1999              return false;
2000         }
2001
2002         fireDocReady();
2003         return true;
2004     }
2005     
2006     function checkReadyState(e){
2007
2008         if(Ext.isIE && doScrollChk()){
2009             return true;
2010         }
2011         if(DOC.readyState == COMPLETE){
2012             fireDocReady();
2013             return true;
2014         }
2015         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
2016         return false;
2017     }
2018
2019     var styles;
2020     function checkStyleSheets(e){
2021         styles || (styles = Ext.query('style, link[rel=stylesheet]'));
2022         if(styles.length == DOC.styleSheets.length){
2023             fireDocReady();
2024             return true;
2025         }
2026         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
2027         return false;
2028     }
2029
2030     function OperaDOMContentLoaded(e){
2031         DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
2032         checkStyleSheets();
2033     }
2034
2035     function fireDocReady(e){
2036         if(!docReadyState){
2037             docReadyState = true; 
2038
2039             if(docReadyProcId){
2040                 clearTimeout(docReadyProcId);
2041             }
2042             if(DETECT_NATIVE) {
2043                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
2044             }
2045             if(Ext.isIE && checkReadyState.bindIE){  
2046                 DOC.detachEvent('onreadystatechange', checkReadyState);
2047             }
2048             E.un(WINDOW, "load", arguments.callee);
2049         }
2050         if(docReadyEvent && !Ext.isReady){
2051             Ext.isReady = true;
2052             docReadyEvent.fire();
2053             docReadyEvent.listeners = [];
2054         }
2055
2056     };
2057
2058     function initDocReady(){
2059         docReadyEvent || (docReadyEvent = new Ext.util.Event());
2060         if (DETECT_NATIVE) {
2061             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
2062         }
2063         
2064         if (Ext.isIE){
2065             
2066             
2067             if(!checkReadyState()){
2068                 checkReadyState.bindIE = true;
2069                 DOC.attachEvent('onreadystatechange', checkReadyState);
2070             }
2071
2072         }else if(Ext.isOpera ){
2073             
2074
2075             
2076             (DOC.readyState == COMPLETE && checkStyleSheets()) ||
2077                 DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
2078
2079         }else if (Ext.isWebKit){
2080             
2081             checkReadyState();
2082         }
2083         
2084         E.on(WINDOW, "load", fireDocReady);
2085     };
2086
2087     function createTargeted(h, o){
2088         return function(){
2089             var args = Ext.toArray(arguments);
2090             if(o.target == Ext.EventObject.setEvent(args[0]).target){
2091                 h.apply(this, args);
2092             }
2093         };
2094     };
2095
2096     function createBuffered(h, o, task){
2097         return function(e){
2098             
2099             task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
2100         };
2101     };
2102
2103     function createSingle(h, el, ename, fn, scope){
2104         return function(e){
2105             Ext.EventManager.removeListener(el, ename, fn, scope);
2106             h(e);
2107         };
2108     };
2109
2110     function createDelayed(h, o, fn){
2111         return function(e){
2112             var task = new Ext.util.DelayedTask(h);
2113             if(!fn.tasks) {
2114                 fn.tasks = [];
2115             }
2116             fn.tasks.push(task);
2117             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
2118         };
2119     };
2120
2121     function listen(element, ename, opt, fn, scope){
2122         var o = (!opt || typeof opt == "boolean") ? {} : opt,
2123             el = Ext.getDom(element), task;
2124
2125         fn = fn || o.fn;
2126         scope = scope || o.scope;
2127
2128         if(!el){
2129             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
2130         }
2131         function h(e){
2132             
2133             if(!Ext){
2134                 return;
2135             }
2136             e = Ext.EventObject.setEvent(e);
2137             var t;
2138             if (o.delegate) {
2139                 if(!(t = e.getTarget(o.delegate, el))){
2140                     return;
2141                 }
2142             } else {
2143                 t = e.target;
2144             }
2145             if (o.stopEvent) {
2146                 e.stopEvent();
2147             }
2148             if (o.preventDefault) {
2149                e.preventDefault();
2150             }
2151             if (o.stopPropagation) {
2152                 e.stopPropagation();
2153             }
2154             if (o.normalized) {
2155                 e = e.browserEvent;
2156             }
2157
2158             fn.call(scope || el, e, t, o);
2159         };
2160         if(o.target){
2161             h = createTargeted(h, o);
2162         }
2163         if(o.delay){
2164             h = createDelayed(h, o, fn);
2165         }
2166         if(o.single){
2167             h = createSingle(h, el, ename, fn, scope);
2168         }
2169         if(o.buffer){
2170             task = new Ext.util.DelayedTask(h);
2171             h = createBuffered(h, o, task);
2172         }
2173
2174         addListener(el, ename, fn, task, h, scope);
2175         return h;
2176     };
2177
2178     var pub = {
2179         
2180         addListener : function(element, eventName, fn, scope, options){
2181             if(typeof eventName == 'object'){
2182                 var o = eventName, e, val;
2183                 for(e in o){
2184                     val = o[e];
2185                     if(!propRe.test(e)){
2186                         if(Ext.isFunction(val)){
2187                             
2188                             listen(element, e, o, val, o.scope);
2189                         }else{
2190                             
2191                             listen(element, e, val);
2192                         }
2193                     }
2194                 }
2195             } else {
2196                 listen(element, eventName, options, fn, scope);
2197             }
2198         },
2199
2200         
2201         removeListener : function(el, eventName, fn, scope){
2202             el = Ext.getDom(el);
2203             var id = getId(el),
2204                 f = el && (Ext.elCache[id].events)[eventName] || [],
2205                 wrap, i, l, k, len, fnc;
2206
2207             for (i = 0, len = f.length; i < len; i++) {
2208
2209                 
2210                 if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
2211                     if(fnc[4]) {
2212                         fnc[4].cancel();
2213                     }
2214                     k = fn.tasks && fn.tasks.length;
2215                     if(k) {
2216                         while(k--) {
2217                             fn.tasks[k].cancel();
2218                         }
2219                         delete fn.tasks;
2220                     }
2221                     wrap = fnc[1];
2222                     E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
2223
2224                     
2225                     if(wrap && el.addEventListener && eventName == "mousewheel"){
2226                         el.removeEventListener("DOMMouseScroll", wrap, false);
2227                     }
2228
2229                     
2230                     if(wrap && el == DOC && eventName == "mousedown"){
2231                         Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
2232                     }
2233
2234                     f.splice(i, 1);
2235                     if (f.length === 0) {
2236                         delete Ext.elCache[id].events[eventName];
2237                     }
2238                     for (k in Ext.elCache[id].events) {
2239                         return false;
2240                     }
2241                     Ext.elCache[id].events = {};
2242                     return false;
2243                 }
2244             }
2245         },
2246
2247         
2248         removeAll : function(el){
2249             el = Ext.getDom(el);
2250             var id = getId(el),
2251                 ec = Ext.elCache[id] || {},
2252                 es = ec.events || {},
2253                 f, i, len, ename, fn, k, wrap;
2254
2255             for(ename in es){
2256                 if(es.hasOwnProperty(ename)){
2257                     f = es[ename];
2258                     
2259                     for (i = 0, len = f.length; i < len; i++) {
2260                         fn = f[i];
2261                         if(fn[4]) {
2262                             fn[4].cancel();
2263                         }
2264                         if(fn[0].tasks && (k = fn[0].tasks.length)) {
2265                             while(k--) {
2266                                 fn[0].tasks[k].cancel();
2267                             }
2268                             delete fn.tasks;
2269                         }
2270                         wrap =  fn[1];
2271                         E.un(el, ename, E.extAdapter ? fn[3] : wrap);
2272
2273                         
2274                         if(el.addEventListener && wrap && ename == "mousewheel"){
2275                             el.removeEventListener("DOMMouseScroll", wrap, false);
2276                         }
2277
2278                         
2279                         if(wrap && el == DOC &&  ename == "mousedown"){
2280                             Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
2281                         }
2282                     }
2283                 }
2284             }
2285             if (Ext.elCache[id]) {
2286                 Ext.elCache[id].events = {};
2287             }
2288         },
2289
2290         getListeners : function(el, eventName) {
2291             el = Ext.getDom(el);
2292             var id = getId(el),
2293                 ec = Ext.elCache[id] || {},
2294                 es = ec.events || {},
2295                 results = [];
2296             if (es && es[eventName]) {
2297                 return es[eventName];
2298             } else {
2299                 return null;
2300             }
2301         },
2302
2303         purgeElement : function(el, recurse, eventName) {
2304             el = Ext.getDom(el);
2305             var id = getId(el),
2306                 ec = Ext.elCache[id] || {},
2307                 es = ec.events || {},
2308                 i, f, len;
2309             if (eventName) {
2310                 if (es && es.hasOwnProperty(eventName)) {
2311                     f = es[eventName];
2312                     for (i = 0, len = f.length; i < len; i++) {
2313                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
2314                     }
2315                 }
2316             } else {
2317                 Ext.EventManager.removeAll(el);
2318             }
2319             if (recurse && el && el.childNodes) {
2320                 for (i = 0, len = el.childNodes.length; i < len; i++) {
2321                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
2322                 }
2323             }
2324         },
2325
2326         _unload : function() {
2327             var el;
2328             for (el in Ext.elCache) {
2329                 Ext.EventManager.removeAll(el);
2330             }
2331             delete Ext.elCache;
2332             delete Ext.Element._flyweights;
2333
2334             
2335             var c,
2336                 conn,
2337                 tid,
2338                 ajax = Ext.lib.Ajax;
2339             (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
2340             for (tid in conn) {
2341                 c = conn[tid];
2342                 if (c) {
2343                     ajax.abort({conn: c, tId: tid});
2344                 }
2345             }
2346         },
2347         
2348         onDocumentReady : function(fn, scope, options){
2349             if(Ext.isReady){ 
2350                 docReadyEvent || (docReadyEvent = new Ext.util.Event());
2351                 docReadyEvent.addListener(fn, scope, options);
2352                 docReadyEvent.fire();
2353                 docReadyEvent.listeners = [];
2354             }else{
2355                 if(!docReadyEvent){
2356                     initDocReady();
2357                 }
2358                 options = options || {};
2359                 options.delay = options.delay || 1;
2360                 docReadyEvent.addListener(fn, scope, options);
2361             }
2362         },
2363
2364         
2365         fireDocReady  : fireDocReady
2366     };
2367      
2368     pub.on = pub.addListener;
2369     
2370     pub.un = pub.removeListener;
2371
2372     pub.stoppedMouseDownEvent = new Ext.util.Event();
2373     return pub;
2374 }();
2375
2376 Ext.onReady = Ext.EventManager.onDocumentReady;
2377
2378
2379
2380 (function(){
2381
2382     var initExtCss = function(){
2383         
2384         var bd = document.body || document.getElementsByTagName('body')[0];
2385         if(!bd){ return false; }
2386         var cls = [' ',
2387                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
2388                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
2389                 : Ext.isOpera ? "ext-opera"
2390                 : Ext.isWebKit ? "ext-webkit" : ""];
2391
2392         if(Ext.isSafari){
2393             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
2394         }else if(Ext.isChrome){
2395             cls.push("ext-chrome");
2396         }
2397
2398         if(Ext.isMac){
2399             cls.push("ext-mac");
2400         }
2401         if(Ext.isLinux){
2402             cls.push("ext-linux");
2403         }
2404
2405         if(Ext.isStrict || Ext.isBorderBox){ 
2406             var p = bd.parentNode;
2407             if(p){
2408                 p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
2409             }
2410         }
2411         bd.className += cls.join(' ');
2412         return true;
2413     }
2414
2415     if(!initExtCss()){
2416         Ext.onReady(initExtCss);
2417     }
2418 })();
2419
2420
2421
2422 Ext.EventObject = function(){
2423     var E = Ext.lib.Event,
2424         
2425         safariKeys = {
2426             3 : 13, 
2427             63234 : 37, 
2428             63235 : 39, 
2429             63232 : 38, 
2430             63233 : 40, 
2431             63276 : 33, 
2432             63277 : 34, 
2433             63272 : 46, 
2434             63273 : 36, 
2435             63275 : 35  
2436         },
2437         
2438         btnMap = Ext.isIE ? {1:0,4:1,2:2} :
2439                 (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
2440
2441     Ext.EventObjectImpl = function(e){
2442         if(e){
2443             this.setEvent(e.browserEvent || e);
2444         }
2445     };
2446
2447     Ext.EventObjectImpl.prototype = {
2448            
2449         setEvent : function(e){
2450             var me = this;
2451             if(e == me || (e && e.browserEvent)){ 
2452                 return e;
2453             }
2454             me.browserEvent = e;
2455             if(e){
2456                 
2457                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
2458                 if(e.type == 'click' && me.button == -1){
2459                     me.button = 0;
2460                 }
2461                 me.type = e.type;
2462                 me.shiftKey = e.shiftKey;
2463                 
2464                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
2465                 me.altKey = e.altKey;
2466                 
2467                 me.keyCode = e.keyCode;
2468                 me.charCode = e.charCode;
2469                 
2470                 me.target = E.getTarget(e);
2471                 
2472                 me.xy = E.getXY(e);
2473             }else{
2474                 me.button = -1;
2475                 me.shiftKey = false;
2476                 me.ctrlKey = false;
2477                 me.altKey = false;
2478                 me.keyCode = 0;
2479                 me.charCode = 0;
2480                 me.target = null;
2481                 me.xy = [0, 0];
2482             }
2483             return me;
2484         },
2485
2486         
2487         stopEvent : function(){
2488             var me = this;
2489             if(me.browserEvent){
2490                 if(me.browserEvent.type == 'mousedown'){
2491                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2492                 }
2493                 E.stopEvent(me.browserEvent);
2494             }
2495         },
2496
2497         
2498         preventDefault : function(){
2499             if(this.browserEvent){
2500                 E.preventDefault(this.browserEvent);
2501             }
2502         },
2503
2504         
2505         stopPropagation : function(){
2506             var me = this;
2507             if(me.browserEvent){
2508                 if(me.browserEvent.type == 'mousedown'){
2509                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2510                 }
2511                 E.stopPropagation(me.browserEvent);
2512             }
2513         },
2514
2515         
2516         getCharCode : function(){
2517             return this.charCode || this.keyCode;
2518         },
2519
2520         
2521         getKey : function(){
2522             return this.normalizeKey(this.keyCode || this.charCode)
2523         },
2524
2525         
2526         normalizeKey: function(k){
2527             return Ext.isSafari ? (safariKeys[k] || k) : k;
2528         },
2529
2530         
2531         getPageX : function(){
2532             return this.xy[0];
2533         },
2534
2535         
2536         getPageY : function(){
2537             return this.xy[1];
2538         },
2539
2540         
2541         getXY : function(){
2542             return this.xy;
2543         },
2544
2545         
2546         getTarget : function(selector, maxDepth, returnEl){
2547             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
2548         },
2549
2550         
2551         getRelatedTarget : function(){
2552             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
2553         },
2554
2555         
2556         getWheelDelta : function(){
2557             var e = this.browserEvent;
2558             var delta = 0;
2559             if(e.wheelDelta){ 
2560                 delta = e.wheelDelta/120;
2561             }else if(e.detail){ 
2562                 delta = -e.detail/3;
2563             }
2564             return delta;
2565         },
2566
2567         
2568         within : function(el, related, allowEl){
2569             if(el){
2570                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
2571                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
2572             }
2573             return false;
2574         }
2575      };
2576
2577     return new Ext.EventObjectImpl();
2578 }();
2579
2580 Ext.apply(Ext.EventManager, function(){
2581    var resizeEvent,
2582        resizeTask,
2583        textEvent,
2584        textSize,
2585        D = Ext.lib.Dom,
2586        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
2587        curWidth = 0,
2588        curHeight = 0,
2589        
2590        
2591        
2592        useKeydown = Ext.isWebKit ?
2593                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
2594                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
2595
2596    return {
2597        
2598        doResizeEvent: function(){
2599            var h = D.getViewHeight(),
2600                w = D.getViewWidth();
2601
2602             
2603             if(curHeight != h || curWidth != w){
2604                resizeEvent.fire(curWidth = w, curHeight = h);
2605             }
2606        },
2607
2608        
2609        onWindowResize : function(fn, scope, options){
2610            if(!resizeEvent){
2611                resizeEvent = new Ext.util.Event();
2612                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
2613                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
2614            }
2615            resizeEvent.addListener(fn, scope, options);
2616        },
2617
2618        
2619        fireWindowResize : function(){
2620            if(resizeEvent){
2621                resizeTask.delay(100);
2622            }
2623        },
2624
2625        
2626        onTextResize : function(fn, scope, options){
2627            if(!textEvent){
2628                textEvent = new Ext.util.Event();
2629                var textEl = new Ext.Element(document.createElement('div'));
2630                textEl.dom.className = 'x-text-resize';
2631                textEl.dom.innerHTML = 'X';
2632                textEl.appendTo(document.body);
2633                textSize = textEl.dom.offsetHeight;
2634                setInterval(function(){
2635                    if(textEl.dom.offsetHeight != textSize){
2636                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
2637                    }
2638                }, this.textResizeInterval);
2639            }
2640            textEvent.addListener(fn, scope, options);
2641        },
2642
2643        
2644        removeResizeListener : function(fn, scope){
2645            if(resizeEvent){
2646                resizeEvent.removeListener(fn, scope);
2647            }
2648        },
2649
2650        
2651        fireResize : function(){
2652            if(resizeEvent){
2653                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
2654            }
2655        },
2656
2657         
2658        textResizeInterval : 50,
2659
2660        
2661        ieDeferSrc : false,
2662
2663        
2664        
2665        useKeydown: useKeydown
2666    };
2667 }());
2668
2669 Ext.EventManager.on = Ext.EventManager.addListener;
2670
2671
2672 Ext.apply(Ext.EventObjectImpl.prototype, {
2673    
2674    BACKSPACE: 8,
2675    
2676    TAB: 9,
2677    
2678    NUM_CENTER: 12,
2679    
2680    ENTER: 13,
2681    
2682    RETURN: 13,
2683    
2684    SHIFT: 16,
2685    
2686    CTRL: 17,
2687    CONTROL : 17, 
2688    
2689    ALT: 18,
2690    
2691    PAUSE: 19,
2692    
2693    CAPS_LOCK: 20,
2694    
2695    ESC: 27,
2696    
2697    SPACE: 32,
2698    
2699    PAGE_UP: 33,
2700    PAGEUP : 33, 
2701    
2702    PAGE_DOWN: 34,
2703    PAGEDOWN : 34, 
2704    
2705    END: 35,
2706    
2707    HOME: 36,
2708    
2709    LEFT: 37,
2710    
2711    UP: 38,
2712    
2713    RIGHT: 39,
2714    
2715    DOWN: 40,
2716    
2717    PRINT_SCREEN: 44,
2718    
2719    INSERT: 45,
2720    
2721    DELETE: 46,
2722    
2723    ZERO: 48,
2724    
2725    ONE: 49,
2726    
2727    TWO: 50,
2728    
2729    THREE: 51,
2730    
2731    FOUR: 52,
2732    
2733    FIVE: 53,
2734    
2735    SIX: 54,
2736    
2737    SEVEN: 55,
2738    
2739    EIGHT: 56,
2740    
2741    NINE: 57,
2742    
2743    A: 65,
2744    
2745    B: 66,
2746    
2747    C: 67,
2748    
2749    D: 68,
2750    
2751    E: 69,
2752    
2753    F: 70,
2754    
2755    G: 71,
2756    
2757    H: 72,
2758    
2759    I: 73,
2760    
2761    J: 74,
2762    
2763    K: 75,
2764    
2765    L: 76,
2766    
2767    M: 77,
2768    
2769    N: 78,
2770    
2771    O: 79,
2772    
2773    P: 80,
2774    
2775    Q: 81,
2776    
2777    R: 82,
2778    
2779    S: 83,
2780    
2781    T: 84,
2782    
2783    U: 85,
2784    
2785    V: 86,
2786    
2787    W: 87,
2788    
2789    X: 88,
2790    
2791    Y: 89,
2792    
2793    Z: 90,
2794    
2795    CONTEXT_MENU: 93,
2796    
2797    NUM_ZERO: 96,
2798    
2799    NUM_ONE: 97,
2800    
2801    NUM_TWO: 98,
2802    
2803    NUM_THREE: 99,
2804    
2805    NUM_FOUR: 100,
2806    
2807    NUM_FIVE: 101,
2808    
2809    NUM_SIX: 102,
2810    
2811    NUM_SEVEN: 103,
2812    
2813    NUM_EIGHT: 104,
2814    
2815    NUM_NINE: 105,
2816    
2817    NUM_MULTIPLY: 106,
2818    
2819    NUM_PLUS: 107,
2820    
2821    NUM_MINUS: 109,
2822    
2823    NUM_PERIOD: 110,
2824    
2825    NUM_DIVISION: 111,
2826    
2827    F1: 112,
2828    
2829    F2: 113,
2830    
2831    F3: 114,
2832    
2833    F4: 115,
2834    
2835    F5: 116,
2836    
2837    F6: 117,
2838    
2839    F7: 118,
2840    
2841    F8: 119,
2842    
2843    F9: 120,
2844    
2845    F10: 121,
2846    
2847    F11: 122,
2848    
2849    F12: 123,
2850
2851    
2852    isNavKeyPress : function(){
2853        var me = this,
2854            k = this.normalizeKey(me.keyCode);
2855        return (k >= 33 && k <= 40) ||  
2856        k == me.RETURN ||
2857        k == me.TAB ||
2858        k == me.ESC;
2859    },
2860
2861    isSpecialKey : function(){
2862        var k = this.normalizeKey(this.keyCode);
2863        return (this.type == 'keypress' && this.ctrlKey) ||
2864        this.isNavKeyPress() ||
2865        (k == this.BACKSPACE) || 
2866        (k >= 16 && k <= 20) || 
2867        (k >= 44 && k <= 46);   
2868    },
2869
2870    getPoint : function(){
2871        return new Ext.lib.Point(this.xy[0], this.xy[1]);
2872    },
2873
2874    
2875    hasModifier : function(){
2876        return ((this.ctrlKey || this.altKey) || this.shiftKey);
2877    }
2878 });
2879 (function(){
2880 var DOC = document;
2881
2882 Ext.Element = function(element, forceNew){
2883     var dom = typeof element == "string" ?
2884               DOC.getElementById(element) : element,
2885         id;
2886
2887     if(!dom) return null;
2888
2889     id = dom.id;
2890
2891     if(!forceNew && id && Ext.elCache[id]){ 
2892         return Ext.elCache[id].el;
2893     }
2894
2895     
2896     this.dom = dom;
2897
2898     
2899     this.id = id || Ext.id(dom);
2900 };
2901
2902 var D = Ext.lib.Dom,
2903     DH = Ext.DomHelper,
2904     E = Ext.lib.Event,
2905     A = Ext.lib.Anim,
2906     El = Ext.Element,
2907     EC = Ext.elCache;
2908
2909 El.prototype = {
2910     
2911     set : function(o, useSet){
2912         var el = this.dom,
2913             attr,
2914             val,
2915             useSet = (useSet !== false) && !!el.setAttribute;
2916
2917         for(attr in o){
2918             if (o.hasOwnProperty(attr)) {
2919                 val = o[attr];
2920                 if (attr == 'style') {
2921                     DH.applyStyles(el, val);
2922                 } else if (attr == 'cls') {
2923                     el.className = val;
2924                 } else if (useSet) {
2925                     el.setAttribute(attr, val);
2926                 } else {
2927                     el[attr] = val;
2928                 }
2929             }
2930         }
2931         return this;
2932     },
2933
2934
2935     
2936     
2937     
2938     
2939     
2940     
2941     
2942     
2943     
2944     
2945
2946
2947     
2948     
2949     
2950
2951
2952
2953     
2954     
2955     
2956     
2957     
2958     
2959
2960
2961     
2962     
2963     
2964     
2965     
2966     
2967
2968
2969     
2970     
2971     
2972
2973
2974     
2975     
2976     
2977     
2978     
2979     
2980     
2981
2982     
2983     defaultUnit : "px",
2984
2985     
2986     is : function(simpleSelector){
2987         return Ext.DomQuery.is(this.dom, simpleSelector);
2988     },
2989
2990     
2991     focus : function(defer,  dom) {
2992         var me = this,
2993             dom = dom || me.dom;
2994         try{
2995             if(Number(defer)){
2996                 me.focus.defer(defer, null, [null, dom]);
2997             }else{
2998                 dom.focus();
2999             }
3000         }catch(e){}
3001         return me;
3002     },
3003
3004     
3005     blur : function() {
3006         try{
3007             this.dom.blur();
3008         }catch(e){}
3009         return this;
3010     },
3011
3012     
3013     getValue : function(asNumber){
3014         var val = this.dom.value;
3015         return asNumber ? parseInt(val, 10) : val;
3016     },
3017
3018     
3019     addListener : function(eventName, fn, scope, options){
3020         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
3021         return this;
3022     },
3023
3024     
3025     removeListener : function(eventName, fn, scope){
3026         Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
3027         return this;
3028     },
3029
3030     
3031     removeAllListeners : function(){
3032         Ext.EventManager.removeAll(this.dom);
3033         return this;
3034     },
3035
3036     
3037     purgeAllListeners : function() {
3038         Ext.EventManager.purgeElement(this, true);
3039         return this;
3040     },
3041     
3042     addUnits : function(size){
3043         if(size === "" || size == "auto" || size === undefined){
3044             size = size || '';
3045         } else if(!isNaN(size) || !unitPattern.test(size)){
3046             size = size + (this.defaultUnit || 'px');
3047         }
3048         return size;
3049     },
3050
3051     
3052     load : function(url, params, cb){
3053         Ext.Ajax.request(Ext.apply({
3054             params: params,
3055             url: url.url || url,
3056             callback: cb,
3057             el: this.dom,
3058             indicatorText: url.indicatorText || ''
3059         }, Ext.isObject(url) ? url : {}));
3060         return this;
3061     },
3062
3063     
3064     isBorderBox : function(){
3065         return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;
3066     },
3067
3068     
3069     remove : function(){
3070         var me = this,
3071             dom = me.dom;
3072
3073         if (dom) {
3074             delete me.dom;
3075             Ext.removeNode(dom);
3076         }
3077     },
3078
3079     
3080     hover : function(overFn, outFn, scope, options){
3081         var me = this;
3082         me.on('mouseenter', overFn, scope || me.dom, options);
3083         me.on('mouseleave', outFn, scope || me.dom, options);
3084         return me;
3085     },
3086
3087     
3088     contains : function(el){
3089         return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
3090     },
3091
3092     
3093     getAttributeNS : function(ns, name){
3094         return this.getAttribute(name, ns);
3095     },
3096
3097     
3098     getAttribute : Ext.isIE ? function(name, ns){
3099         var d = this.dom,
3100             type = typeof d[ns + ":" + name];
3101
3102         if(['undefined', 'unknown'].indexOf(type) == -1){
3103             return d[ns + ":" + name];
3104         }
3105         return d[name];
3106     } : function(name, ns){
3107         var d = this.dom;
3108         return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
3109     },
3110
3111     
3112     update : function(html) {
3113         if (this.dom) {
3114             this.dom.innerHTML = html;
3115         }
3116         return this;
3117     }
3118 };
3119
3120 var ep = El.prototype;
3121
3122 El.addMethods = function(o){
3123    Ext.apply(ep, o);
3124 };
3125
3126
3127 ep.on = ep.addListener;
3128
3129
3130 ep.un = ep.removeListener;
3131
3132
3133 ep.autoBoxAdjust = true;
3134
3135
3136 var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
3137     docEl;
3138
3139
3140
3141
3142 El.get = function(el){
3143     var ex,
3144         elm,
3145         id;
3146     if(!el){ return null; }
3147     if (typeof el == "string") { 
3148         if (!(elm = DOC.getElementById(el))) {
3149             return null;
3150         }
3151         if (EC[el] && EC[el].el) {
3152             ex = EC[el].el;
3153             ex.dom = elm;
3154         } else {
3155             ex = El.addToCache(new El(elm));
3156         }
3157         return ex;
3158     } else if (el.tagName) { 
3159         if(!(id = el.id)){
3160             id = Ext.id(el);
3161         }
3162         if (EC[id] && EC[id].el) {
3163             ex = EC[id].el;
3164             ex.dom = el;
3165         } else {
3166             ex = El.addToCache(new El(el));
3167         }
3168         return ex;
3169     } else if (el instanceof El) {
3170         if(el != docEl){
3171             
3172             
3173
3174             
3175             if (Ext.isIE && (el.id == undefined || el.id == '')) {
3176                 el.dom = el.dom;
3177             } else {
3178                 el.dom = DOC.getElementById(el.id) || el.dom;
3179             }
3180         }
3181         return el;
3182     } else if(el.isComposite) {
3183         return el;
3184     } else if(Ext.isArray(el)) {
3185         return El.select(el);
3186     } else if(el == DOC) {
3187         
3188         if(!docEl){
3189             var f = function(){};
3190             f.prototype = El.prototype;
3191             docEl = new f();
3192             docEl.dom = DOC;
3193         }
3194         return docEl;
3195     }
3196     return null;
3197 };
3198
3199 El.addToCache = function(el, id){
3200     id = id || el.id;
3201     EC[id] = {
3202         el:  el,
3203         data: {},
3204         events: {}
3205     };
3206     return el;
3207 };
3208
3209
3210 El.data = function(el, key, value){
3211     el = El.get(el);
3212     if (!el) {
3213         return null;
3214     }
3215     var c = EC[el.id].data;
3216     if(arguments.length == 2){
3217         return c[key];
3218     }else{
3219         return (c[key] = value);
3220     }
3221 };
3222
3223
3224
3225
3226 function garbageCollect(){
3227     if(!Ext.enableGarbageCollector){
3228         clearInterval(El.collectorThreadId);
3229     } else {
3230         var eid,
3231             el,
3232             d,
3233             o;
3234
3235         for(eid in EC){
3236             o = EC[eid];
3237             if(o.skipGC){
3238                 continue;
3239             }
3240             el = o.el;
3241             d = el.dom;
3242             
3243             
3244             
3245             
3246             
3247             
3248             
3249             
3250             
3251             
3252             
3253             
3254             
3255             
3256             
3257             
3258             
3259             if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
3260                 if(Ext.enableListenerCollection){
3261                     Ext.EventManager.removeAll(d);
3262                 }
3263                 delete EC[eid];
3264             }
3265         }
3266         
3267         if (Ext.isIE) {
3268             var t = {};
3269             for (eid in EC) {
3270                 t[eid] = EC[eid];
3271             }
3272             EC = Ext.elCache = t;
3273         }
3274     }
3275 }
3276 El.collectorThreadId = setInterval(garbageCollect, 30000);
3277
3278 var flyFn = function(){};
3279 flyFn.prototype = El.prototype;
3280
3281
3282 El.Flyweight = function(dom){
3283     this.dom = dom;
3284 };
3285
3286 El.Flyweight.prototype = new flyFn();
3287 El.Flyweight.prototype.isFlyweight = true;
3288 El._flyweights = {};
3289
3290
3291 El.fly = function(el, named){
3292     var ret = null;
3293     named = named || '_global';
3294
3295     if (el = Ext.getDom(el)) {
3296         (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
3297         ret = El._flyweights[named];
3298     }
3299     return ret;
3300 };
3301
3302
3303 Ext.get = El.get;
3304
3305
3306 Ext.fly = El.fly;
3307
3308
3309 var noBoxAdjust = Ext.isStrict ? {
3310     select:1
3311 } : {
3312     input:1, select:1, textarea:1
3313 };
3314 if(Ext.isIE || Ext.isGecko){
3315     noBoxAdjust['button'] = 1;
3316 }
3317
3318 })();
3319
3320 Ext.Element.addMethods({
3321     
3322     swallowEvent : function(eventName, preventDefault){
3323         var me = this;
3324         function fn(e){
3325             e.stopPropagation();
3326             if(preventDefault){
3327                 e.preventDefault();
3328             }
3329         }
3330         if(Ext.isArray(eventName)){
3331             Ext.each(eventName, function(e) {
3332                  me.on(e, fn);
3333             });
3334             return me;
3335         }
3336         me.on(eventName, fn);
3337         return me;
3338     },
3339
3340     
3341     relayEvent : function(eventName, observable){
3342         this.on(eventName, function(e){
3343             observable.fireEvent(eventName, e);
3344         });
3345     },
3346
3347     
3348     clean : function(forceReclean){
3349         var me = this,
3350             dom = me.dom,
3351             n = dom.firstChild,
3352             ni = -1;
3353
3354         if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
3355             return me;
3356         }
3357
3358         while(n){
3359             var nx = n.nextSibling;
3360             if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
3361                 dom.removeChild(n);
3362             }else{
3363                 n.nodeIndex = ++ni;
3364             }
3365             n = nx;
3366         }
3367         Ext.Element.data(dom, 'isCleaned', true);
3368         return me;
3369     },
3370
3371     
3372     load : function(){
3373         var um = this.getUpdater();
3374         um.update.apply(um, arguments);
3375         return this;
3376     },
3377
3378     
3379     getUpdater : function(){
3380         return this.updateManager || (this.updateManager = new Ext.Updater(this));
3381     },
3382
3383     
3384     update : function(html, loadScripts, callback){
3385         if (!this.dom) {
3386             return this;
3387         }
3388         html = html || "";
3389
3390         if(loadScripts !== true){
3391             this.dom.innerHTML = html;
3392             if(typeof callback == 'function'){
3393                 callback();
3394             }
3395             return this;
3396         }
3397
3398         var id = Ext.id(),
3399             dom = this.dom;
3400
3401         html += '<span id="' + id + '"></span>';
3402
3403         Ext.lib.Event.onAvailable(id, function(){
3404             var DOC = document,
3405                 hd = DOC.getElementsByTagName("head")[0],
3406                 re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
3407                 srcRe = /\ssrc=([\'\"])(.*?)\1/i,
3408                 typeRe = /\stype=([\'\"])(.*?)\1/i,
3409                 match,
3410                 attrs,
3411                 srcMatch,
3412                 typeMatch,
3413                 el,
3414                 s;
3415
3416             while((match = re.exec(html))){
3417                 attrs = match[1];
3418                 srcMatch = attrs ? attrs.match(srcRe) : false;
3419                 if(srcMatch && srcMatch[2]){
3420                    s = DOC.createElement("script");
3421                    s.src = srcMatch[2];
3422                    typeMatch = attrs.match(typeRe);
3423                    if(typeMatch && typeMatch[2]){
3424                        s.type = typeMatch[2];
3425                    }
3426                    hd.appendChild(s);
3427                 }else if(match[2] && match[2].length > 0){
3428                     if(window.execScript) {
3429                        window.execScript(match[2]);
3430                     } else {
3431                        window.eval(match[2]);
3432                     }
3433                 }
3434             }
3435             el = DOC.getElementById(id);
3436             if(el){Ext.removeNode(el);}
3437             if(typeof callback == 'function'){
3438                 callback();
3439             }
3440         });
3441         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
3442         return this;
3443     },
3444
3445     
3446     removeAllListeners : function(){
3447         this.removeAnchor();
3448         Ext.EventManager.removeAll(this.dom);
3449         return this;
3450     },
3451
3452     
3453     createProxy : function(config, renderTo, matchBox){
3454         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
3455
3456         var me = this,
3457             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
3458                                Ext.DomHelper.insertBefore(me.dom, config, true);
3459
3460         if(matchBox && me.setBox && me.getBox){ 
3461            proxy.setBox(me.getBox());
3462         }
3463         return proxy;
3464     }
3465 });
3466
3467 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
3468
3469 Ext.Element.addMethods({
3470     
3471     getAnchorXY : function(anchor, local, s){
3472         
3473         
3474                 anchor = (anchor || "tl").toLowerCase();
3475         s = s || {};
3476         
3477         var me = this,        
3478                 vp = me.dom == document.body || me.dom == document,
3479                 w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
3480                 h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
3481                 xy,             
3482                 r = Math.round,
3483                 o = me.getXY(),
3484                 scroll = me.getScroll(),
3485                 extraX = vp ? scroll.left : !local ? o[0] : 0,
3486                 extraY = vp ? scroll.top : !local ? o[1] : 0,
3487                 hash = {
3488                         c  : [r(w * 0.5), r(h * 0.5)],
3489                         t  : [r(w * 0.5), 0],
3490                         l  : [0, r(h * 0.5)],
3491                         r  : [w, r(h * 0.5)],
3492                         b  : [r(w * 0.5), h],
3493                         tl : [0, 0],    
3494                         bl : [0, h],
3495                         br : [w, h],
3496                         tr : [w, 0]
3497                 };
3498         
3499         xy = hash[anchor];      
3500         return [xy[0] + extraX, xy[1] + extraY]; 
3501     },
3502
3503     
3504     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
3505             var me = this,
3506             dom = me.dom,
3507             scroll = !Ext.isEmpty(monitorScroll),
3508             action = function(){
3509                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
3510                 Ext.callback(callback, Ext.fly(dom));
3511             },
3512             anchor = this.getAnchor();
3513             
3514         
3515         this.removeAnchor();
3516         Ext.apply(anchor, {
3517             fn: action,
3518             scroll: scroll
3519         });
3520
3521         Ext.EventManager.onWindowResize(action, null);
3522         
3523         if(scroll){
3524             Ext.EventManager.on(window, 'scroll', action, null,
3525                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
3526         }
3527         action.call(me); 
3528         return me;
3529     },
3530     
3531     
3532     removeAnchor : function(){
3533         var me = this,
3534             anchor = this.getAnchor();
3535             
3536         if(anchor && anchor.fn){
3537             Ext.EventManager.removeResizeListener(anchor.fn);
3538             if(anchor.scroll){
3539                 Ext.EventManager.un(window, 'scroll', anchor.fn);
3540             }
3541             delete anchor.fn;
3542         }
3543         return me;
3544     },
3545     
3546     
3547     getAnchor : function(){
3548         var data = Ext.Element.data,
3549             dom = this.dom;
3550             if (!dom) {
3551                 return;
3552             }
3553             var anchor = data(dom, '_anchor');
3554             
3555         if(!anchor){
3556             anchor = data(dom, '_anchor', {});
3557         }
3558         return anchor;
3559     },
3560
3561     
3562     getAlignToXY : function(el, p, o){      
3563         el = Ext.get(el);
3564         
3565         if(!el || !el.dom){
3566             throw "Element.alignToXY with an element that doesn't exist";
3567         }
3568         
3569         o = o || [0,0];
3570         p = (!p || p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
3571                 
3572         var me = this,
3573                 d = me.dom,
3574                 a1,
3575                 a2,
3576                 x,
3577                 y,
3578                 
3579                 w,
3580                 h,
3581                 r,
3582                 dw = Ext.lib.Dom.getViewWidth() -10, 
3583                 dh = Ext.lib.Dom.getViewHeight()-10, 
3584                 p1y,
3585                 p1x,            
3586                 p2y,
3587                 p2x,
3588                 swapY,
3589                 swapX,
3590                 doc = document,
3591                 docElement = doc.documentElement,
3592                 docBody = doc.body,
3593                 scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
3594                 scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
3595                 c = false, 
3596                 p1 = "", 
3597                 p2 = "",
3598                 m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
3599         
3600         if(!m){
3601            throw "Element.alignTo with an invalid alignment " + p;
3602         }
3603         
3604         p1 = m[1]; 
3605         p2 = m[2]; 
3606         c = !!m[3];
3607
3608         
3609         
3610         a1 = me.getAnchorXY(p1, true);
3611         a2 = el.getAnchorXY(p2, false);
3612
3613         x = a2[0] - a1[0] + o[0];
3614         y = a2[1] - a1[1] + o[1];
3615
3616         if(c){    
3617                w = me.getWidth();
3618            h = me.getHeight();
3619            r = el.getRegion();       
3620            
3621            
3622            
3623            p1y = p1.charAt(0);
3624            p1x = p1.charAt(p1.length-1);
3625            p2y = p2.charAt(0);
3626            p2x = p2.charAt(p2.length-1);
3627            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
3628            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
3629            
3630
3631            if (x + w > dw + scrollX) {
3632                 x = swapX ? r.left-w : dw+scrollX-w;
3633            }
3634            if (x < scrollX) {
3635                x = swapX ? r.right : scrollX;
3636            }
3637            if (y + h > dh + scrollY) {
3638                 y = swapY ? r.top-h : dh+scrollY-h;
3639             }
3640            if (y < scrollY){
3641                y = swapY ? r.bottom : scrollY;
3642            }
3643         }
3644         return [x,y];
3645     },
3646
3647     
3648     alignTo : function(element, position, offsets, animate){
3649             var me = this;
3650         return me.setXY(me.getAlignToXY(element, position, offsets),
3651                                 me.preanim && !!animate ? me.preanim(arguments, 3) : false);
3652     },
3653     
3654     
3655     adjustForConstraints : function(xy, parent, offsets){
3656         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
3657     },
3658
3659     
3660     getConstrainToXY : function(el, local, offsets, proposedXY){   
3661             var os = {top:0, left:0, bottom:0, right: 0};
3662
3663         return function(el, local, offsets, proposedXY){
3664             el = Ext.get(el);
3665             offsets = offsets ? Ext.applyIf(offsets, os) : os;
3666
3667             var vw, vh, vx = 0, vy = 0;
3668             if(el.dom == document.body || el.dom == document){
3669                 vw =Ext.lib.Dom.getViewWidth();
3670                 vh = Ext.lib.Dom.getViewHeight();
3671             }else{
3672                 vw = el.dom.clientWidth;
3673                 vh = el.dom.clientHeight;
3674                 if(!local){
3675                     var vxy = el.getXY();
3676                     vx = vxy[0];
3677                     vy = vxy[1];
3678                 }
3679             }
3680
3681             var s = el.getScroll();
3682
3683             vx += offsets.left + s.left;
3684             vy += offsets.top + s.top;
3685
3686             vw -= offsets.right;
3687             vh -= offsets.bottom;
3688
3689             var vr = vx+vw;
3690             var vb = vy+vh;
3691
3692             var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
3693             var x = xy[0], y = xy[1];
3694             var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
3695
3696             
3697             var moved = false;
3698
3699             
3700             if((x + w) > vr){
3701                 x = vr - w;
3702                 moved = true;
3703             }
3704             if((y + h) > vb){
3705                 y = vb - h;
3706                 moved = true;
3707             }
3708             
3709             if(x < vx){
3710                 x = vx;
3711                 moved = true;
3712             }
3713             if(y < vy){
3714                 y = vy;
3715                 moved = true;
3716             }
3717             return moved ? [x, y] : false;
3718         };
3719     }(),
3720             
3721             
3722                 
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775     
3776     
3777     getCenterXY : function(){
3778         return this.getAlignToXY(document, 'c-c');
3779     },
3780
3781     
3782     center : function(centerIn){
3783         return this.alignTo(centerIn || document, 'c-c');        
3784     }    
3785 });
3786
3787 Ext.Element.addMethods(function(){
3788         var PARENTNODE = 'parentNode',
3789                 NEXTSIBLING = 'nextSibling',
3790                 PREVIOUSSIBLING = 'previousSibling',
3791                 DQ = Ext.DomQuery,
3792                 GET = Ext.get;
3793         
3794         return {
3795                 
3796             findParent : function(simpleSelector, maxDepth, returnEl){
3797                 var p = this.dom,
3798                         b = document.body, 
3799                         depth = 0,                      
3800                         stopEl;         
3801             if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
3802                 return null;
3803             }
3804                 maxDepth = maxDepth || 50;
3805                 if (isNaN(maxDepth)) {
3806                     stopEl = Ext.getDom(maxDepth);
3807                     maxDepth = Number.MAX_VALUE;
3808                 }
3809                 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
3810                     if(DQ.is(p, simpleSelector)){
3811                         return returnEl ? GET(p) : p;
3812                     }
3813                     depth++;
3814                     p = p.parentNode;
3815                 }
3816                 return null;
3817             },
3818         
3819             
3820             findParentNode : function(simpleSelector, maxDepth, returnEl){
3821                 var p = Ext.fly(this.dom.parentNode, '_internal');
3822                 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
3823             },
3824         
3825             
3826             up : function(simpleSelector, maxDepth){
3827                 return this.findParentNode(simpleSelector, maxDepth, true);
3828             },
3829         
3830             
3831             select : function(selector){
3832                 return Ext.Element.select(selector, this.dom);
3833             },
3834         
3835             
3836             query : function(selector){
3837                 return DQ.select(selector, this.dom);
3838             },
3839         
3840             
3841             child : function(selector, returnDom){
3842                 var n = DQ.selectNode(selector, this.dom);
3843                 return returnDom ? n : GET(n);
3844             },
3845         
3846             
3847             down : function(selector, returnDom){
3848                 var n = DQ.selectNode(" > " + selector, this.dom);
3849                 return returnDom ? n : GET(n);
3850             },
3851         
3852                  
3853             parent : function(selector, returnDom){
3854                 return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
3855             },
3856         
3857              
3858             next : function(selector, returnDom){
3859                 return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
3860             },
3861         
3862             
3863             prev : function(selector, returnDom){
3864                 return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
3865             },
3866         
3867         
3868             
3869             first : function(selector, returnDom){
3870                 return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
3871             },
3872         
3873             
3874             last : function(selector, returnDom){
3875                 return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
3876             },
3877             
3878             matchNode : function(dir, start, selector, returnDom){
3879                 var n = this.dom[start];
3880                 while(n){
3881                     if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
3882                         return !returnDom ? GET(n) : n;
3883                     }
3884                     n = n[dir];
3885                 }
3886                 return null;
3887             }   
3888     }
3889 }());
3890 Ext.Element.addMethods({
3891     
3892     select : function(selector, unique){
3893         return Ext.Element.select(selector, unique, this.dom);
3894     }
3895 });
3896 Ext.Element.addMethods(
3897 function() {
3898         var GETDOM = Ext.getDom,
3899                 GET = Ext.get,
3900                 DH = Ext.DomHelper;
3901         
3902         return {
3903             
3904             appendChild: function(el){        
3905                 return GET(el).appendTo(this);        
3906             },
3907         
3908             
3909             appendTo: function(el){        
3910                 GETDOM(el).appendChild(this.dom);        
3911                 return this;
3912             },
3913         
3914             
3915             insertBefore: function(el){                   
3916                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
3917                 return this;
3918             },
3919         
3920             
3921             insertAfter: function(el){
3922                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
3923                 return this;
3924             },
3925         
3926             
3927             insertFirst: function(el, returnDom){
3928             el = el || {};
3929             if(el.nodeType || el.dom || typeof el == 'string'){ 
3930                 el = GETDOM(el);
3931                 this.dom.insertBefore(el, this.dom.firstChild);
3932                 return !returnDom ? GET(el) : el;
3933             }else{ 
3934                 return this.createChild(el, this.dom.firstChild, returnDom);
3935             }
3936         },
3937         
3938             
3939             replace: function(el){
3940                 el = GET(el);
3941                 this.insertBefore(el);
3942                 el.remove();
3943                 return this;
3944             },
3945         
3946             
3947             replaceWith: function(el){
3948                     var me = this;
3949                 
3950             if(el.nodeType || el.dom || typeof el == 'string'){
3951                 el = GETDOM(el);
3952                 me.dom.parentNode.insertBefore(el, me.dom);
3953             }else{
3954                 el = DH.insertBefore(me.dom, el);
3955             }
3956                 
3957                 delete Ext.elCache[me.id];
3958                 Ext.removeNode(me.dom);      
3959                 me.id = Ext.id(me.dom = el);
3960                 Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
3961             return me;
3962             },
3963             
3964                 
3965                 createChild: function(config, insertBefore, returnDom){
3966                     config = config || {tag:'div'};
3967                     return insertBefore ? 
3968                            DH.insertBefore(insertBefore, config, returnDom !== true) :  
3969                            DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
3970                 },
3971                 
3972                 
3973                 wrap: function(config, returnDom){        
3974                     var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
3975                     newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
3976                     return newEl;
3977                 },
3978                 
3979                 
3980                 insertHtml : function(where, html, returnEl){
3981                     var el = DH.insertHtml(where, this.dom, html);
3982                     return returnEl ? Ext.get(el) : el;
3983                 }
3984         }
3985 }());
3986 Ext.apply(Ext.Element.prototype, function() {
3987         var GETDOM = Ext.getDom,
3988                 GET = Ext.get,
3989                 DH = Ext.DomHelper;
3990         
3991         return {        
3992                 
3993             insertSibling: function(el, where, returnDom){
3994                 var me = this,
3995                         rt,
3996                 isAfter = (where || 'before').toLowerCase() == 'after',
3997                 insertEl;
3998                         
3999                 if(Ext.isArray(el)){
4000                 insertEl = me;
4001                     Ext.each(el, function(e) {
4002                             rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
4003                     if(isAfter){
4004                         insertEl = rt;
4005                     }
4006                     });
4007                     return rt;
4008                 }
4009                         
4010                 el = el || {};
4011                 
4012             if(el.nodeType || el.dom){
4013                 rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
4014                 if (!returnDom) {
4015                     rt = GET(rt);
4016                 }
4017             }else{
4018                 if (isAfter && !me.dom.nextSibling) {
4019                     rt = DH.append(me.dom.parentNode, el, !returnDom);
4020                 } else {                    
4021                     rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
4022                 }
4023             }
4024                 return rt;
4025             }
4026     };
4027 }());
4028 Ext.Element.addMethods(function(){
4029     
4030     var propCache = {},
4031         camelRe = /(-[a-z])/gi,
4032         classReCache = {},
4033         view = document.defaultView,
4034         propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
4035         opacityRe = /alpha\(opacity=(.*)\)/i,
4036         trimRe = /^\s+|\s+$/g,
4037         spacesRe = /\s+/,
4038         wordsRe = /\w/g,
4039         EL = Ext.Element,
4040         PADDING = "padding",
4041         MARGIN = "margin",
4042         BORDER = "border",
4043         LEFT = "-left",
4044         RIGHT = "-right",
4045         TOP = "-top",
4046         BOTTOM = "-bottom",
4047         WIDTH = "-width",
4048         MATH = Math,
4049         HIDDEN = 'hidden',
4050         ISCLIPPED = 'isClipped',
4051         OVERFLOW = 'overflow',
4052         OVERFLOWX = 'overflow-x',
4053         OVERFLOWY = 'overflow-y',
4054         ORIGINALCLIP = 'originalClip',
4055         
4056         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
4057         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
4058         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
4059         data = Ext.Element.data;
4060
4061
4062     
4063     function camelFn(m, a) {
4064         return a.charAt(1).toUpperCase();
4065     }
4066
4067     function chkCache(prop) {
4068         return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
4069     }
4070
4071     return {
4072         
4073         adjustWidth : function(width) {
4074             var me = this;
4075             var isNum = (typeof width == "number");
4076             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
4077                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
4078             }
4079             return (isNum && width < 0) ? 0 : width;
4080         },
4081
4082         
4083         adjustHeight : function(height) {
4084             var me = this;
4085             var isNum = (typeof height == "number");
4086             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
4087                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
4088             }
4089             return (isNum && height < 0) ? 0 : height;
4090         },
4091
4092
4093         
4094         addClass : function(className){
4095             var me = this,
4096                 i,
4097                 len,
4098                 v,
4099                 cls = [];
4100             
4101             if (!Ext.isArray(className)) {
4102                 if (typeof className == 'string' && !this.hasClass(className)) {
4103                     me.dom.className += " " + className;
4104                 }
4105             }
4106             else {
4107                 for (i = 0, len = className.length; i < len; i++) {
4108                     v = className[i];
4109                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
4110                         cls.push(v);
4111                     }
4112                 }
4113                 if (cls.length) {
4114                     me.dom.className += " " + cls.join(" ");
4115                 }
4116             }
4117             return me;
4118         },
4119
4120         
4121         removeClass : function(className){
4122             var me = this,
4123                 i,
4124                 idx,
4125                 len,
4126                 cls,
4127                 elClasses;
4128             if (!Ext.isArray(className)){
4129                 className = [className];
4130             }
4131             if (me.dom && me.dom.className) {
4132                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
4133                 for (i = 0, len = className.length; i < len; i++) {
4134                     cls = className[i];
4135                     if (typeof cls == 'string') {
4136                         cls = cls.replace(trimRe, '');
4137                         idx = elClasses.indexOf(cls);
4138                         if (idx != -1) {
4139                             elClasses.splice(idx, 1);
4140                         }
4141                     }
4142                 }
4143                 me.dom.className = elClasses.join(" ");
4144             }
4145             return me;
4146         },
4147
4148         
4149         radioClass : function(className){
4150             var cn = this.dom.parentNode.childNodes,
4151                 v,
4152                 i,
4153                 len;
4154             className = Ext.isArray(className) ? className : [className];
4155             for (i = 0, len = cn.length; i < len; i++) {
4156                 v = cn[i];
4157                 if (v && v.nodeType == 1) {
4158                     Ext.fly(v, '_internal').removeClass(className);
4159                 }
4160             };
4161             return this.addClass(className);
4162         },
4163
4164         
4165         toggleClass : function(className){
4166             return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
4167         },
4168
4169         
4170         hasClass : function(className){
4171             return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
4172         },
4173
4174         
4175         replaceClass : function(oldClassName, newClassName){
4176             return this.removeClass(oldClassName).addClass(newClassName);
4177         },
4178
4179         isStyle : function(style, val) {
4180             return this.getStyle(style) == val;
4181         },
4182
4183         
4184         getStyle : function(){
4185             return view && view.getComputedStyle ?
4186                 function(prop){
4187                     var el = this.dom,
4188                         v,
4189                         cs,
4190                         out,
4191                         display,
4192                         wk = Ext.isWebKit,
4193                         display;
4194
4195                     if(el == document){
4196                         return null;
4197                     }
4198                     prop = chkCache(prop);
4199                     
4200                     if(wk && /marginRight/.test(prop)){
4201                         display = this.getStyle('display');
4202                         el.style.display = 'inline-block';
4203                     }
4204                     out = (v = el.style[prop]) ? v :
4205                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
4206
4207                     
4208                     if(wk){
4209                         if(out == 'rgba(0, 0, 0, 0)'){
4210                             out = 'transparent';
4211                         }else if(display){
4212                             el.style.display = display;
4213                         }
4214                     }
4215                     return out;
4216                 } :
4217                 function(prop){
4218                     var el = this.dom,
4219                         m,
4220                         cs;
4221
4222                     if(el == document) return null;
4223                     if (prop == 'opacity') {
4224                         if (el.style.filter.match) {
4225                             if(m = el.style.filter.match(opacityRe)){
4226                                 var fv = parseFloat(m[1]);
4227                                 if(!isNaN(fv)){
4228                                     return fv ? fv / 100 : 0;
4229                                 }
4230                             }
4231                         }
4232                         return 1;
4233                     }
4234                     prop = chkCache(prop);
4235                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
4236                 };
4237         }(),
4238
4239         
4240         getColor : function(attr, defaultValue, prefix){
4241             var v = this.getStyle(attr),
4242                 color = (typeof prefix != 'undefined') ? prefix : '#',
4243                 h;
4244
4245             if(!v || /transparent|inherit/.test(v)){
4246                 return defaultValue;
4247             }
4248             if(/^r/.test(v)){
4249                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
4250                     h = parseInt(s, 10);
4251                     color += (h < 16 ? '0' : '') + h.toString(16);
4252                 });
4253             }else{
4254                 v = v.replace('#', '');
4255                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
4256             }
4257             return(color.length > 5 ? color.toLowerCase() : defaultValue);
4258         },
4259
4260         
4261         setStyle : function(prop, value){
4262             var tmp,
4263                 style,
4264                 camel;
4265             if (typeof prop != 'object') {
4266                 tmp = {};
4267                 tmp[prop] = value;
4268                 prop = tmp;
4269             }
4270             for (style in prop) {
4271                 value = prop[style];
4272                 style == 'opacity' ?
4273                     this.setOpacity(value) :
4274                     this.dom.style[chkCache(style)] = value;
4275             }
4276             return this;
4277         },
4278
4279         
4280          setOpacity : function(opacity, animate){
4281             var me = this,
4282                 s = me.dom.style;
4283
4284             if(!animate || !me.anim){
4285                 if(Ext.isIE){
4286                     var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
4287                     val = s.filter.replace(opacityRe, '').replace(trimRe, '');
4288
4289                     s.zoom = 1;
4290                     s.filter = val + (val.length > 0 ? ' ' : '') + opac;
4291                 }else{
4292                     s.opacity = opacity;
4293                 }
4294             }else{
4295                 me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
4296             }
4297             return me;
4298         },
4299
4300         
4301         clearOpacity : function(){
4302             var style = this.dom.style;
4303             if(Ext.isIE){
4304                 if(!Ext.isEmpty(style.filter)){
4305                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
4306                 }
4307             }else{
4308                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
4309             }
4310             return this;
4311         },
4312
4313         
4314         getHeight : function(contentHeight){
4315             var me = this,
4316                 dom = me.dom,
4317                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4318                 h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
4319
4320             h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
4321             return h < 0 ? 0 : h;
4322         },
4323
4324         
4325         getWidth : function(contentWidth){
4326             var me = this,
4327                 dom = me.dom,
4328                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4329                 w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
4330             w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
4331             return w < 0 ? 0 : w;
4332         },
4333
4334         
4335         setWidth : function(width, animate){
4336             var me = this;
4337             width = me.adjustWidth(width);
4338             !animate || !me.anim ?
4339                 me.dom.style.width = me.addUnits(width) :
4340                 me.anim({width : {to : width}}, me.preanim(arguments, 1));
4341             return me;
4342         },
4343
4344         
4345          setHeight : function(height, animate){
4346             var me = this;
4347             height = me.adjustHeight(height);
4348             !animate || !me.anim ?
4349                 me.dom.style.height = me.addUnits(height) :
4350                 me.anim({height : {to : height}}, me.preanim(arguments, 1));
4351             return me;
4352         },
4353
4354         
4355         getBorderWidth : function(side){
4356             return this.addStyles(side, borders);
4357         },
4358
4359         
4360         getPadding : function(side){
4361             return this.addStyles(side, paddings);
4362         },
4363
4364         
4365         clip : function(){
4366             var me = this,
4367                 dom = me.dom;
4368
4369             if(!data(dom, ISCLIPPED)){
4370                 data(dom, ISCLIPPED, true);
4371                 data(dom, ORIGINALCLIP, {
4372                     o: me.getStyle(OVERFLOW),
4373                     x: me.getStyle(OVERFLOWX),
4374                     y: me.getStyle(OVERFLOWY)
4375                 });
4376                 me.setStyle(OVERFLOW, HIDDEN);
4377                 me.setStyle(OVERFLOWX, HIDDEN);
4378                 me.setStyle(OVERFLOWY, HIDDEN);
4379             }
4380             return me;
4381         },
4382
4383         
4384         unclip : function(){
4385             var me = this,
4386                 dom = me.dom;
4387
4388             if(data(dom, ISCLIPPED)){
4389                 data(dom, ISCLIPPED, false);
4390                 var o = data(dom, ORIGINALCLIP);
4391                 if(o.o){
4392                     me.setStyle(OVERFLOW, o.o);
4393                 }
4394                 if(o.x){
4395                     me.setStyle(OVERFLOWX, o.x);
4396                 }
4397                 if(o.y){
4398                     me.setStyle(OVERFLOWY, o.y);
4399                 }
4400             }
4401             return me;
4402         },
4403
4404         
4405         addStyles : function(sides, styles){
4406             var ttlSize = 0,
4407                 sidesArr = sides.match(wordsRe),
4408                 side,
4409                 size,
4410                 i,
4411                 len = sidesArr.length;
4412             for (i = 0; i < len; i++) {
4413                 side = sidesArr[i];
4414                 size = side && parseInt(this.getStyle(styles[side]), 10);
4415                 if (size) {
4416                     ttlSize += MATH.abs(size);
4417                 }
4418             }
4419             return ttlSize;
4420         },
4421
4422         margins : margins
4423     }
4424 }()
4425 );
4426
4427
4428
4429 Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
4430
4431 Ext.Element.addMethods(function(){
4432     var INTERNAL = "_internal",
4433         pxMatch = /(\d+\.?\d+)px/;
4434     return {
4435         
4436         applyStyles : function(style){
4437             Ext.DomHelper.applyStyles(this.dom, style);
4438             return this;
4439         },
4440
4441         
4442         getStyles : function(){
4443             var ret = {};
4444             Ext.each(arguments, function(v) {
4445                ret[v] = this.getStyle(v);
4446             },
4447             this);
4448             return ret;
4449         },
4450
4451         
4452         setOverflow : function(v){
4453             var dom = this.dom;
4454             if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
4455                 dom.style.overflow = 'hidden';
4456                 (function(){dom.style.overflow = 'auto';}).defer(1);
4457             }else{
4458                 dom.style.overflow = v;
4459             }
4460         },
4461
4462        
4463         boxWrap : function(cls){
4464             cls = cls || 'x-box';
4465             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
4466             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
4467             return el;
4468         },
4469
4470         
4471         setSize : function(width, height, animate){
4472             var me = this;
4473             if(typeof width == 'object'){ 
4474                 height = width.height;
4475                 width = width.width;
4476             }
4477             width = me.adjustWidth(width);
4478             height = me.adjustHeight(height);
4479             if(!animate || !me.anim){
4480                 me.dom.style.width = me.addUnits(width);
4481                 me.dom.style.height = me.addUnits(height);
4482             }else{
4483                 me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
4484             }
4485             return me;
4486         },
4487
4488         
4489         getComputedHeight : function(){
4490             var me = this,
4491                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
4492             if(!h){
4493                 h = parseFloat(me.getStyle('height')) || 0;
4494                 if(!me.isBorderBox()){
4495                     h += me.getFrameWidth('tb');
4496                 }
4497             }
4498             return h;
4499         },
4500
4501         
4502         getComputedWidth : function(){
4503             var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
4504             if(!w){
4505                 w = parseFloat(this.getStyle('width')) || 0;
4506                 if(!this.isBorderBox()){
4507                     w += this.getFrameWidth('lr');
4508                 }
4509             }
4510             return w;
4511         },
4512
4513         
4514         getFrameWidth : function(sides, onlyContentBox){
4515             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
4516         },
4517
4518         
4519         addClassOnOver : function(className){
4520             this.hover(
4521                 function(){
4522                     Ext.fly(this, INTERNAL).addClass(className);
4523                 },
4524                 function(){
4525                     Ext.fly(this, INTERNAL).removeClass(className);
4526                 }
4527             );
4528             return this;
4529         },
4530
4531         
4532         addClassOnFocus : function(className){
4533             this.on("focus", function(){
4534                 Ext.fly(this, INTERNAL).addClass(className);
4535             }, this.dom);
4536             this.on("blur", function(){
4537                 Ext.fly(this, INTERNAL).removeClass(className);
4538             }, this.dom);
4539             return this;
4540         },
4541
4542         
4543         addClassOnClick : function(className){
4544             var dom = this.dom;
4545             this.on("mousedown", function(){
4546                 Ext.fly(dom, INTERNAL).addClass(className);
4547                 var d = Ext.getDoc(),
4548                     fn = function(){
4549                         Ext.fly(dom, INTERNAL).removeClass(className);
4550                         d.removeListener("mouseup", fn);
4551                     };
4552                 d.on("mouseup", fn);
4553             });
4554             return this;
4555         },
4556
4557         
4558
4559         getViewSize : function(){
4560             var doc = document,
4561                 d = this.dom,
4562                 isDoc = (d == doc || d == doc.body);
4563
4564             
4565             if (isDoc) {
4566                 var extdom = Ext.lib.Dom;
4567                 return {
4568                     width : extdom.getViewWidth(),
4569                     height : extdom.getViewHeight()
4570                 };
4571
4572             
4573             } else {
4574                 return {
4575                     width : d.clientWidth,
4576                     height : d.clientHeight
4577                 }
4578             }
4579         },
4580
4581         
4582
4583         getStyleSize : function(){
4584             var me = this,
4585                 w, h,
4586                 doc = document,
4587                 d = this.dom,
4588                 isDoc = (d == doc || d == doc.body),
4589                 s = d.style;
4590
4591             
4592             if (isDoc) {
4593                 var extdom = Ext.lib.Dom;
4594                 return {
4595                     width : extdom.getViewWidth(),
4596                     height : extdom.getViewHeight()
4597                 }
4598             }
4599             
4600             if(s.width && s.width != 'auto'){
4601                 w = parseFloat(s.width);
4602                 if(me.isBorderBox()){
4603                    w -= me.getFrameWidth('lr');
4604                 }
4605             }
4606             
4607             if(s.height && s.height != 'auto'){
4608                 h = parseFloat(s.height);
4609                 if(me.isBorderBox()){
4610                    h -= me.getFrameWidth('tb');
4611                 }
4612             }
4613             
4614             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
4615         },
4616
4617         
4618         getSize : function(contentSize){
4619             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
4620         },
4621
4622         
4623         repaint : function(){
4624             var dom = this.dom;
4625             this.addClass("x-repaint");
4626             setTimeout(function(){
4627                 Ext.fly(dom).removeClass("x-repaint");
4628             }, 1);
4629             return this;
4630         },
4631
4632         
4633         unselectable : function(){
4634             this.dom.unselectable = "on";
4635             return this.swallowEvent("selectstart", true).
4636                         applyStyles("-moz-user-select:none;-khtml-user-select:none;").
4637                         addClass("x-unselectable");
4638         },
4639
4640         
4641         getMargins : function(side){
4642             var me = this,
4643                 key,
4644                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
4645                 o = {};
4646
4647             if (!side) {
4648                 for (key in me.margins){
4649                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
4650                 }
4651                 return o;
4652             } else {
4653                 return me.addStyles.call(me, side, me.margins);
4654             }
4655         }
4656     };
4657 }());
4658
4659 (function(){
4660 var D = Ext.lib.Dom,
4661         LEFT = "left",
4662         RIGHT = "right",
4663         TOP = "top",
4664         BOTTOM = "bottom",
4665         POSITION = "position",
4666         STATIC = "static",
4667         RELATIVE = "relative",
4668         AUTO = "auto",
4669         ZINDEX = "z-index";
4670
4671 Ext.Element.addMethods({
4672         
4673     getX : function(){
4674         return D.getX(this.dom);
4675     },
4676
4677     
4678     getY : function(){
4679         return D.getY(this.dom);
4680     },
4681
4682     
4683     getXY : function(){
4684         return D.getXY(this.dom);
4685     },
4686
4687     
4688     getOffsetsTo : function(el){
4689         var o = this.getXY(),
4690                 e = Ext.fly(el, '_internal').getXY();
4691         return [o[0]-e[0],o[1]-e[1]];
4692     },
4693
4694     
4695     setX : function(x, animate){            
4696             return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
4697     },
4698
4699     
4700     setY : function(y, animate){            
4701             return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
4702     },
4703
4704     
4705     setLeft : function(left){
4706         this.setStyle(LEFT, this.addUnits(left));
4707         return this;
4708     },
4709
4710     
4711     setTop : function(top){
4712         this.setStyle(TOP, this.addUnits(top));
4713         return this;
4714     },
4715
4716     
4717     setRight : function(right){
4718         this.setStyle(RIGHT, this.addUnits(right));
4719         return this;
4720     },
4721
4722     
4723     setBottom : function(bottom){
4724         this.setStyle(BOTTOM, this.addUnits(bottom));
4725         return this;
4726     },
4727
4728     
4729     setXY : function(pos, animate){
4730             var me = this;
4731         if(!animate || !me.anim){
4732             D.setXY(me.dom, pos);
4733         }else{
4734             me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
4735         }
4736         return me;
4737     },
4738
4739     
4740     setLocation : function(x, y, animate){
4741         return this.setXY([x, y], this.animTest(arguments, animate, 2));
4742     },
4743
4744     
4745     moveTo : function(x, y, animate){
4746         return this.setXY([x, y], this.animTest(arguments, animate, 2));        
4747     },    
4748     
4749     
4750     getLeft : function(local){
4751             return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
4752     },
4753
4754     
4755     getRight : function(local){
4756             var me = this;
4757             return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
4758     },
4759
4760     
4761     getTop : function(local) {
4762             return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
4763     },
4764
4765     
4766     getBottom : function(local){
4767             var me = this;
4768             return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
4769     },
4770
4771     
4772     position : function(pos, zIndex, x, y){
4773             var me = this;
4774             
4775         if(!pos && me.isStyle(POSITION, STATIC)){           
4776             me.setStyle(POSITION, RELATIVE);           
4777         } else if(pos) {
4778             me.setStyle(POSITION, pos);
4779         }
4780         if(zIndex){
4781             me.setStyle(ZINDEX, zIndex);
4782         }
4783         if(x || y) me.setXY([x || false, y || false]);
4784     },
4785
4786     
4787     clearPositioning : function(value){
4788         value = value || '';
4789         this.setStyle({
4790             left : value,
4791             right : value,
4792             top : value,
4793             bottom : value,
4794             "z-index" : "",
4795             position : STATIC
4796         });
4797         return this;
4798     },
4799
4800     
4801     getPositioning : function(){
4802         var l = this.getStyle(LEFT);
4803         var t = this.getStyle(TOP);
4804         return {
4805             "position" : this.getStyle(POSITION),
4806             "left" : l,
4807             "right" : l ? "" : this.getStyle(RIGHT),
4808             "top" : t,
4809             "bottom" : t ? "" : this.getStyle(BOTTOM),
4810             "z-index" : this.getStyle(ZINDEX)
4811         };
4812     },
4813     
4814     
4815     setPositioning : function(pc){
4816             var me = this,
4817                 style = me.dom.style;
4818                 
4819         me.setStyle(pc);
4820         
4821         if(pc.right == AUTO){
4822             style.right = "";
4823         }
4824         if(pc.bottom == AUTO){
4825             style.bottom = "";
4826         }
4827         
4828         return me;
4829     },    
4830         
4831     
4832     translatePoints : function(x, y){                
4833             y = isNaN(x[1]) ? y : x[1];
4834         x = isNaN(x[0]) ? x : x[0];
4835         var me = this,
4836                 relative = me.isStyle(POSITION, RELATIVE),
4837                 o = me.getXY(),
4838                 l = parseInt(me.getStyle(LEFT), 10),
4839                 t = parseInt(me.getStyle(TOP), 10);
4840         
4841         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
4842         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
4843
4844         return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
4845     },
4846     
4847     animTest : function(args, animate, i) {
4848         return !!animate && this.preanim ? this.preanim(args, i) : false;
4849     }
4850 });
4851 })();
4852 Ext.Element.addMethods({
4853     
4854     setBox : function(box, adjust, animate){
4855         var me = this,
4856                 w = box.width, 
4857                 h = box.height;
4858         if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
4859            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
4860            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
4861         }
4862         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
4863         return me;
4864     },
4865
4866     
4867         getBox : function(contentBox, local) {      
4868             var me = this,
4869                 xy,
4870                 left,
4871                 top,
4872                 getBorderWidth = me.getBorderWidth,
4873                 getPadding = me.getPadding, 
4874                 l,
4875                 r,
4876                 t,
4877                 b;
4878         if(!local){
4879             xy = me.getXY();
4880         }else{
4881             left = parseInt(me.getStyle("left"), 10) || 0;
4882             top = parseInt(me.getStyle("top"), 10) || 0;
4883             xy = [left, top];
4884         }
4885         var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
4886         if(!contentBox){
4887             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
4888         }else{
4889             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
4890             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
4891             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
4892             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
4893             bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
4894         }
4895         bx.right = bx.x + bx.width;
4896         bx.bottom = bx.y + bx.height;
4897         return bx;
4898         },
4899         
4900     
4901      move : function(direction, distance, animate){
4902         var me = this,          
4903                 xy = me.getXY(),
4904                 x = xy[0],
4905                 y = xy[1],              
4906                 left = [x - distance, y],
4907                 right = [x + distance, y],
4908                 top = [x, y - distance],
4909                 bottom = [x, y + distance],
4910                 hash = {
4911                         l :     left,
4912                         left : left,
4913                         r : right,
4914                         right : right,
4915                         t : top,
4916                         top : top,
4917                         up : top,
4918                         b : bottom, 
4919                         bottom : bottom,
4920                         down : bottom                           
4921                 };
4922         
4923             direction = direction.toLowerCase();    
4924             me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
4925     },
4926     
4927     
4928      setLeftTop : function(left, top){
4929             var me = this,
4930                 style = me.dom.style;
4931         style.left = me.addUnits(left);
4932         style.top = me.addUnits(top);
4933         return me;
4934     },
4935     
4936     
4937     getRegion : function(){
4938         return Ext.lib.Dom.getRegion(this.dom);
4939     },
4940     
4941     
4942     setBounds : function(x, y, width, height, animate){
4943             var me = this;
4944         if (!animate || !me.anim) {
4945             me.setSize(width, height);
4946             me.setLocation(x, y);
4947         } else {
4948             me.anim({points: {to: [x, y]}, 
4949                          width: {to: me.adjustWidth(width)}, 
4950                          height: {to: me.adjustHeight(height)}},
4951                      me.preanim(arguments, 4), 
4952                      'motion');
4953         }
4954         return me;
4955     },
4956
4957     
4958     setRegion : function(region, animate) {
4959         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
4960     }
4961 });
4962 Ext.Element.addMethods({
4963     
4964     isScrollable : function(){
4965         var dom = this.dom;
4966         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
4967     },
4968
4969     
4970     scrollTo : function(side, value){
4971         this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
4972         return this;
4973     },
4974
4975     
4976     getScroll : function(){
4977         var d = this.dom, 
4978             doc = document,
4979             body = doc.body,
4980             docElement = doc.documentElement,
4981             l,
4982             t,
4983             ret;
4984
4985         if(d == doc || d == body){
4986             if(Ext.isIE && Ext.isStrict){
4987                 l = docElement.scrollLeft; 
4988                 t = docElement.scrollTop;
4989             }else{
4990                 l = window.pageXOffset;
4991                 t = window.pageYOffset;
4992             }
4993             ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
4994         }else{
4995             ret = {left: d.scrollLeft, top: d.scrollTop};
4996         }
4997         return ret;
4998     }
4999 });
5000 Ext.Element.addMethods({
5001     
5002     scrollTo : function(side, value, animate){
5003         var top = /top/i.test(side), 
5004                 me = this,
5005                 dom = me.dom,
5006             prop;
5007         if (!animate || !me.anim) {
5008             prop = 'scroll' + (top ? 'Top' : 'Left'), 
5009             dom[prop] = value;
5010         }else{
5011             prop = 'scroll' + (top ? 'Left' : 'Top'), 
5012             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}},
5013                          me.preanim(arguments, 2), 'scroll');
5014         }
5015         return me;
5016     },
5017     
5018     
5019     scrollIntoView : function(container, hscroll){
5020         var c = Ext.getDom(container) || Ext.getBody().dom,
5021                 el = this.dom,
5022                 o = this.getOffsetsTo(c),
5023             l = o[0] + c.scrollLeft,
5024             t = o[1] + c.scrollTop,
5025             b = t + el.offsetHeight,
5026             r = l + el.offsetWidth,
5027                 ch = c.clientHeight,
5028                 ct = parseInt(c.scrollTop, 10),
5029                 cl = parseInt(c.scrollLeft, 10),
5030                 cb = ct + ch,
5031                 cr = cl + c.clientWidth;
5032
5033         if (el.offsetHeight > ch || t < ct) {
5034                 c.scrollTop = t;
5035         } else if (b > cb){
5036             c.scrollTop = b-ch;
5037         }
5038         c.scrollTop = c.scrollTop; 
5039
5040         if(hscroll !== false){
5041                         if(el.offsetWidth > c.clientWidth || l < cl){
5042                 c.scrollLeft = l;
5043             }else if(r > cr){
5044                 c.scrollLeft = r - c.clientWidth;
5045             }
5046             c.scrollLeft = c.scrollLeft;
5047         }
5048         return this;
5049     },
5050
5051     
5052     scrollChildIntoView : function(child, hscroll){
5053         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
5054     },
5055     
5056     
5057      scroll : function(direction, distance, animate){
5058          if(!this.isScrollable()){
5059              return;
5060          }
5061          var el = this.dom,
5062             l = el.scrollLeft, t = el.scrollTop,
5063             w = el.scrollWidth, h = el.scrollHeight,
5064             cw = el.clientWidth, ch = el.clientHeight,
5065             scrolled = false, v,
5066             hash = {
5067                 l: Math.min(l + distance, w-cw),
5068                 r: v = Math.max(l - distance, 0),
5069                 t: Math.max(t - distance, 0),
5070                 b: Math.min(t + distance, h-ch)
5071             };
5072             hash.d = hash.b;
5073             hash.u = hash.t;
5074             
5075          direction = direction.substr(0, 1);
5076          if((v = hash[direction]) > -1){
5077             scrolled = true;
5078             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
5079          }
5080          return scrolled;
5081     }
5082 });
5083
5084 Ext.Element.VISIBILITY = 1;
5085
5086 Ext.Element.DISPLAY = 2;
5087
5088 Ext.Element.addMethods(function(){
5089     var VISIBILITY = "visibility",
5090         DISPLAY = "display",
5091         HIDDEN = "hidden",
5092         OFFSETS = "offsets",
5093         NONE = "none",
5094         ORIGINALDISPLAY = 'originalDisplay',
5095         VISMODE = 'visibilityMode',
5096         ELDISPLAY = Ext.Element.DISPLAY,
5097         data = Ext.Element.data,
5098         getDisplay = function(dom){
5099             var d = data(dom, ORIGINALDISPLAY);
5100             if(d === undefined){
5101                 data(dom, ORIGINALDISPLAY, d = '');
5102             }
5103             return d;
5104         },
5105         getVisMode = function(dom){
5106             var m = data(dom, VISMODE);
5107             if(m === undefined){
5108                 data(dom, VISMODE, m = 1);
5109             }
5110             return m;
5111         };
5112
5113     return {
5114         
5115         originalDisplay : "",
5116         visibilityMode : 1,
5117
5118         
5119         setVisibilityMode : function(visMode){
5120             data(this.dom, VISMODE, visMode);
5121             return this;
5122         },
5123
5124         
5125         animate : function(args, duration, onComplete, easing, animType){
5126             this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
5127             return this;
5128         },
5129
5130         
5131         anim : function(args, opt, animType, defaultDur, defaultEase, cb){
5132             animType = animType || 'run';
5133             opt = opt || {};
5134             var me = this,
5135                 anim = Ext.lib.Anim[animType](
5136                     me.dom,
5137                     args,
5138                     (opt.duration || defaultDur) || .35,
5139                     (opt.easing || defaultEase) || 'easeOut',
5140                     function(){
5141                         if(cb) cb.call(me);
5142                         if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
5143                     },
5144                     me
5145                 );
5146             opt.anim = anim;
5147             return anim;
5148         },
5149
5150         
5151         preanim : function(a, i){
5152             return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
5153         },
5154
5155         
5156         isVisible : function() {
5157             return !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
5158         },
5159
5160         
5161          setVisible : function(visible, animate){
5162             var me = this, isDisplay, isVisible, isOffsets,
5163                 dom = me.dom;
5164
5165             
5166             if (typeof animate == 'string'){
5167                 isDisplay = animate == DISPLAY;
5168                 isVisible = animate == VISIBILITY;
5169                 isOffsets = animate == OFFSETS;
5170                 animate = false;
5171             } else {
5172                 isDisplay = getVisMode(this.dom) == ELDISPLAY;
5173                 isVisible = !isDisplay;
5174             }
5175
5176             if (!animate || !me.anim) {
5177                 if (isDisplay){
5178                     me.setDisplayed(visible);
5179                 } else if (isOffsets){
5180                     if (!visible){
5181                         me.hideModeStyles = {
5182                             position: me.getStyle('position'),
5183                             top: me.getStyle('top'),
5184                             left: me.getStyle('left')
5185                         };
5186
5187                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
5188                     } else {
5189                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
5190                     }
5191                 }else{
5192                     me.fixDisplay();
5193                     dom.style.visibility = visible ? "visible" : HIDDEN;
5194                 }
5195             }else{
5196                 
5197                 if (visible){
5198                     me.setOpacity(.01);
5199                     me.setVisible(true);
5200                 }
5201                 me.anim({opacity: { to: (visible?1:0) }},
5202                         me.preanim(arguments, 1),
5203                         null,
5204                         .35,
5205                         'easeIn',
5206                         function(){
5207                              if(!visible){
5208                                  dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;
5209                                  Ext.fly(dom).setOpacity(1);
5210                              }
5211                         });
5212             }
5213             return me;
5214         },
5215
5216         
5217         toggle : function(animate){
5218             var me = this;
5219             me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
5220             return me;
5221         },
5222
5223         
5224         setDisplayed : function(value) {
5225             if(typeof value == "boolean"){
5226                value = value ? getDisplay(this.dom) : NONE;
5227             }
5228             this.setStyle(DISPLAY, value);
5229             return this;
5230         },
5231
5232         
5233         fixDisplay : function(){
5234             var me = this;
5235             if(me.isStyle(DISPLAY, NONE)){
5236                 me.setStyle(VISIBILITY, HIDDEN);
5237                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
5238                 if(me.isStyle(DISPLAY, NONE)){ 
5239                     me.setStyle(DISPLAY, "block");
5240                 }
5241             }
5242         },
5243
5244         
5245         hide : function(animate){
5246             
5247             if (typeof animate == 'string'){
5248                 this.setVisible(false, animate);
5249                 return this;
5250             }
5251             this.setVisible(false, this.preanim(arguments, 0));
5252             return this;
5253         },
5254
5255         
5256         show : function(animate){
5257             
5258             if (typeof animate == 'string'){
5259                 this.setVisible(true, animate);
5260                 return this;
5261             }
5262             this.setVisible(true, this.preanim(arguments, 0));
5263             return this;
5264         }
5265     };
5266 }());
5267
5268 Ext.Element.addMethods(
5269 function(){
5270     var VISIBILITY = "visibility",
5271         DISPLAY = "display",
5272         HIDDEN = "hidden",
5273         NONE = "none",
5274             XMASKED = "x-masked",
5275                 XMASKEDRELATIVE = "x-masked-relative",
5276         data = Ext.Element.data;
5277
5278         return {
5279                 
5280             isVisible : function(deep) {
5281                 var vis = !this.isStyle(VISIBILITY,HIDDEN) && !this.isStyle(DISPLAY,NONE),
5282                         p = this.dom.parentNode;
5283                 if(deep !== true || !vis){
5284                     return vis;
5285                 }
5286                 while(p && !/^body/i.test(p.tagName)){
5287                     if(!Ext.fly(p, '_isVisible').isVisible()){
5288                         return false;
5289                     }
5290                     p = p.parentNode;
5291                 }
5292                 return true;
5293             },
5294
5295             
5296             isDisplayed : function() {
5297                 return !this.isStyle(DISPLAY, NONE);
5298             },
5299
5300                 
5301             enableDisplayMode : function(display){
5302                 this.setVisibilityMode(Ext.Element.DISPLAY);
5303                 if(!Ext.isEmpty(display)){
5304                 data(this.dom, 'originalDisplay', display);
5305             }
5306                 return this;
5307             },
5308
5309                 
5310             mask : function(msg, msgCls){
5311                     var me = this,
5312                         dom = me.dom,
5313                         dh = Ext.DomHelper,
5314                         EXTELMASKMSG = "ext-el-mask-msg",
5315                 el,
5316                 mask;
5317
5318                 if(!/^body/i.test(dom.tagName) && me.getStyle('position') == 'static'){
5319                     me.addClass(XMASKEDRELATIVE);
5320                 }
5321                 if((el = data(dom, 'maskMsg'))){
5322                     el.remove();
5323                 }
5324                 if((el = data(dom, 'mask'))){
5325                     el.remove();
5326                 }
5327
5328             mask = dh.append(dom, {cls : "ext-el-mask"}, true);
5329                 data(dom, 'mask', mask);
5330
5331                 me.addClass(XMASKED);
5332                 mask.setDisplayed(true);
5333                 if(typeof msg == 'string'){
5334                 var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
5335                 data(dom, 'maskMsg', mm);
5336                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
5337                     mm.dom.firstChild.innerHTML = msg;
5338                     mm.setDisplayed(true);
5339                     mm.center(me);
5340                 }
5341                 if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto'){ 
5342                     mask.setSize(undefined, me.getHeight());
5343                 }
5344                 return mask;
5345             },
5346
5347             
5348             unmask : function(){
5349                     var me = this,
5350                 dom = me.dom,
5351                         mask = data(dom, 'mask'),
5352                         maskMsg = data(dom, 'maskMsg');
5353                 if(mask){
5354                     if(maskMsg){
5355                         maskMsg.remove();
5356                     data(dom, 'maskMsg', undefined);
5357                     }
5358                     mask.remove();
5359                 data(dom, 'mask', undefined);
5360                 }
5361                 me.removeClass([XMASKED, XMASKEDRELATIVE]);
5362             },
5363
5364             
5365             isMasked : function(){
5366             var m = data(this.dom, 'mask');
5367                 return m && m.isVisible();
5368             },
5369
5370             
5371             createShim : function(){
5372                 var el = document.createElement('iframe'),
5373                         shim;
5374                 el.frameBorder = '0';
5375                 el.className = 'ext-shim';
5376                 el.src = Ext.SSL_SECURE_URL;
5377                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
5378                 shim.autoBoxAdjust = false;
5379                 return shim;
5380             }
5381     };
5382 }());
5383 Ext.Element.addMethods({
5384     
5385     addKeyListener : function(key, fn, scope){
5386         var config;
5387         if(typeof key != 'object' || Ext.isArray(key)){
5388             config = {
5389                 key: key,
5390                 fn: fn,
5391                 scope: scope
5392             };
5393         }else{
5394             config = {
5395                 key : key.key,
5396                 shift : key.shift,
5397                 ctrl : key.ctrl,
5398                 alt : key.alt,
5399                 fn: fn,
5400                 scope: scope
5401             };
5402         }
5403         return new Ext.KeyMap(this, config);
5404     },
5405
5406     
5407     addKeyMap : function(config){
5408         return new Ext.KeyMap(this, config);
5409     }
5410 });
5411 (function(){
5412     
5413     var NULL = null,
5414         UNDEFINED = undefined,
5415         TRUE = true,
5416         FALSE = false,
5417         SETX = "setX",
5418         SETY = "setY",
5419         SETXY = "setXY",
5420         LEFT = "left",
5421         BOTTOM = "bottom",
5422         TOP = "top",
5423         RIGHT = "right",
5424         HEIGHT = "height",
5425         WIDTH = "width",
5426         POINTS = "points",
5427         HIDDEN = "hidden",
5428         ABSOLUTE = "absolute",
5429         VISIBLE = "visible",
5430         MOTION = "motion",
5431         POSITION = "position",
5432         EASEOUT = "easeOut",
5433         
5434         flyEl = new Ext.Element.Flyweight(),
5435         queues = {},
5436         getObject = function(o){
5437             return o || {};
5438         },
5439         fly = function(dom){
5440             flyEl.dom = dom;
5441             flyEl.id = Ext.id(dom);
5442             return flyEl;
5443         },
5444         
5445         getQueue = function(id){
5446             if(!queues[id]){
5447                 queues[id] = [];
5448             }
5449             return queues[id];
5450         },
5451         setQueue = function(id, value){
5452             queues[id] = value;
5453         };
5454         
5455
5456 Ext.enableFx = TRUE;
5457
5458
5459 Ext.Fx = {
5460     
5461     
5462     
5463     switchStatements : function(key, fn, argHash){
5464         return fn.apply(this, argHash[key]);
5465     },
5466     
5467     
5468     slideIn : function(anchor, o){ 
5469         o = getObject(o);
5470         var me = this,
5471             dom = me.dom,
5472             st = dom.style,
5473             xy,
5474             r,
5475             b,              
5476             wrap,               
5477             after,
5478             st,
5479             args, 
5480             pt,
5481             bw,
5482             bh;
5483             
5484         anchor = anchor || "t";
5485
5486         me.queueFx(o, function(){            
5487             xy = fly(dom).getXY();
5488             
5489             fly(dom).fixDisplay();            
5490             
5491             
5492             r = fly(dom).getFxRestore();      
5493             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5494             b.right = b.x + b.width;
5495             b.bottom = b.y + b.height;
5496             
5497             
5498             fly(dom).setWidth(b.width).setHeight(b.height);            
5499             
5500             
5501             wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
5502             
5503             st.visibility = VISIBLE;
5504             st.position = ABSOLUTE;
5505             
5506             
5507             function after(){
5508                  fly(dom).fxUnwrap(wrap, r.pos, o);
5509                  st.width = r.width;
5510                  st.height = r.height;
5511                  fly(dom).afterFx(o);
5512             }
5513             
5514             
5515             pt = {to: [b.x, b.y]}; 
5516             bw = {to: b.width};
5517             bh = {to: b.height};
5518                 
5519             function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
5520                 var ret = {};
5521                 fly(wrap).setWidth(ww).setHeight(wh);
5522                 if(fly(wrap)[sXY]){
5523                     fly(wrap)[sXY](sXYval);                  
5524                 }
5525                 style[s1] = style[s2] = "0";                    
5526                 if(w){
5527                     ret.width = w
5528                 };
5529                 if(h){
5530                     ret.height = h;
5531                 }
5532                 if(p){
5533                     ret.points = p;
5534                 }
5535                 return ret;
5536             };
5537
5538             args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5539                     t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
5540                     l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
5541                     r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
5542                     b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
5543                     tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
5544                     bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
5545                     br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
5546                     tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
5547                 });
5548             
5549             st.visibility = VISIBLE;
5550             fly(wrap).show();
5551
5552             arguments.callee.anim = fly(wrap).fxanim(args,
5553                 o,
5554                 MOTION,
5555                 .5,
5556                 EASEOUT, 
5557                 after);
5558         });
5559         return me;
5560     },
5561     
5562     
5563     slideOut : function(anchor, o){
5564         o = getObject(o);
5565         var me = this,
5566             dom = me.dom,
5567             st = dom.style,
5568             xy = me.getXY(),
5569             wrap,
5570             r,
5571             b,
5572             a,
5573             zero = {to: 0}; 
5574                     
5575         anchor = anchor || "t";
5576
5577         me.queueFx(o, function(){
5578             
5579             
5580             r = fly(dom).getFxRestore(); 
5581             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5582             b.right = b.x + b.width;
5583             b.bottom = b.y + b.height;
5584                 
5585             
5586             fly(dom).setWidth(b.width).setHeight(b.height);
5587
5588             
5589             wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
5590                 
5591             st.visibility = VISIBLE;
5592             st.position = ABSOLUTE;
5593             fly(wrap).setWidth(b.width).setHeight(b.height);            
5594
5595             function after(){
5596                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
5597                 fly(dom).fxUnwrap(wrap, r.pos, o);
5598                 st.width = r.width;
5599                 st.height = r.height;
5600                 fly(dom).afterFx(o);
5601             }            
5602             
5603             function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
5604                 var ret = {};
5605                 
5606                 style[s1] = style[s2] = "0";
5607                 ret[p1] = v1;               
5608                 if(p2){
5609                     ret[p2] = v2;               
5610                 }
5611                 if(p3){
5612                     ret[p3] = v3;
5613                 }
5614                 
5615                 return ret;
5616             };
5617             
5618             a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5619                 t  : [st, LEFT, BOTTOM, HEIGHT, zero],
5620                 l  : [st, RIGHT, TOP, WIDTH, zero],
5621                 r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
5622                 b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5623                 tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
5624                 bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5625                 br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
5626                 tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
5627             });
5628             
5629             arguments.callee.anim = fly(wrap).fxanim(a,
5630                 o,
5631                 MOTION,
5632                 .5,
5633                 EASEOUT, 
5634                 after);
5635         });
5636         return me;
5637     },
5638
5639     
5640     puff : function(o){
5641         o = getObject(o);
5642         var me = this,
5643             dom = me.dom,
5644             st = dom.style,
5645             width,
5646             height,
5647             r;
5648
5649         me.queueFx(o, function(){
5650             width = fly(dom).getWidth();
5651             height = fly(dom).getHeight();
5652             fly(dom).clearOpacity();
5653             fly(dom).show();
5654
5655             
5656             r = fly(dom).getFxRestore();                   
5657             
5658             function after(){
5659                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
5660                 fly(dom).clearOpacity();  
5661                 fly(dom).setPositioning(r.pos);
5662                 st.width = r.width;
5663                 st.height = r.height;
5664                 st.fontSize = '';
5665                 fly(dom).afterFx(o);
5666             }   
5667
5668             arguments.callee.anim = fly(dom).fxanim({
5669                     width : {to : fly(dom).adjustWidth(width * 2)},
5670                     height : {to : fly(dom).adjustHeight(height * 2)},
5671                     points : {by : [-width * .5, -height * .5]},
5672                     opacity : {to : 0},
5673                     fontSize: {to : 200, unit: "%"}
5674                 },
5675                 o,
5676                 MOTION,
5677                 .5,
5678                 EASEOUT,
5679                  after);
5680         });
5681         return me;
5682     },
5683
5684     
5685     switchOff : function(o){
5686         o = getObject(o);
5687         var me = this,
5688             dom = me.dom,
5689             st = dom.style,
5690             r;
5691
5692         me.queueFx(o, function(){
5693             fly(dom).clearOpacity();
5694             fly(dom).clip();
5695
5696             
5697             r = fly(dom).getFxRestore();
5698                 
5699             function after(){
5700                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
5701                 fly(dom).clearOpacity();
5702                 fly(dom).setPositioning(r.pos);
5703                 st.width = r.width;
5704                 st.height = r.height;   
5705                 fly(dom).afterFx(o);
5706             };
5707
5708             fly(dom).fxanim({opacity : {to : 0.3}}, 
5709                 NULL, 
5710                 NULL, 
5711                 .1, 
5712                 NULL, 
5713                 function(){                                 
5714                     fly(dom).clearOpacity();
5715                         (function(){                            
5716                             fly(dom).fxanim({
5717                                 height : {to : 1},
5718                                 points : {by : [0, fly(dom).getHeight() * .5]}
5719                             }, 
5720                             o, 
5721                             MOTION, 
5722                             0.3, 
5723                             'easeIn', 
5724                             after);
5725                         }).defer(100);
5726                 });
5727         });
5728         return me;
5729     },
5730
5731      
5732     highlight : function(color, o){
5733         o = getObject(o);
5734         var me = this,
5735             dom = me.dom,
5736             attr = o.attr || "backgroundColor",
5737             a = {},
5738             restore;
5739
5740         me.queueFx(o, function(){
5741             fly(dom).clearOpacity();
5742             fly(dom).show();
5743
5744             function after(){
5745                 dom.style[attr] = restore;
5746                 fly(dom).afterFx(o);
5747             }            
5748             restore = dom.style[attr];
5749             a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
5750             arguments.callee.anim = fly(dom).fxanim(a,
5751                 o,
5752                 'color',
5753                 1,
5754                 'easeIn', 
5755                 after);
5756         });
5757         return me;
5758     },
5759
5760    
5761     frame : function(color, count, o){
5762         o = getObject(o);
5763         var me = this,
5764             dom = me.dom,
5765             proxy,
5766             active;
5767
5768         me.queueFx(o, function(){
5769             color = color || '#C3DAF9';
5770             if(color.length == 6){
5771                 color = '#' + color;
5772             }            
5773             count = count || 1;
5774             fly(dom).show();
5775
5776             var xy = fly(dom).getXY(),
5777                 b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
5778                 queue = function(){
5779                     proxy = fly(document.body || document.documentElement).createChild({
5780                         style:{
5781                             position : ABSOLUTE,
5782                             'z-index': 35000, 
5783                             border : '0px solid ' + color
5784                         }
5785                     });
5786                     return proxy.queueFx({}, animFn);
5787                 };
5788             
5789             
5790             arguments.callee.anim = {
5791                 isAnimated: true,
5792                 stop: function() {
5793                     count = 0;
5794                     proxy.stopFx();
5795                 }
5796             };
5797             
5798             function animFn(){
5799                 var scale = Ext.isBorderBox ? 2 : 1;
5800                 active = proxy.anim({
5801                     top : {from : b.y, to : b.y - 20},
5802                     left : {from : b.x, to : b.x - 20},
5803                     borderWidth : {from : 0, to : 10},
5804                     opacity : {from : 1, to : 0},
5805                     height : {from : b.height, to : b.height + 20 * scale},
5806                     width : {from : b.width, to : b.width + 20 * scale}
5807                 },{
5808                     duration: o.duration || 1,
5809                     callback: function() {
5810                         proxy.remove();
5811                         --count > 0 ? queue() : fly(dom).afterFx(o);
5812                     }
5813                 });
5814                 arguments.callee.anim = {
5815                     isAnimated: true,
5816                     stop: function(){
5817                         active.stop();
5818                     }
5819                 };
5820             };
5821             queue();
5822         });
5823         return me;
5824     },
5825
5826    
5827     pause : function(seconds){        
5828         var dom = this.dom,
5829             t;
5830
5831         this.queueFx({}, function(){
5832             t = setTimeout(function(){
5833                 fly(dom).afterFx({});
5834             }, seconds * 1000);
5835             arguments.callee.anim = {
5836                 isAnimated: true,
5837                 stop: function(){
5838                     clearTimeout(t);
5839                     fly(dom).afterFx({});
5840                 }
5841             };
5842         });
5843         return this;
5844     },
5845
5846    
5847     fadeIn : function(o){
5848         o = getObject(o);
5849         var me = this,
5850             dom = me.dom,
5851             to = o.endOpacity || 1;
5852         
5853         me.queueFx(o, function(){
5854             fly(dom).setOpacity(0);
5855             fly(dom).fixDisplay();
5856             dom.style.visibility = VISIBLE;
5857             arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
5858                 o, NULL, .5, EASEOUT, function(){
5859                 if(to == 1){
5860                     fly(dom).clearOpacity();
5861                 }
5862                 fly(dom).afterFx(o);
5863             });
5864         });
5865         return me;
5866     },
5867
5868    
5869     fadeOut : function(o){
5870         o = getObject(o);
5871         var me = this,
5872             dom = me.dom,
5873             style = dom.style,
5874             to = o.endOpacity || 0;         
5875         
5876         me.queueFx(o, function(){  
5877             arguments.callee.anim = fly(dom).fxanim({ 
5878                 opacity : {to : to}},
5879                 o, 
5880                 NULL, 
5881                 .5, 
5882                 EASEOUT, 
5883                 function(){
5884                     if(to == 0){
5885                         Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
5886                             style.display = "none" :
5887                             style.visibility = HIDDEN;
5888                             
5889                         fly(dom).clearOpacity();
5890                     }
5891                     fly(dom).afterFx(o);
5892             });
5893         });
5894         return me;
5895     },
5896
5897    
5898     scale : function(w, h, o){
5899         this.shift(Ext.apply({}, o, {
5900             width: w,
5901             height: h
5902         }));
5903         return this;
5904     },
5905
5906    
5907     shift : function(o){
5908         o = getObject(o);
5909         var dom = this.dom,
5910             a = {};
5911                 
5912         this.queueFx(o, function(){
5913             for (var prop in o) {
5914                 if (o[prop] != UNDEFINED) {                                                 
5915                     a[prop] = {to : o[prop]};                   
5916                 }
5917             } 
5918             
5919             a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
5920             a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
5921             
5922             if (a.x || a.y || a.xy) {
5923                 a.points = a.xy || 
5924                            {to : [ a.x ? a.x.to : fly(dom).getX(),
5925                                    a.y ? a.y.to : fly(dom).getY()]};                  
5926             }
5927
5928             arguments.callee.anim = fly(dom).fxanim(a,
5929                 o, 
5930                 MOTION, 
5931                 .35, 
5932                 EASEOUT, 
5933                 function(){
5934                     fly(dom).afterFx(o);
5935                 });
5936         });
5937         return this;
5938     },
5939
5940     
5941     ghost : function(anchor, o){
5942         o = getObject(o);
5943         var me = this,
5944             dom = me.dom,
5945             st = dom.style,
5946             a = {opacity: {to: 0}, points: {}},
5947             pt = a.points,
5948             r,
5949             w,
5950             h;
5951             
5952         anchor = anchor || "b";
5953
5954         me.queueFx(o, function(){
5955             
5956             r = fly(dom).getFxRestore();
5957             w = fly(dom).getWidth();
5958             h = fly(dom).getHeight();
5959             
5960             function after(){
5961                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
5962                 fly(dom).clearOpacity();
5963                 fly(dom).setPositioning(r.pos);
5964                 st.width = r.width;
5965                 st.height = r.height;
5966                 fly(dom).afterFx(o);
5967             }
5968                 
5969             pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
5970                t  : [0, -h],
5971                l  : [-w, 0],
5972                r  : [w, 0],
5973                b  : [0, h],
5974                tl : [-w, -h],
5975                bl : [-w, h],
5976                br : [w, h],
5977                tr : [w, -h] 
5978             });
5979                 
5980             arguments.callee.anim = fly(dom).fxanim(a,
5981                 o,
5982                 MOTION,
5983                 .5,
5984                 EASEOUT, after);
5985         });
5986         return me;
5987     },
5988
5989     
5990     syncFx : function(){
5991         var me = this;
5992         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
5993             block : FALSE,
5994             concurrent : TRUE,
5995             stopFx : FALSE
5996         });
5997         return me;
5998     },
5999
6000     
6001     sequenceFx : function(){
6002         var me = this;
6003         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
6004             block : FALSE,
6005             concurrent : FALSE,
6006             stopFx : FALSE
6007         });
6008         return me;
6009     },
6010
6011     
6012     nextFx : function(){        
6013         var ef = getQueue(this.dom.id)[0];
6014         if(ef){
6015             ef.call(this);
6016         }
6017     },
6018
6019     
6020     hasActiveFx : function(){
6021         return getQueue(this.dom.id)[0];
6022     },
6023
6024     
6025     stopFx : function(finish){
6026         var me = this,
6027             id = me.dom.id;
6028         if(me.hasActiveFx()){
6029             var cur = getQueue(id)[0];
6030             if(cur && cur.anim){
6031                 if(cur.anim.isAnimated){
6032                     setQueue(id, [cur]); 
6033                     cur.anim.stop(finish !== undefined ? finish : TRUE);
6034                 }else{
6035                     setQueue(id, []);
6036                 }
6037             }
6038         }
6039         return me;
6040     },
6041
6042     
6043     beforeFx : function(o){
6044         if(this.hasActiveFx() && !o.concurrent){
6045            if(o.stopFx){
6046                this.stopFx();
6047                return TRUE;
6048            }
6049            return FALSE;
6050         }
6051         return TRUE;
6052     },
6053
6054     
6055     hasFxBlock : function(){
6056         var q = getQueue(this.dom.id);
6057         return q && q[0] && q[0].block;
6058     },
6059
6060     
6061     queueFx : function(o, fn){
6062         var me = fly(this.dom);
6063         if(!me.hasFxBlock()){
6064             Ext.applyIf(o, me.fxDefaults);
6065             if(!o.concurrent){
6066                 var run = me.beforeFx(o);
6067                 fn.block = o.block;
6068                 getQueue(me.dom.id).push(fn);
6069                 if(run){
6070                     me.nextFx();
6071                 }
6072             }else{
6073                 fn.call(me);
6074             }
6075         }
6076         return me;
6077     },
6078
6079     
6080     fxWrap : function(pos, o, vis){ 
6081         var dom = this.dom,
6082             wrap,
6083             wrapXY;
6084         if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
6085             if(o.fixPosition){
6086                 wrapXY = fly(dom).getXY();
6087             }
6088             var div = document.createElement("div");
6089             div.style.visibility = vis;
6090             wrap = dom.parentNode.insertBefore(div, dom);
6091             fly(wrap).setPositioning(pos);
6092             if(fly(wrap).isStyle(POSITION, "static")){
6093                 fly(wrap).position("relative");
6094             }
6095             fly(dom).clearPositioning('auto');
6096             fly(wrap).clip();
6097             wrap.appendChild(dom);
6098             if(wrapXY){
6099                 fly(wrap).setXY(wrapXY);
6100             }
6101         }
6102         return wrap;
6103     },
6104
6105     
6106     fxUnwrap : function(wrap, pos, o){      
6107         var dom = this.dom;
6108         fly(dom).clearPositioning();
6109         fly(dom).setPositioning(pos);
6110         if(!o.wrap){
6111             var pn = fly(wrap).dom.parentNode;
6112             pn.insertBefore(dom, wrap); 
6113             fly(wrap).remove();
6114         }
6115     },
6116
6117     
6118     getFxRestore : function(){
6119         var st = this.dom.style;
6120         return {pos: this.getPositioning(), width: st.width, height : st.height};
6121     },
6122
6123     
6124     afterFx : function(o){
6125         var dom = this.dom,
6126             id = dom.id;
6127         if(o.afterStyle){
6128             fly(dom).setStyle(o.afterStyle);            
6129         }
6130         if(o.afterCls){
6131             fly(dom).addClass(o.afterCls);
6132         }
6133         if(o.remove == TRUE){
6134             fly(dom).remove();
6135         }
6136         if(o.callback){
6137             o.callback.call(o.scope, fly(dom));
6138         }
6139         if(!o.concurrent){
6140             getQueue(id).shift();
6141             fly(dom).nextFx();
6142         }
6143     },
6144
6145     
6146     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
6147         animType = animType || 'run';
6148         opt = opt || {};
6149         var anim = Ext.lib.Anim[animType](
6150                 this.dom, 
6151                 args,
6152                 (opt.duration || defaultDur) || .35,
6153                 (opt.easing || defaultEase) || EASEOUT,
6154                 cb,            
6155                 this
6156             );
6157         opt.anim = anim;
6158         return anim;
6159     }
6160 };
6161
6162
6163 Ext.Fx.resize = Ext.Fx.scale;
6164
6165
6166
6167 Ext.Element.addMethods(Ext.Fx);
6168 })();
6169
6170 Ext.CompositeElementLite = function(els, root){
6171     
6172     this.elements = [];
6173     this.add(els, root);
6174     this.el = new Ext.Element.Flyweight();
6175 };
6176
6177 Ext.CompositeElementLite.prototype = {
6178     isComposite: true,
6179
6180     
6181     getElement : function(el){
6182         
6183         var e = this.el;
6184         e.dom = el;
6185         e.id = el.id;
6186         return e;
6187     },
6188
6189     
6190     transformElement : function(el){
6191         return Ext.getDom(el);
6192     },
6193
6194     
6195     getCount : function(){
6196         return this.elements.length;
6197     },
6198     
6199     add : function(els, root){
6200         var me = this,
6201             elements = me.elements;
6202         if(!els){
6203             return this;
6204         }
6205         if(typeof els == "string"){
6206             els = Ext.Element.selectorFunction(els, root);
6207         }else if(els.isComposite){
6208             els = els.elements;
6209         }else if(!Ext.isIterable(els)){
6210             els = [els];
6211         }
6212
6213         for(var i = 0, len = els.length; i < len; ++i){
6214             elements.push(me.transformElement(els[i]));
6215         }
6216         return me;
6217     },
6218
6219     invoke : function(fn, args){
6220         var me = this,
6221             els = me.elements,
6222             len = els.length,
6223             e,
6224             i;
6225
6226         for(i = 0; i < len; i++) {
6227             e = els[i];
6228             if(e){
6229                 Ext.Element.prototype[fn].apply(me.getElement(e), args);
6230             }
6231         }
6232         return me;
6233     },
6234     
6235     item : function(index){
6236         var me = this,
6237             el = me.elements[index],
6238             out = null;
6239
6240         if(el){
6241             out = me.getElement(el);
6242         }
6243         return out;
6244     },
6245
6246     
6247     addListener : function(eventName, handler, scope, opt){
6248         var els = this.elements,
6249             len = els.length,
6250             i, e;
6251
6252         for(i = 0; i<len; i++) {
6253             e = els[i];
6254             if(e) {
6255                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
6256             }
6257         }
6258         return this;
6259     },
6260     
6261     each : function(fn, scope){
6262         var me = this,
6263             els = me.elements,
6264             len = els.length,
6265             i, e;
6266
6267         for(i = 0; i<len; i++) {
6268             e = els[i];
6269             if(e){
6270                 e = this.getElement(e);
6271                 if(fn.call(scope || e, e, me, i) === false){
6272                     break;
6273                 }
6274             }
6275         }
6276         return me;
6277     },
6278
6279     
6280     fill : function(els){
6281         var me = this;
6282         me.elements = [];
6283         me.add(els);
6284         return me;
6285     },
6286
6287     
6288     filter : function(selector){
6289         var els = [],
6290             me = this,
6291             elements = me.elements,
6292             fn = Ext.isFunction(selector) ? selector
6293                 : function(el){
6294                     return el.is(selector);
6295                 };
6296
6297
6298         me.each(function(el, self, i){
6299             if(fn(el, i) !== false){
6300                 els[els.length] = me.transformElement(el);
6301             }
6302         });
6303         me.elements = els;
6304         return me;
6305     },
6306
6307     
6308     indexOf : function(el){
6309         return this.elements.indexOf(this.transformElement(el));
6310     },
6311
6312     
6313     replaceElement : function(el, replacement, domReplace){
6314         var index = !isNaN(el) ? el : this.indexOf(el),
6315             d;
6316         if(index > -1){
6317             replacement = Ext.getDom(replacement);
6318             if(domReplace){
6319                 d = this.elements[index];
6320                 d.parentNode.insertBefore(replacement, d);
6321                 Ext.removeNode(d);
6322             }
6323             this.elements.splice(index, 1, replacement);
6324         }
6325         return this;
6326     },
6327
6328     
6329     clear : function(){
6330         this.elements = [];
6331     }
6332 };
6333
6334 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
6335
6336 (function(){
6337 var fnName,
6338     ElProto = Ext.Element.prototype,
6339     CelProto = Ext.CompositeElementLite.prototype;
6340
6341 for(fnName in ElProto){
6342     if(Ext.isFunction(ElProto[fnName])){
6343         (function(fnName){
6344             CelProto[fnName] = CelProto[fnName] || function(){
6345                 return this.invoke(fnName, arguments);
6346             };
6347         }).call(CelProto, fnName);
6348
6349     }
6350 }
6351 })();
6352
6353 if(Ext.DomQuery){
6354     Ext.Element.selectorFunction = Ext.DomQuery.select;
6355 }
6356
6357
6358 Ext.Element.select = function(selector, root){
6359     var els;
6360     if(typeof selector == "string"){
6361         els = Ext.Element.selectorFunction(selector, root);
6362     }else if(selector.length !== undefined){
6363         els = selector;
6364     }else{
6365         throw "Invalid selector";
6366     }
6367     return new Ext.CompositeElementLite(els);
6368 };
6369
6370 Ext.select = Ext.Element.select;
6371
6372 Ext.apply(Ext.CompositeElementLite.prototype, {
6373     addElements : function(els, root){
6374         if(!els){
6375             return this;
6376         }
6377         if(typeof els == "string"){
6378             els = Ext.Element.selectorFunction(els, root);
6379         }
6380         var yels = this.elements;
6381         Ext.each(els, function(e) {
6382             yels.push(Ext.get(e));
6383         });
6384         return this;
6385     },
6386
6387     
6388     first : function(){
6389         return this.item(0);
6390     },
6391
6392     
6393     last : function(){
6394         return this.item(this.getCount()-1);
6395     },
6396
6397     
6398     contains : function(el){
6399         return this.indexOf(el) != -1;
6400     },
6401
6402     
6403     removeElement : function(keys, removeDom){
6404         var me = this,
6405             els = this.elements,
6406             el;
6407         Ext.each(keys, function(val){
6408             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
6409                 if(removeDom){
6410                     if(el.dom){
6411                         el.remove();
6412                     }else{
6413                         Ext.removeNode(el);
6414                     }
6415                 }
6416                 els.splice(val, 1);
6417             }
6418         });
6419         return this;
6420     }
6421 });
6422
6423 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
6424     
6425     constructor : function(els, root){
6426         this.elements = [];
6427         this.add(els, root);
6428     },
6429     
6430     
6431     getElement : function(el){
6432         
6433         return el;
6434     },
6435     
6436     
6437     transformElement : function(el){
6438         return Ext.get(el);
6439     }
6440
6441     
6442
6443     
6444
6445     
6446 });
6447
6448
6449 Ext.Element.select = function(selector, unique, root){
6450     var els;
6451     if(typeof selector == "string"){
6452         els = Ext.Element.selectorFunction(selector, root);
6453     }else if(selector.length !== undefined){
6454         els = selector;
6455     }else{
6456         throw "Invalid selector";
6457     }
6458
6459     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
6460 };
6461
6462
6463 Ext.select = Ext.Element.select;(function(){
6464     var BEFOREREQUEST = "beforerequest",
6465         REQUESTCOMPLETE = "requestcomplete",
6466         REQUESTEXCEPTION = "requestexception",
6467         UNDEFINED = undefined,
6468         LOAD = 'load',
6469         POST = 'POST',
6470         GET = 'GET',
6471         WINDOW = window;
6472
6473     
6474     Ext.data.Connection = function(config){
6475         Ext.apply(this, config);
6476         this.addEvents(
6477             
6478             BEFOREREQUEST,
6479             
6480             REQUESTCOMPLETE,
6481             
6482             REQUESTEXCEPTION
6483         );
6484         Ext.data.Connection.superclass.constructor.call(this);
6485     };
6486
6487     Ext.extend(Ext.data.Connection, Ext.util.Observable, {
6488         
6489         
6490         
6491         
6492         
6493         timeout : 30000,
6494         
6495         autoAbort:false,
6496
6497         
6498         disableCaching: true,
6499
6500         
6501         disableCachingParam: '_dc',
6502
6503         
6504         request : function(o){
6505             var me = this;
6506             if(me.fireEvent(BEFOREREQUEST, me, o)){
6507                 if (o.el) {
6508                     if(!Ext.isEmpty(o.indicatorText)){
6509                         me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
6510                     }
6511                     if(me.indicatorText) {
6512                         Ext.getDom(o.el).innerHTML = me.indicatorText;
6513                     }
6514                     o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
6515                         Ext.getDom(o.el).innerHTML = response.responseText;
6516                     });
6517                 }
6518
6519                 var p = o.params,
6520                     url = o.url || me.url,
6521                     method,
6522                     cb = {success: me.handleResponse,
6523                           failure: me.handleFailure,
6524                           scope: me,
6525                           argument: {options: o},
6526                           timeout : o.timeout || me.timeout
6527                     },
6528                     form,
6529                     serForm;
6530
6531
6532                 if (Ext.isFunction(p)) {
6533                     p = p.call(o.scope||WINDOW, o);
6534                 }
6535
6536                 p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
6537
6538                 if (Ext.isFunction(url)) {
6539                     url = url.call(o.scope || WINDOW, o);
6540                 }
6541
6542                 if((form = Ext.getDom(o.form))){
6543                     url = url || form.action;
6544                      if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) {
6545                          return me.doFormUpload.call(me, o, p, url);
6546                      }
6547                     serForm = Ext.lib.Ajax.serializeForm(form);
6548                     p = p ? (p + '&' + serForm) : serForm;
6549                 }
6550
6551                 method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
6552
6553                 if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
6554                     var dcp = o.disableCachingParam || me.disableCachingParam;
6555                     url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
6556                 }
6557
6558                 o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
6559
6560                 if(o.autoAbort === true || me.autoAbort) {
6561                     me.abort();
6562                 }
6563
6564                 if((method == GET || o.xmlData || o.jsonData) && p){
6565                     url = Ext.urlAppend(url, p);
6566                     p = '';
6567                 }
6568                 return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
6569             }else{
6570                 return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
6571             }
6572         },
6573
6574         
6575         isLoading : function(transId){
6576             return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
6577         },
6578
6579         
6580         abort : function(transId){
6581             if(transId || this.isLoading()){
6582                 Ext.lib.Ajax.abort(transId || this.transId);
6583             }
6584         },
6585
6586         
6587         handleResponse : function(response){
6588             this.transId = false;
6589             var options = response.argument.options;
6590             response.argument = options ? options.argument : null;
6591             this.fireEvent(REQUESTCOMPLETE, this, response, options);
6592             if(options.success){
6593                 options.success.call(options.scope, response, options);
6594             }
6595             if(options.callback){
6596                 options.callback.call(options.scope, options, true, response);
6597             }
6598         },
6599
6600         
6601         handleFailure : function(response, e){
6602             this.transId = false;
6603             var options = response.argument.options;
6604             response.argument = options ? options.argument : null;
6605             this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
6606             if(options.failure){
6607                 options.failure.call(options.scope, response, options);
6608             }
6609             if(options.callback){
6610                 options.callback.call(options.scope, options, false, response);
6611             }
6612         },
6613
6614         
6615         doFormUpload : function(o, ps, url){
6616             var id = Ext.id(),
6617                 doc = document,
6618                 frame = doc.createElement('iframe'),
6619                 form = Ext.getDom(o.form),
6620                 hiddens = [],
6621                 hd,
6622                 encoding = 'multipart/form-data',
6623                 buf = {
6624                     target: form.target,
6625                     method: form.method,
6626                     encoding: form.encoding,
6627                     enctype: form.enctype,
6628                     action: form.action
6629                 };
6630
6631             
6632             Ext.fly(frame).set({
6633                 id: id,
6634                 name: id,
6635                 cls: 'x-hidden',
6636                 src: Ext.SSL_SECURE_URL
6637             }); 
6638
6639             doc.body.appendChild(frame);
6640
6641             
6642             if(Ext.isIE){
6643                document.frames[id].name = id;
6644             }
6645
6646
6647             Ext.fly(form).set({
6648                 target: id,
6649                 method: POST,
6650                 enctype: encoding,
6651                 encoding: encoding,
6652                 action: url || buf.action
6653             });
6654
6655             
6656             Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
6657                 hd = doc.createElement('input');
6658                 Ext.fly(hd).set({
6659                     type: 'hidden',
6660                     value: v,
6661                     name: k
6662                 });
6663                 form.appendChild(hd);
6664                 hiddens.push(hd);
6665             });
6666
6667             function cb(){
6668                 var me = this,
6669                     
6670                     r = {responseText : '',
6671                          responseXML : null,
6672                          argument : o.argument},
6673                     doc,
6674                     firstChild;
6675
6676                 try{
6677                     doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
6678                     if(doc){
6679                         if(doc.body){
6680                             if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
6681                                 r.responseText = firstChild.value;
6682                             }else{
6683                                 r.responseText = doc.body.innerHTML;
6684                             }
6685                         }
6686                         
6687                         r.responseXML = doc.XMLDocument || doc;
6688                     }
6689                 }
6690                 catch(e) {}
6691
6692                 Ext.EventManager.removeListener(frame, LOAD, cb, me);
6693
6694                 me.fireEvent(REQUESTCOMPLETE, me, r, o);
6695
6696                 function runCallback(fn, scope, args){
6697                     if(Ext.isFunction(fn)){
6698                         fn.apply(scope, args);
6699                     }
6700                 }
6701
6702                 runCallback(o.success, o.scope, [r, o]);
6703                 runCallback(o.callback, o.scope, [o, true, r]);
6704
6705                 if(!me.debugUploads){
6706                     setTimeout(function(){Ext.removeNode(frame);}, 100);
6707                 }
6708             }
6709
6710             Ext.EventManager.on(frame, LOAD, cb, this);
6711             form.submit();
6712
6713             Ext.fly(form).set(buf);
6714             Ext.each(hiddens, function(h) {
6715                 Ext.removeNode(h);
6716             });
6717         }
6718     });
6719 })();
6720
6721
6722 Ext.Ajax = new Ext.data.Connection({
6723     
6724     
6725     
6726     
6727     
6728     
6729
6730     
6731
6732     
6733     
6734     
6735     
6736     
6737     
6738
6739     
6740     autoAbort : false,
6741
6742     
6743     serializeForm : function(form){
6744         return Ext.lib.Ajax.serializeForm(form);
6745     }
6746 });
6747
6748 Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
6749 function() {
6750     var BEFOREUPDATE = "beforeupdate",
6751         UPDATE = "update",
6752         FAILURE = "failure";
6753
6754     
6755     function processSuccess(response){
6756         var me = this;
6757         me.transaction = null;
6758         if (response.argument.form && response.argument.reset) {
6759             try { 
6760                 response.argument.form.reset();
6761             } catch(e){}
6762         }
6763         if (me.loadScripts) {
6764             me.renderer.render(me.el, response, me,
6765                updateComplete.createDelegate(me, [response]));
6766         } else {
6767             me.renderer.render(me.el, response, me);
6768             updateComplete.call(me, response);
6769         }
6770     }
6771
6772     
6773     function updateComplete(response, type, success){
6774         this.fireEvent(type || UPDATE, this.el, response);
6775         if(Ext.isFunction(response.argument.callback)){
6776             response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
6777         }
6778     }
6779
6780     
6781     function processFailure(response){
6782         updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
6783     }
6784
6785     return {
6786         constructor: function(el, forceNew){
6787             var me = this;
6788             el = Ext.get(el);
6789             if(!forceNew && el.updateManager){
6790                 return el.updateManager;
6791             }
6792             
6793             me.el = el;
6794             
6795             me.defaultUrl = null;
6796
6797             me.addEvents(
6798                 
6799                 BEFOREUPDATE,
6800                 
6801                 UPDATE,
6802                 
6803                 FAILURE
6804             );
6805
6806             Ext.apply(me, Ext.Updater.defaults);
6807             
6808             
6809             
6810             
6811             
6812             
6813
6814             
6815             me.transaction = null;
6816             
6817             me.refreshDelegate = me.refresh.createDelegate(me);
6818             
6819             me.updateDelegate = me.update.createDelegate(me);
6820             
6821             me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
6822
6823             
6824             me.renderer = me.renderer || me.getDefaultRenderer();
6825
6826             Ext.Updater.superclass.constructor.call(me);
6827         },
6828
6829         
6830         setRenderer : function(renderer){
6831             this.renderer = renderer;
6832         },
6833
6834         
6835         getRenderer : function(){
6836            return this.renderer;
6837         },
6838
6839         
6840         getDefaultRenderer: function() {
6841             return new Ext.Updater.BasicRenderer();
6842         },
6843
6844         
6845         setDefaultUrl : function(defaultUrl){
6846             this.defaultUrl = defaultUrl;
6847         },
6848
6849         
6850         getEl : function(){
6851             return this.el;
6852         },
6853
6854         
6855         update : function(url, params, callback, discardUrl){
6856             var me = this,
6857                 cfg,
6858                 callerScope;
6859
6860             if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
6861                 if(Ext.isObject(url)){ 
6862                     cfg = url;
6863                     url = cfg.url;
6864                     params = params || cfg.params;
6865                     callback = callback || cfg.callback;
6866                     discardUrl = discardUrl || cfg.discardUrl;
6867                     callerScope = cfg.scope;
6868                     if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
6869                     if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
6870                     if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
6871                     if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
6872                 }
6873                 me.showLoading();
6874
6875                 if(!discardUrl){
6876                     me.defaultUrl = url;
6877                 }
6878                 if(Ext.isFunction(url)){
6879                     url = url.call(me);
6880                 }
6881
6882                 var o = Ext.apply({}, {
6883                     url : url,
6884                     params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
6885                     success: processSuccess,
6886                     failure: processFailure,
6887                     scope: me,
6888                     callback: undefined,
6889                     timeout: (me.timeout*1000),
6890                     disableCaching: me.disableCaching,
6891                     argument: {
6892                         "options": cfg,
6893                         "url": url,
6894                         "form": null,
6895                         "callback": callback,
6896                         "scope": callerScope || window,
6897                         "params": params
6898                     }
6899                 }, cfg);
6900
6901                 me.transaction = Ext.Ajax.request(o);
6902             }
6903         },
6904
6905         
6906         formUpdate : function(form, url, reset, callback){
6907             var me = this;
6908             if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
6909                 if(Ext.isFunction(url)){
6910                     url = url.call(me);
6911                 }
6912                 form = Ext.getDom(form);
6913                 me.transaction = Ext.Ajax.request({
6914                     form: form,
6915                     url:url,
6916                     success: processSuccess,
6917                     failure: processFailure,
6918                     scope: me,
6919                     timeout: (me.timeout*1000),
6920                     argument: {
6921                         "url": url,
6922                         "form": form,
6923                         "callback": callback,
6924                         "reset": reset
6925                     }
6926                 });
6927                 me.showLoading.defer(1, me);
6928             }
6929         },
6930
6931         
6932         startAutoRefresh : function(interval, url, params, callback, refreshNow){
6933             var me = this;
6934             if(refreshNow){
6935                 me.update(url || me.defaultUrl, params, callback, true);
6936             }
6937             if(me.autoRefreshProcId){
6938                 clearInterval(me.autoRefreshProcId);
6939             }
6940             me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
6941         },
6942
6943         
6944         stopAutoRefresh : function(){
6945             if(this.autoRefreshProcId){
6946                 clearInterval(this.autoRefreshProcId);
6947                 delete this.autoRefreshProcId;
6948             }
6949         },
6950
6951         
6952         isAutoRefreshing : function(){
6953            return !!this.autoRefreshProcId;
6954         },
6955
6956         
6957         showLoading : function(){
6958             if(this.showLoadIndicator){
6959                 this.el.dom.innerHTML = this.indicatorText;
6960             }
6961         },
6962
6963         
6964         abort : function(){
6965             if(this.transaction){
6966                 Ext.Ajax.abort(this.transaction);
6967             }
6968         },
6969
6970         
6971         isUpdating : function(){
6972             return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
6973         },
6974
6975         
6976         refresh : function(callback){
6977             if(this.defaultUrl){
6978                 this.update(this.defaultUrl, null, callback, true);
6979             }
6980         }
6981     }
6982 }());
6983
6984
6985 Ext.Updater.defaults = {
6986    
6987     timeout : 30,
6988     
6989     disableCaching : false,
6990     
6991     showLoadIndicator : true,
6992     
6993     indicatorText : '<div class="loading-indicator">Loading...</div>',
6994      
6995     loadScripts : false,
6996     
6997     sslBlankUrl : Ext.SSL_SECURE_URL
6998 };
6999
7000
7001
7002 Ext.Updater.updateElement = function(el, url, params, options){
7003     var um = Ext.get(el).getUpdater();
7004     Ext.apply(um, options);
7005     um.update(url, params, options ? options.callback : null);
7006 };
7007
7008
7009 Ext.Updater.BasicRenderer = function(){};
7010
7011 Ext.Updater.BasicRenderer.prototype = {
7012     
7013      render : function(el, response, updateManager, callback){
7014         el.update(response.responseText, updateManager.loadScripts, callback);
7015     }
7016 };
7017
7018
7019
7020 (function() {
7021
7022
7023 Date.useStrict = false;
7024
7025
7026
7027
7028
7029 function xf(format) {
7030     var args = Array.prototype.slice.call(arguments, 1);
7031     return format.replace(/\{(\d+)\}/g, function(m, i) {
7032         return args[i];
7033     });
7034 }
7035
7036
7037
7038 Date.formatCodeToRegex = function(character, currentGroup) {
7039     
7040     var p = Date.parseCodes[character];
7041
7042     if (p) {
7043       p = typeof p == 'function'? p() : p;
7044       Date.parseCodes[character] = p; 
7045     }
7046
7047     return p ? Ext.applyIf({
7048       c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
7049     }, p) : {
7050         g:0,
7051         c:null,
7052         s:Ext.escapeRe(character) 
7053     }
7054 };
7055
7056
7057 var $f = Date.formatCodeToRegex;
7058
7059 Ext.apply(Date, {
7060     
7061     parseFunctions: {
7062         "M$": function(input, strict) {
7063             
7064             
7065             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
7066             var r = (input || '').match(re);
7067             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
7068         }
7069     },
7070     parseRegexes: [],
7071
7072     
7073     formatFunctions: {
7074         "M$": function() {
7075             
7076             return '\\/Date(' + this.getTime() + ')\\/';
7077         }
7078     },
7079
7080     y2kYear : 50,
7081
7082     
7083     MILLI : "ms",
7084
7085     
7086     SECOND : "s",
7087
7088     
7089     MINUTE : "mi",
7090
7091     
7092     HOUR : "h",
7093
7094     
7095     DAY : "d",
7096
7097     
7098     MONTH : "mo",
7099
7100     
7101     YEAR : "y",
7102
7103     
7104     defaults: {},
7105
7106     
7107     dayNames : [
7108         "Sunday",
7109         "Monday",
7110         "Tuesday",
7111         "Wednesday",
7112         "Thursday",
7113         "Friday",
7114         "Saturday"
7115     ],
7116
7117     
7118     monthNames : [
7119         "January",
7120         "February",
7121         "March",
7122         "April",
7123         "May",
7124         "June",
7125         "July",
7126         "August",
7127         "September",
7128         "October",
7129         "November",
7130         "December"
7131     ],
7132
7133     
7134     monthNumbers : {
7135         Jan:0,
7136         Feb:1,
7137         Mar:2,
7138         Apr:3,
7139         May:4,
7140         Jun:5,
7141         Jul:6,
7142         Aug:7,
7143         Sep:8,
7144         Oct:9,
7145         Nov:10,
7146         Dec:11
7147     },
7148
7149     
7150     getShortMonthName : function(month) {
7151         return Date.monthNames[month].substring(0, 3);
7152     },
7153
7154     
7155     getShortDayName : function(day) {
7156         return Date.dayNames[day].substring(0, 3);
7157     },
7158
7159     
7160     getMonthNumber : function(name) {
7161         
7162         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
7163     },
7164
7165     
7166     formatCodes : {
7167         d: "String.leftPad(this.getDate(), 2, '0')",
7168         D: "Date.getShortDayName(this.getDay())", 
7169         j: "this.getDate()",
7170         l: "Date.dayNames[this.getDay()]",
7171         N: "(this.getDay() ? this.getDay() : 7)",
7172         S: "this.getSuffix()",
7173         w: "this.getDay()",
7174         z: "this.getDayOfYear()",
7175         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
7176         F: "Date.monthNames[this.getMonth()]",
7177         m: "String.leftPad(this.getMonth() + 1, 2, '0')",
7178         M: "Date.getShortMonthName(this.getMonth())", 
7179         n: "(this.getMonth() + 1)",
7180         t: "this.getDaysInMonth()",
7181         L: "(this.isLeapYear() ? 1 : 0)",
7182         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
7183         Y: "this.getFullYear()",
7184         y: "('' + this.getFullYear()).substring(2, 4)",
7185         a: "(this.getHours() < 12 ? 'am' : 'pm')",
7186         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
7187         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
7188         G: "this.getHours()",
7189         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
7190         H: "String.leftPad(this.getHours(), 2, '0')",
7191         i: "String.leftPad(this.getMinutes(), 2, '0')",
7192         s: "String.leftPad(this.getSeconds(), 2, '0')",
7193         u: "String.leftPad(this.getMilliseconds(), 3, '0')",
7194         O: "this.getGMTOffset()",
7195         P: "this.getGMTOffset(true)",
7196         T: "this.getTimezone()",
7197         Z: "(this.getTimezoneOffset() * -60)",
7198
7199         c: function() { 
7200             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
7201                 var e = c.charAt(i);
7202                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
7203             }
7204             return code.join(" + ");
7205         },
7206         
7207
7208         U: "Math.round(this.getTime() / 1000)"
7209     },
7210
7211     
7212     isValid : function(y, m, d, h, i, s, ms) {
7213         
7214         h = h || 0;
7215         i = i || 0;
7216         s = s || 0;
7217         ms = ms || 0;
7218
7219         var dt = new Date(y, m - 1, d, h, i, s, ms);
7220
7221         return y == dt.getFullYear() &&
7222             m == dt.getMonth() + 1 &&
7223             d == dt.getDate() &&
7224             h == dt.getHours() &&
7225             i == dt.getMinutes() &&
7226             s == dt.getSeconds() &&
7227             ms == dt.getMilliseconds();
7228     },
7229
7230     
7231     parseDate : function(input, format, strict) {
7232         var p = Date.parseFunctions;
7233         if (p[format] == null) {
7234             Date.createParser(format);
7235         }
7236         return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
7237     },
7238
7239     
7240     getFormatCode : function(character) {
7241         var f = Date.formatCodes[character];
7242
7243         if (f) {
7244           f = typeof f == 'function'? f() : f;
7245           Date.formatCodes[character] = f; 
7246         }
7247
7248         
7249         return f || ("'" + String.escape(character) + "'");
7250     },
7251
7252     
7253     createFormat : function(format) {
7254         var code = [],
7255             special = false,
7256             ch = '';
7257
7258         for (var i = 0; i < format.length; ++i) {
7259             ch = format.charAt(i);
7260             if (!special && ch == "\\") {
7261                 special = true;
7262             } else if (special) {
7263                 special = false;
7264                 code.push("'" + String.escape(ch) + "'");
7265             } else {
7266                 code.push(Date.getFormatCode(ch))
7267             }
7268         }
7269         Date.formatFunctions[format] = new Function("return " + code.join('+'));
7270     },
7271
7272     
7273     createParser : function() {
7274         var code = [
7275             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
7276                 "def = Date.defaults,",
7277                 "results = String(input).match(Date.parseRegexes[{0}]);", 
7278
7279             "if(results){",
7280                 "{1}",
7281
7282                 "if(u != null){", 
7283                     "v = new Date(u * 1000);", 
7284                 "}else{",
7285                     
7286                     
7287                     
7288                     "dt = (new Date()).clearTime();",
7289
7290                     
7291                     "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
7292                     "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
7293                     "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
7294
7295                     
7296                     "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
7297                     "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
7298                     "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
7299                     "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
7300
7301                     "if(z >= 0 && y >= 0){",
7302                         
7303                         
7304
7305                         
7306                         "v = new Date(y, 0, 1, h, i, s, ms);",
7307
7308                         
7309                         "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
7310                     "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
7311                         "v = null;", 
7312                     "}else{",
7313                         
7314                         "v = new Date(y, m, d, h, i, s, ms);",
7315                     "}",
7316                 "}",
7317             "}",
7318
7319             "if(v){",
7320                 
7321                 "if(zz != null){",
7322                     
7323                     "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
7324                 "}else if(o){",
7325                     
7326                     "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
7327                 "}",
7328             "}",
7329
7330             "return v;"
7331         ].join('\n');
7332
7333         return function(format) {
7334             var regexNum = Date.parseRegexes.length,
7335                 currentGroup = 1,
7336                 calc = [],
7337                 regex = [],
7338                 special = false,
7339                 ch = "";
7340
7341             for (var i = 0; i < format.length; ++i) {
7342                 ch = format.charAt(i);
7343                 if (!special && ch == "\\") {
7344                     special = true;
7345                 } else if (special) {
7346                     special = false;
7347                     regex.push(String.escape(ch));
7348                 } else {
7349                     var obj = $f(ch, currentGroup);
7350                     currentGroup += obj.g;
7351                     regex.push(obj.s);
7352                     if (obj.g && obj.c) {
7353                         calc.push(obj.c);
7354                     }
7355                 }
7356             }
7357
7358             Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$");
7359             Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
7360         }
7361     }(),
7362
7363     
7364     parseCodes : {
7365         
7366         d: {
7367             g:1,
7368             c:"d = parseInt(results[{0}], 10);\n",
7369             s:"(\\d{2})" 
7370         },
7371         j: {
7372             g:1,
7373             c:"d = parseInt(results[{0}], 10);\n",
7374             s:"(\\d{1,2})" 
7375         },
7376         D: function() {
7377             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
7378             return {
7379                 g:0,
7380                 c:null,
7381                 s:"(?:" + a.join("|") +")"
7382             }
7383         },
7384         l: function() {
7385             return {
7386                 g:0,
7387                 c:null,
7388                 s:"(?:" + Date.dayNames.join("|") + ")"
7389             }
7390         },
7391         N: {
7392             g:0,
7393             c:null,
7394             s:"[1-7]" 
7395         },
7396         S: {
7397             g:0,
7398             c:null,
7399             s:"(?:st|nd|rd|th)"
7400         },
7401         w: {
7402             g:0,
7403             c:null,
7404             s:"[0-6]" 
7405         },
7406         z: {
7407             g:1,
7408             c:"z = parseInt(results[{0}], 10);\n",
7409             s:"(\\d{1,3})" 
7410         },
7411         W: {
7412             g:0,
7413             c:null,
7414             s:"(?:\\d{2})" 
7415         },
7416         F: function() {
7417             return {
7418                 g:1,
7419                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
7420                 s:"(" + Date.monthNames.join("|") + ")"
7421             }
7422         },
7423         M: function() {
7424             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
7425             return Ext.applyIf({
7426                 s:"(" + a.join("|") + ")"
7427             }, $f("F"));
7428         },
7429         m: {
7430             g:1,
7431             c:"m = parseInt(results[{0}], 10) - 1;\n",
7432             s:"(\\d{2})" 
7433         },
7434         n: {
7435             g:1,
7436             c:"m = parseInt(results[{0}], 10) - 1;\n",
7437             s:"(\\d{1,2})" 
7438         },
7439         t: {
7440             g:0,
7441             c:null,
7442             s:"(?:\\d{2})" 
7443         },
7444         L: {
7445             g:0,
7446             c:null,
7447             s:"(?:1|0)"
7448         },
7449         o: function() {
7450             return $f("Y");
7451         },
7452         Y: {
7453             g:1,
7454             c:"y = parseInt(results[{0}], 10);\n",
7455             s:"(\\d{4})" 
7456         },
7457         y: {
7458             g:1,
7459             c:"var ty = parseInt(results[{0}], 10);\n"
7460                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
7461             s:"(\\d{1,2})"
7462         },
7463         a: {
7464             g:1,
7465             c:"if (results[{0}] == 'am') {\n"
7466                 + "if (!h || h == 12) { h = 0; }\n"
7467                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7468             s:"(am|pm)"
7469         },
7470         A: {
7471             g:1,
7472             c:"if (results[{0}] == 'AM') {\n"
7473                 + "if (!h || h == 12) { h = 0; }\n"
7474                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7475             s:"(AM|PM)"
7476         },
7477         g: function() {
7478             return $f("G");
7479         },
7480         G: {
7481             g:1,
7482             c:"h = parseInt(results[{0}], 10);\n",
7483             s:"(\\d{1,2})" 
7484         },
7485         h: function() {
7486             return $f("H");
7487         },
7488         H: {
7489             g:1,
7490             c:"h = parseInt(results[{0}], 10);\n",
7491             s:"(\\d{2})" 
7492         },
7493         i: {
7494             g:1,
7495             c:"i = parseInt(results[{0}], 10);\n",
7496             s:"(\\d{2})" 
7497         },
7498         s: {
7499             g:1,
7500             c:"s = parseInt(results[{0}], 10);\n",
7501             s:"(\\d{2})" 
7502         },
7503         u: {
7504             g:1,
7505             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
7506             s:"(\\d+)" 
7507         },
7508         O: {
7509             g:1,
7510             c:[
7511                 "o = results[{0}];",
7512                 "var sn = o.substring(0,1),", 
7513                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
7514                     "mn = o.substring(3,5) % 60;", 
7515                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
7516             ].join("\n"),
7517             s: "([+\-]\\d{4})" 
7518         },
7519         P: {
7520             g:1,
7521             c:[
7522                 "o = results[{0}];",
7523                 "var sn = o.substring(0,1),", 
7524                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
7525                     "mn = o.substring(4,6) % 60;", 
7526                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
7527             ].join("\n"),
7528             s: "([+\-]\\d{2}:\\d{2})" 
7529         },
7530         T: {
7531             g:0,
7532             c:null,
7533             s:"[A-Z]{1,4}" 
7534         },
7535         Z: {
7536             g:1,
7537             c:"zz = results[{0}] * 1;\n" 
7538                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
7539             s:"([+\-]?\\d{1,5})" 
7540         },
7541         c: function() {
7542             var calc = [],
7543                 arr = [
7544                     $f("Y", 1), 
7545                     $f("m", 2), 
7546                     $f("d", 3), 
7547                     $f("h", 4), 
7548                     $f("i", 5), 
7549                     $f("s", 6), 
7550                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
7551                     {c:[ 
7552                         "if(results[8]) {", 
7553                             "if(results[8] == 'Z'){",
7554                                 "zz = 0;", 
7555                             "}else if (results[8].indexOf(':') > -1){",
7556                                 $f("P", 8).c, 
7557                             "}else{",
7558                                 $f("O", 8).c, 
7559                             "}",
7560                         "}"
7561                     ].join('\n')}
7562                 ];
7563
7564             for (var i = 0, l = arr.length; i < l; ++i) {
7565                 calc.push(arr[i].c);
7566             }
7567
7568             return {
7569                 g:1,
7570                 c:calc.join(""),
7571                 s:[
7572                     arr[0].s, 
7573                     "(?:", "-", arr[1].s, 
7574                         "(?:", "-", arr[2].s, 
7575                             "(?:",
7576                                 "(?:T| )?", 
7577                                 arr[3].s, ":", arr[4].s,  
7578                                 "(?::", arr[5].s, ")?", 
7579                                 "(?:(?:\\.|,)(\\d+))?", 
7580                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
7581                             ")?",
7582                         ")?",
7583                     ")?"
7584                 ].join("")
7585             }
7586         },
7587         U: {
7588             g:1,
7589             c:"u = parseInt(results[{0}], 10);\n",
7590             s:"(-?\\d+)" 
7591         }
7592     }
7593 });
7594
7595 }());
7596
7597 Ext.apply(Date.prototype, {
7598     
7599     dateFormat : function(format) {
7600         if (Date.formatFunctions[format] == null) {
7601             Date.createFormat(format);
7602         }
7603         return Date.formatFunctions[format].call(this);
7604     },
7605
7606     
7607     getTimezone : function() {
7608         
7609         
7610         
7611         
7612         
7613         
7614         
7615         
7616         
7617         
7618         
7619         
7620         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
7621     },
7622
7623     
7624     getGMTOffset : function(colon) {
7625         return (this.getTimezoneOffset() > 0 ? "-" : "+")
7626             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
7627             + (colon ? ":" : "")
7628             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
7629     },
7630
7631     
7632     getDayOfYear: function() {
7633         var num = 0,
7634             d = this.clone(),
7635             m = this.getMonth(),
7636             i;
7637
7638         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
7639             num += d.getDaysInMonth();
7640         }
7641         return num + this.getDate() - 1;
7642     },
7643
7644     
7645     getWeekOfYear : function() {
7646         
7647         var ms1d = 864e5, 
7648             ms7d = 7 * ms1d; 
7649
7650         return function() { 
7651             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
7652                 AWN = Math.floor(DC3 / 7), 
7653                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
7654
7655             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
7656         }
7657     }(),
7658
7659     
7660     isLeapYear : function() {
7661         var year = this.getFullYear();
7662         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
7663     },
7664
7665     
7666     getFirstDayOfMonth : function() {
7667         var day = (this.getDay() - (this.getDate() - 1)) % 7;
7668         return (day < 0) ? (day + 7) : day;
7669     },
7670
7671     
7672     getLastDayOfMonth : function() {
7673         return this.getLastDateOfMonth().getDay();
7674     },
7675
7676
7677     
7678     getFirstDateOfMonth : function() {
7679         return new Date(this.getFullYear(), this.getMonth(), 1);
7680     },
7681
7682     
7683     getLastDateOfMonth : function() {
7684         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
7685     },
7686
7687     
7688     getDaysInMonth: function() {
7689         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
7690
7691         return function() { 
7692             var m = this.getMonth();
7693
7694             return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
7695         }
7696     }(),
7697
7698     
7699     getSuffix : function() {
7700         switch (this.getDate()) {
7701             case 1:
7702             case 21:
7703             case 31:
7704                 return "st";
7705             case 2:
7706             case 22:
7707                 return "nd";
7708             case 3:
7709             case 23:
7710                 return "rd";
7711             default:
7712                 return "th";
7713         }
7714     },
7715
7716     
7717     clone : function() {
7718         return new Date(this.getTime());
7719     },
7720
7721     
7722     isDST : function() {
7723         
7724         
7725         return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
7726     },
7727
7728     
7729     clearTime : function(clone) {
7730         if (clone) {
7731             return this.clone().clearTime();
7732         }
7733
7734         
7735         var d = this.getDate();
7736
7737         
7738         this.setHours(0);
7739         this.setMinutes(0);
7740         this.setSeconds(0);
7741         this.setMilliseconds(0);
7742
7743         if (this.getDate() != d) { 
7744             
7745             
7746
7747             
7748             for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
7749
7750             this.setDate(d);
7751             this.setHours(c.getHours());
7752         }
7753
7754         return this;
7755     },
7756
7757     
7758     add : function(interval, value) {
7759         var d = this.clone();
7760         if (!interval || value === 0) return d;
7761
7762         switch(interval.toLowerCase()) {
7763             case Date.MILLI:
7764                 d.setMilliseconds(this.getMilliseconds() + value);
7765                 break;
7766             case Date.SECOND:
7767                 d.setSeconds(this.getSeconds() + value);
7768                 break;
7769             case Date.MINUTE:
7770                 d.setMinutes(this.getMinutes() + value);
7771                 break;
7772             case Date.HOUR:
7773                 d.setHours(this.getHours() + value);
7774                 break;
7775             case Date.DAY:
7776                 d.setDate(this.getDate() + value);
7777                 break;
7778             case Date.MONTH:
7779                 var day = this.getDate();
7780                 if (day > 28) {
7781                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
7782                 }
7783                 d.setDate(day);
7784                 d.setMonth(this.getMonth() + value);
7785                 break;
7786             case Date.YEAR:
7787                 d.setFullYear(this.getFullYear() + value);
7788                 break;
7789         }
7790         return d;
7791     },
7792
7793     
7794     between : function(start, end) {
7795         var t = this.getTime();
7796         return start.getTime() <= t && t <= end.getTime();
7797     }
7798 });
7799
7800
7801
7802 Date.prototype.format = Date.prototype.dateFormat;
7803
7804
7805
7806 if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
7807     Ext.apply(Date.prototype, {
7808         _xMonth : Date.prototype.setMonth,
7809         _xDate  : Date.prototype.setDate,
7810
7811         
7812         
7813         setMonth : function(num) {
7814             if (num <= -1) {
7815                 var n = Math.ceil(-num),
7816                     back_year = Math.ceil(n / 12),
7817                     month = (n % 12) ? 12 - n % 12 : 0;
7818
7819                 this.setFullYear(this.getFullYear() - back_year);
7820
7821                 return this._xMonth(month);
7822             } else {
7823                 return this._xMonth(num);
7824             }
7825         },
7826
7827         
7828         
7829         
7830         setDate : function(d) {
7831             
7832             
7833             return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
7834         }
7835     });
7836 }
7837
7838
7839
7840
7841
7842 Ext.util.MixedCollection = function(allowFunctions, keyFn){
7843     this.items = [];
7844     this.map = {};
7845     this.keys = [];
7846     this.length = 0;
7847     this.addEvents(
7848         
7849         'clear',
7850         
7851         'add',
7852         
7853         'replace',
7854         
7855         'remove',
7856         'sort'
7857     );
7858     this.allowFunctions = allowFunctions === true;
7859     if(keyFn){
7860         this.getKey = keyFn;
7861     }
7862     Ext.util.MixedCollection.superclass.constructor.call(this);
7863 };
7864
7865 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
7866
7867     
7868     allowFunctions : false,
7869
7870     
7871     add : function(key, o){
7872         if(arguments.length == 1){
7873             o = arguments[0];
7874             key = this.getKey(o);
7875         }
7876         if(typeof key != 'undefined' && key !== null){
7877             var old = this.map[key];
7878             if(typeof old != 'undefined'){
7879                 return this.replace(key, o);
7880             }
7881             this.map[key] = o;
7882         }
7883         this.length++;
7884         this.items.push(o);
7885         this.keys.push(key);
7886         this.fireEvent('add', this.length-1, o, key);
7887         return o;
7888     },
7889
7890     
7891     getKey : function(o){
7892          return o.id;
7893     },
7894
7895     
7896     replace : function(key, o){
7897         if(arguments.length == 1){
7898             o = arguments[0];
7899             key = this.getKey(o);
7900         }
7901         var old = this.map[key];
7902         if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
7903              return this.add(key, o);
7904         }
7905         var index = this.indexOfKey(key);
7906         this.items[index] = o;
7907         this.map[key] = o;
7908         this.fireEvent('replace', key, old, o);
7909         return o;
7910     },
7911
7912     
7913     addAll : function(objs){
7914         if(arguments.length > 1 || Ext.isArray(objs)){
7915             var args = arguments.length > 1 ? arguments : objs;
7916             for(var i = 0, len = args.length; i < len; i++){
7917                 this.add(args[i]);
7918             }
7919         }else{
7920             for(var key in objs){
7921                 if(this.allowFunctions || typeof objs[key] != 'function'){
7922                     this.add(key, objs[key]);
7923                 }
7924             }
7925         }
7926     },
7927
7928     
7929     each : function(fn, scope){
7930         var items = [].concat(this.items); 
7931         for(var i = 0, len = items.length; i < len; i++){
7932             if(fn.call(scope || items[i], items[i], i, len) === false){
7933                 break;
7934             }
7935         }
7936     },
7937
7938     
7939     eachKey : function(fn, scope){
7940         for(var i = 0, len = this.keys.length; i < len; i++){
7941             fn.call(scope || window, this.keys[i], this.items[i], i, len);
7942         }
7943     },
7944
7945     
7946     find : function(fn, scope){
7947         for(var i = 0, len = this.items.length; i < len; i++){
7948             if(fn.call(scope || window, this.items[i], this.keys[i])){
7949                 return this.items[i];
7950             }
7951         }
7952         return null;
7953     },
7954
7955     
7956     insert : function(index, key, o){
7957         if(arguments.length == 2){
7958             o = arguments[1];
7959             key = this.getKey(o);
7960         }
7961         if(this.containsKey(key)){
7962             this.suspendEvents();
7963             this.removeKey(key);
7964             this.resumeEvents();
7965         }
7966         if(index >= this.length){
7967             return this.add(key, o);
7968         }
7969         this.length++;
7970         this.items.splice(index, 0, o);
7971         if(typeof key != 'undefined' && key !== null){
7972             this.map[key] = o;
7973         }
7974         this.keys.splice(index, 0, key);
7975         this.fireEvent('add', index, o, key);
7976         return o;
7977     },
7978
7979     
7980     remove : function(o){
7981         return this.removeAt(this.indexOf(o));
7982     },
7983
7984     
7985     removeAt : function(index){
7986         if(index < this.length && index >= 0){
7987             this.length--;
7988             var o = this.items[index];
7989             this.items.splice(index, 1);
7990             var key = this.keys[index];
7991             if(typeof key != 'undefined'){
7992                 delete this.map[key];
7993             }
7994             this.keys.splice(index, 1);
7995             this.fireEvent('remove', o, key);
7996             return o;
7997         }
7998         return false;
7999     },
8000
8001     
8002     removeKey : function(key){
8003         return this.removeAt(this.indexOfKey(key));
8004     },
8005
8006     
8007     getCount : function(){
8008         return this.length;
8009     },
8010
8011     
8012     indexOf : function(o){
8013         return this.items.indexOf(o);
8014     },
8015
8016     
8017     indexOfKey : function(key){
8018         return this.keys.indexOf(key);
8019     },
8020
8021     
8022     item : function(key){
8023         var mk = this.map[key],
8024             item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
8025         return typeof item != 'function' || this.allowFunctions ? item : null; 
8026     },
8027
8028     
8029     itemAt : function(index){
8030         return this.items[index];
8031     },
8032
8033     
8034     key : function(key){
8035         return this.map[key];
8036     },
8037
8038     
8039     contains : function(o){
8040         return this.indexOf(o) != -1;
8041     },
8042
8043     
8044     containsKey : function(key){
8045         return typeof this.map[key] != 'undefined';
8046     },
8047
8048     
8049     clear : function(){
8050         this.length = 0;
8051         this.items = [];
8052         this.keys = [];
8053         this.map = {};
8054         this.fireEvent('clear');
8055     },
8056
8057     
8058     first : function(){
8059         return this.items[0];
8060     },
8061
8062     
8063     last : function(){
8064         return this.items[this.length-1];
8065     },
8066
8067     
8068     _sort : function(property, dir, fn){
8069         var i, len,
8070             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
8071
8072             
8073             c     = [],
8074             keys  = this.keys,
8075             items = this.items;
8076
8077         
8078         fn = fn || function(a, b) {
8079             return a - b;
8080         };
8081
8082         
8083         for(i = 0, len = items.length; i < len; i++){
8084             c[c.length] = {
8085                 key  : keys[i],
8086                 value: items[i],
8087                 index: i
8088             };
8089         }
8090
8091         
8092         c.sort(function(a, b){
8093             var v = fn(a[property], b[property]) * dsc;
8094             if(v === 0){
8095                 v = (a.index < b.index ? -1 : 1);
8096             }
8097             return v;
8098         });
8099
8100         
8101         for(i = 0, len = c.length; i < len; i++){
8102             items[i] = c[i].value;
8103             keys[i]  = c[i].key;
8104         }
8105
8106         this.fireEvent('sort', this);
8107     },
8108
8109     
8110     sort : function(dir, fn){
8111         this._sort('value', dir, fn);
8112     },
8113
8114     
8115     reorder: function(mapping) {
8116         this.suspendEvents();
8117
8118         var items     = this.items,
8119             index     = 0,
8120             length    = items.length,
8121             order     = [],
8122             remaining = [];
8123
8124         
8125         for (oldIndex in mapping) {
8126             order[mapping[oldIndex]] = items[oldIndex];
8127         }
8128
8129         for (index = 0; index < length; index++) {
8130             if (mapping[index] == undefined) {
8131                 remaining.push(items[index]);
8132             }
8133         }
8134
8135         for (index = 0; index < length; index++) {
8136             if (order[index] == undefined) {
8137                 order[index] = remaining.shift();
8138             }
8139         }
8140
8141         this.clear();
8142         this.addAll(order);
8143
8144         this.resumeEvents();
8145         this.fireEvent('sort', this);
8146     },
8147
8148     
8149     keySort : function(dir, fn){
8150         this._sort('key', dir, fn || function(a, b){
8151             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
8152             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
8153         });
8154     },
8155
8156     
8157     getRange : function(start, end){
8158         var items = this.items;
8159         if(items.length < 1){
8160             return [];
8161         }
8162         start = start || 0;
8163         end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
8164         var i, r = [];
8165         if(start <= end){
8166             for(i = start; i <= end; i++) {
8167                 r[r.length] = items[i];
8168             }
8169         }else{
8170             for(i = start; i >= end; i--) {
8171                 r[r.length] = items[i];
8172             }
8173         }
8174         return r;
8175     },
8176
8177     
8178     filter : function(property, value, anyMatch, caseSensitive){
8179         if(Ext.isEmpty(value, false)){
8180             return this.clone();
8181         }
8182         value = this.createValueMatcher(value, anyMatch, caseSensitive);
8183         return this.filterBy(function(o){
8184             return o && value.test(o[property]);
8185         });
8186     },
8187
8188     
8189     filterBy : function(fn, scope){
8190         var r = new Ext.util.MixedCollection();
8191         r.getKey = this.getKey;
8192         var k = this.keys, it = this.items;
8193         for(var i = 0, len = it.length; i < len; i++){
8194             if(fn.call(scope||this, it[i], k[i])){
8195                 r.add(k[i], it[i]);
8196             }
8197         }
8198         return r;
8199     },
8200
8201     
8202     findIndex : function(property, value, start, anyMatch, caseSensitive){
8203         if(Ext.isEmpty(value, false)){
8204             return -1;
8205         }
8206         value = this.createValueMatcher(value, anyMatch, caseSensitive);
8207         return this.findIndexBy(function(o){
8208             return o && value.test(o[property]);
8209         }, null, start);
8210     },
8211
8212     
8213     findIndexBy : function(fn, scope, start){
8214         var k = this.keys, it = this.items;
8215         for(var i = (start||0), len = it.length; i < len; i++){
8216             if(fn.call(scope||this, it[i], k[i])){
8217                 return i;
8218             }
8219         }
8220         return -1;
8221     },
8222
8223     
8224     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
8225         if (!value.exec) { 
8226             var er = Ext.escapeRe;
8227             value = String(value);
8228
8229             if (anyMatch === true) {
8230                 value = er(value);
8231             } else {
8232                 value = '^' + er(value);
8233                 if (exactMatch === true) {
8234                     value += '$';
8235                 }
8236             }
8237             value = new RegExp(value, caseSensitive ? '' : 'i');
8238          }
8239          return value;
8240     },
8241
8242     
8243     clone : function(){
8244         var r = new Ext.util.MixedCollection();
8245         var k = this.keys, it = this.items;
8246         for(var i = 0, len = it.length; i < len; i++){
8247             r.add(k[i], it[i]);
8248         }
8249         r.getKey = this.getKey;
8250         return r;
8251     }
8252 });
8253
8254 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
8255
8256 Ext.util.JSON = new (function(){
8257     var useHasOwn = !!{}.hasOwnProperty,
8258         isNative = function() {
8259             var useNative = null;
8260
8261             return function() {
8262                 if (useNative === null) {
8263                     useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
8264                 }
8265         
8266                 return useNative;
8267             };
8268         }(),
8269         pad = function(n) {
8270             return n < 10 ? "0" + n : n;
8271         },
8272         doDecode = function(json){
8273             return eval("(" + json + ')');    
8274         },
8275         doEncode = function(o){
8276             if(!Ext.isDefined(o) || o === null){
8277                 return "null";
8278             }else if(Ext.isArray(o)){
8279                 return encodeArray(o);
8280             }else if(Ext.isDate(o)){
8281                 return Ext.util.JSON.encodeDate(o);
8282             }else if(Ext.isString(o)){
8283                 return encodeString(o);
8284             }else if(typeof o == "number"){
8285                 
8286                 return isFinite(o) ? String(o) : "null";
8287             }else if(Ext.isBoolean(o)){
8288                 return String(o);
8289             }else {
8290                 var a = ["{"], b, i, v;
8291                 for (i in o) {
8292                     
8293                     if(!o.getElementsByTagName){
8294                         if(!useHasOwn || o.hasOwnProperty(i)) {
8295                             v = o[i];
8296                             switch (typeof v) {
8297                             case "undefined":
8298                             case "function":
8299                             case "unknown":
8300                                 break;
8301                             default:
8302                                 if(b){
8303                                     a.push(',');
8304                                 }
8305                                 a.push(doEncode(i), ":",
8306                                         v === null ? "null" : doEncode(v));
8307                                 b = true;
8308                             }
8309                         }
8310                     }
8311                 }
8312                 a.push("}");
8313                 return a.join("");
8314             }    
8315         },
8316         m = {
8317             "\b": '\\b',
8318             "\t": '\\t',
8319             "\n": '\\n',
8320             "\f": '\\f',
8321             "\r": '\\r',
8322             '"' : '\\"',
8323             "\\": '\\\\'
8324         },
8325         encodeString = function(s){
8326             if (/["\\\x00-\x1f]/.test(s)) {
8327                 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
8328                     var c = m[b];
8329                     if(c){
8330                         return c;
8331                     }
8332                     c = b.charCodeAt();
8333                     return "\\u00" +
8334                         Math.floor(c / 16).toString(16) +
8335                         (c % 16).toString(16);
8336                 }) + '"';
8337             }
8338             return '"' + s + '"';
8339         },
8340         encodeArray = function(o){
8341             var a = ["["], b, i, l = o.length, v;
8342                 for (i = 0; i < l; i += 1) {
8343                     v = o[i];
8344                     switch (typeof v) {
8345                         case "undefined":
8346                         case "function":
8347                         case "unknown":
8348                             break;
8349                         default:
8350                             if (b) {
8351                                 a.push(',');
8352                             }
8353                             a.push(v === null ? "null" : Ext.util.JSON.encode(v));
8354                             b = true;
8355                     }
8356                 }
8357                 a.push("]");
8358                 return a.join("");
8359         };
8360
8361     
8362     this.encodeDate = function(o){
8363         return '"' + o.getFullYear() + "-" +
8364                 pad(o.getMonth() + 1) + "-" +
8365                 pad(o.getDate()) + "T" +
8366                 pad(o.getHours()) + ":" +
8367                 pad(o.getMinutes()) + ":" +
8368                 pad(o.getSeconds()) + '"';
8369     };
8370
8371     
8372     this.encode = function() {
8373         var ec;
8374         return function(o) {
8375             if (!ec) {
8376                 
8377                 ec = isNative() ? JSON.stringify : doEncode;
8378             }
8379             return ec(o);
8380         };
8381     }();
8382
8383
8384     
8385     this.decode = function() {
8386         var dc;
8387         return function(json) {
8388             if (!dc) {
8389                 
8390                 dc = isNative() ? JSON.parse : doDecode;
8391             }
8392             return dc(json);
8393         };
8394     }();
8395
8396 })();
8397
8398 Ext.encode = Ext.util.JSON.encode;
8399
8400 Ext.decode = Ext.util.JSON.decode;
8401
8402 Ext.util.Format = function(){
8403     var trimRe = /^\s+|\s+$/g,
8404         stripTagsRE = /<\/?[^>]+>/gi,
8405         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
8406         nl2brRe = /\r?\n/g;
8407
8408     return {
8409         
8410         ellipsis : function(value, len, word){
8411             if(value && value.length > len){
8412                 if(word){
8413                     var vs = value.substr(0, len - 2),
8414                         index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
8415                     if(index == -1 || index < (len - 15)){
8416                         return value.substr(0, len - 3) + "...";
8417                     }else{
8418                         return vs.substr(0, index) + "...";
8419                     }
8420                 } else{
8421                     return value.substr(0, len - 3) + "...";
8422                 }
8423             }
8424             return value;
8425         },
8426
8427         
8428         undef : function(value){
8429             return value !== undefined ? value : "";
8430         },
8431
8432         
8433         defaultValue : function(value, defaultValue){
8434             return value !== undefined && value !== '' ? value : defaultValue;
8435         },
8436
8437         
8438         htmlEncode : function(value){
8439             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
8440         },
8441
8442         
8443         htmlDecode : function(value){
8444             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
8445         },
8446
8447         
8448         trim : function(value){
8449             return String(value).replace(trimRe, "");
8450         },
8451
8452         
8453         substr : function(value, start, length){
8454             return String(value).substr(start, length);
8455         },
8456
8457         
8458         lowercase : function(value){
8459             return String(value).toLowerCase();
8460         },
8461
8462         
8463         uppercase : function(value){
8464             return String(value).toUpperCase();
8465         },
8466
8467         
8468         capitalize : function(value){
8469             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
8470         },
8471
8472         
8473         call : function(value, fn){
8474             if(arguments.length > 2){
8475                 var args = Array.prototype.slice.call(arguments, 2);
8476                 args.unshift(value);
8477                 return eval(fn).apply(window, args);
8478             }else{
8479                 return eval(fn).call(window, value);
8480             }
8481         },
8482
8483         
8484         usMoney : function(v){
8485             v = (Math.round((v-0)*100))/100;
8486             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
8487             v = String(v);
8488             var ps = v.split('.'),
8489                 whole = ps[0],
8490                 sub = ps[1] ? '.'+ ps[1] : '.00',
8491                 r = /(\d+)(\d{3})/;
8492             while (r.test(whole)) {
8493                 whole = whole.replace(r, '$1' + ',' + '$2');
8494             }
8495             v = whole + sub;
8496             if(v.charAt(0) == '-'){
8497                 return '-$' + v.substr(1);
8498             }
8499             return "$" +  v;
8500         },
8501
8502         
8503         date : function(v, format){
8504             if(!v){
8505                 return "";
8506             }
8507             if(!Ext.isDate(v)){
8508                 v = new Date(Date.parse(v));
8509             }
8510             return v.dateFormat(format || "m/d/Y");
8511         },
8512
8513         
8514         dateRenderer : function(format){
8515             return function(v){
8516                 return Ext.util.Format.date(v, format);
8517             };
8518         },
8519
8520         
8521         stripTags : function(v){
8522             return !v ? v : String(v).replace(stripTagsRE, "");
8523         },
8524
8525         
8526         stripScripts : function(v){
8527             return !v ? v : String(v).replace(stripScriptsRe, "");
8528         },
8529
8530         
8531         fileSize : function(size){
8532             if(size < 1024) {
8533                 return size + " bytes";
8534             } else if(size < 1048576) {
8535                 return (Math.round(((size*10) / 1024))/10) + " KB";
8536             } else {
8537                 return (Math.round(((size*10) / 1048576))/10) + " MB";
8538             }
8539         },
8540
8541         
8542         math : function(){
8543             var fns = {};
8544             return function(v, a){
8545                 if(!fns[a]){
8546                     fns[a] = new Function('v', 'return v ' + a + ';');
8547                 }
8548                 return fns[a](v);
8549             }
8550         }(),
8551
8552         
8553         round : function(value, precision) {
8554             var result = Number(value);
8555             if (typeof precision == 'number') {
8556                 precision = Math.pow(10, precision);
8557                 result = Math.round(value * precision) / precision;
8558             }
8559             return result;
8560         },
8561
8562         
8563         number: function(v, format) {
8564             if(!format){
8565                 return v;
8566             }
8567             v = Ext.num(v, NaN);
8568             if (isNaN(v)){
8569                 return '';
8570             }
8571             var comma = ',',
8572                 dec = '.',
8573                 i18n = false,
8574                 neg = v < 0;
8575
8576             v = Math.abs(v);
8577             if(format.substr(format.length - 2) == '/i'){
8578                 format = format.substr(0, format.length - 2);
8579                 i18n = true;
8580                 comma = '.';
8581                 dec = ',';
8582             }
8583
8584             var hasComma = format.indexOf(comma) != -1,
8585                 psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
8586
8587             if(1 < psplit.length){
8588                 v = v.toFixed(psplit[1].length);
8589             }else if(2 < psplit.length){
8590                 throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
8591             }else{
8592                 v = v.toFixed(0);
8593             }
8594
8595             var fnum = v.toString();
8596
8597             psplit = fnum.split('.');
8598
8599             if (hasComma) {
8600                 var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3;
8601
8602                 for (var i = 0; i < j; i += n) {
8603                     if (i != 0) {
8604                         n = 3;
8605                     }
8606                     parr[parr.length] = cnum.substr(i, n);
8607                     m -= 1;
8608                 }
8609                 fnum = parr.join(comma);
8610                 if (psplit[1]) {
8611                     fnum += dec + psplit[1];
8612                 }
8613             } else {
8614                 if (psplit[1]) {
8615                     fnum = psplit[0] + dec + psplit[1];
8616                 }
8617             }
8618
8619             return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
8620         },
8621
8622         
8623         numberRenderer : function(format){
8624             return function(v){
8625                 return Ext.util.Format.number(v, format);
8626             };
8627         },
8628
8629         
8630         plural : function(v, s, p){
8631             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
8632         },
8633
8634         
8635         nl2br : function(v){
8636             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
8637         }
8638     }
8639 }();
8640
8641 Ext.XTemplate = function(){
8642     Ext.XTemplate.superclass.constructor.apply(this, arguments);
8643
8644     var me = this,
8645         s = me.html,
8646         re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
8647         nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
8648         ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
8649         execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
8650         m,
8651         id = 0,
8652         tpls = [],
8653         VALUES = 'values',
8654         PARENT = 'parent',
8655         XINDEX = 'xindex',
8656         XCOUNT = 'xcount',
8657         RETURN = 'return ',
8658         WITHVALUES = 'with(values){ ';
8659
8660     s = ['<tpl>', s, '</tpl>'].join('');
8661
8662     while((m = s.match(re))){
8663         var m2 = m[0].match(nameRe),
8664             m3 = m[0].match(ifRe),
8665             m4 = m[0].match(execRe),
8666             exp = null,
8667             fn = null,
8668             exec = null,
8669             name = m2 && m2[1] ? m2[1] : '';
8670
8671        if (m3) {
8672            exp = m3 && m3[1] ? m3[1] : null;
8673            if(exp){
8674                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
8675            }
8676        }
8677        if (m4) {
8678            exp = m4 && m4[1] ? m4[1] : null;
8679            if(exp){
8680                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
8681            }
8682        }
8683        if(name){
8684            switch(name){
8685                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
8686                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
8687                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
8688            }
8689        }
8690        tpls.push({
8691             id: id,
8692             target: name,
8693             exec: exec,
8694             test: fn,
8695             body: m[1]||''
8696         });
8697        s = s.replace(m[0], '{xtpl'+ id + '}');
8698        ++id;
8699     }
8700     for(var i = tpls.length-1; i >= 0; --i){
8701         me.compileTpl(tpls[i]);
8702     }
8703     me.master = tpls[tpls.length-1];
8704     me.tpls = tpls;
8705 };
8706 Ext.extend(Ext.XTemplate, Ext.Template, {
8707     
8708     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
8709     
8710     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
8711
8712     
8713     applySubTemplate : function(id, values, parent, xindex, xcount){
8714         var me = this,
8715             len,
8716             t = me.tpls[id],
8717             vs,
8718             buf = [];
8719         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
8720             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
8721             return '';
8722         }
8723         vs = t.target ? t.target.call(me, values, parent) : values;
8724         len = vs.length;
8725         parent = t.target ? values : parent;
8726         if(t.target && Ext.isArray(vs)){
8727             for(var i = 0, len = vs.length; i < len; i++){
8728                 buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
8729             }
8730             return buf.join('');
8731         }
8732         return t.compiled.call(me, vs, parent, xindex, xcount);
8733     },
8734
8735     
8736     compileTpl : function(tpl){
8737         var fm = Ext.util.Format,
8738             useF = this.disableFormats !== true,
8739             sep = Ext.isGecko ? "+" : ",",
8740             body;
8741
8742         function fn(m, name, format, args, math){
8743             if(name.substr(0, 4) == 'xtpl'){
8744                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
8745             }
8746             var v;
8747             if(name === '.'){
8748                 v = 'values';
8749             }else if(name === '#'){
8750                 v = 'xindex';
8751             }else if(name.indexOf('.') != -1){
8752                 v = name;
8753             }else{
8754                 v = "values['" + name + "']";
8755             }
8756             if(math){
8757                 v = '(' + v + math + ')';
8758             }
8759             if (format && useF) {
8760                 args = args ? ',' + args : "";
8761                 if(format.substr(0, 5) != "this."){
8762                     format = "fm." + format + '(';
8763                 }else{
8764                     format = 'this.call("'+ format.substr(5) + '", ';
8765                     args = ", values";
8766                 }
8767             } else {
8768                 args= ''; format = "("+v+" === undefined ? '' : ";
8769             }
8770             return "'"+ sep + format + v + args + ")"+sep+"'";
8771         }
8772
8773         function codeFn(m, code){
8774             
8775             return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
8776         }
8777
8778         
8779         if(Ext.isGecko){
8780             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
8781                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
8782                     "';};";
8783         }else{
8784             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
8785             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
8786             body.push("'].join('');};");
8787             body = body.join('');
8788         }
8789         eval(body);
8790         return this;
8791     },
8792
8793     
8794     applyTemplate : function(values){
8795         return this.master.compiled.call(this, values, {}, 1, 1);
8796     },
8797
8798     
8799     compile : function(){return this;}
8800
8801     
8802     
8803     
8804
8805 });
8806
8807 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
8808
8809
8810 Ext.XTemplate.from = function(el){
8811     el = Ext.getDom(el);
8812     return new Ext.XTemplate(el.value || el.innerHTML);
8813 };
8814
8815 Ext.util.CSS = function(){
8816         var rules = null;
8817         var doc = document;
8818
8819     var camelRe = /(-[a-z])/gi;
8820     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
8821
8822    return {
8823    
8824    createStyleSheet : function(cssText, id){
8825        var ss;
8826        var head = doc.getElementsByTagName("head")[0];
8827        var rules = doc.createElement("style");
8828        rules.setAttribute("type", "text/css");
8829        if(id){
8830            rules.setAttribute("id", id);
8831        }
8832        if(Ext.isIE){
8833            head.appendChild(rules);
8834            ss = rules.styleSheet;
8835            ss.cssText = cssText;
8836        }else{
8837            try{
8838                 rules.appendChild(doc.createTextNode(cssText));
8839            }catch(e){
8840                rules.cssText = cssText;
8841            }
8842            head.appendChild(rules);
8843            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
8844        }
8845        this.cacheStyleSheet(ss);
8846        return ss;
8847    },
8848
8849    
8850    removeStyleSheet : function(id){
8851        var existing = doc.getElementById(id);
8852        if(existing){
8853            existing.parentNode.removeChild(existing);
8854        }
8855    },
8856
8857    
8858    swapStyleSheet : function(id, url){
8859        this.removeStyleSheet(id);
8860        var ss = doc.createElement("link");
8861        ss.setAttribute("rel", "stylesheet");
8862        ss.setAttribute("type", "text/css");
8863        ss.setAttribute("id", id);
8864        ss.setAttribute("href", url);
8865        doc.getElementsByTagName("head")[0].appendChild(ss);
8866    },
8867    
8868    
8869    refreshCache : function(){
8870        return this.getRules(true);
8871    },
8872
8873    
8874    cacheStyleSheet : function(ss){
8875        if(!rules){
8876            rules = {};
8877        }
8878        try{
8879            var ssRules = ss.cssRules || ss.rules;
8880            for(var j = ssRules.length-1; j >= 0; --j){
8881                rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
8882            }
8883        }catch(e){}
8884    },
8885    
8886    
8887    getRules : function(refreshCache){
8888                 if(rules === null || refreshCache){
8889                         rules = {};
8890                         var ds = doc.styleSheets;
8891                         for(var i =0, len = ds.length; i < len; i++){
8892                             try{
8893                         this.cacheStyleSheet(ds[i]);
8894                     }catch(e){} 
8895                 }
8896                 }
8897                 return rules;
8898         },
8899         
8900         
8901    getRule : function(selector, refreshCache){
8902                 var rs = this.getRules(refreshCache);
8903                 if(!Ext.isArray(selector)){
8904                     return rs[selector.toLowerCase()];
8905                 }
8906                 for(var i = 0; i < selector.length; i++){
8907                         if(rs[selector[i]]){
8908                                 return rs[selector[i].toLowerCase()];
8909                         }
8910                 }
8911                 return null;
8912         },
8913         
8914         
8915         
8916    updateRule : function(selector, property, value){
8917                 if(!Ext.isArray(selector)){
8918                         var rule = this.getRule(selector);
8919                         if(rule){
8920                                 rule.style[property.replace(camelRe, camelFn)] = value;
8921                                 return true;
8922                         }
8923                 }else{
8924                         for(var i = 0; i < selector.length; i++){
8925                                 if(this.updateRule(selector[i], property, value)){
8926                                         return true;
8927                                 }
8928                         }
8929                 }
8930                 return false;
8931         }
8932    };   
8933 }();
8934 Ext.util.ClickRepeater = function(el, config)
8935 {
8936     this.el = Ext.get(el);
8937     this.el.unselectable();
8938
8939     Ext.apply(this, config);
8940
8941     this.addEvents(
8942     
8943         "mousedown",
8944     
8945         "click",
8946     
8947         "mouseup"
8948     );
8949
8950     if(!this.disabled){
8951         this.disabled = true;
8952         this.enable();
8953     }
8954
8955     
8956     if(this.handler){
8957         this.on("click", this.handler,  this.scope || this);
8958     }
8959
8960     Ext.util.ClickRepeater.superclass.constructor.call(this);
8961 };
8962
8963 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
8964     interval : 20,
8965     delay: 250,
8966     preventDefault : true,
8967     stopDefault : false,
8968     timer : 0,
8969
8970     
8971     enable: function(){
8972         if(this.disabled){
8973             this.el.on('mousedown', this.handleMouseDown, this);
8974             if (Ext.isIE){
8975                 this.el.on('dblclick', this.handleDblClick, this);
8976             }
8977             if(this.preventDefault || this.stopDefault){
8978                 this.el.on('click', this.eventOptions, this);
8979             }
8980         }
8981         this.disabled = false;
8982     },
8983
8984     
8985     disable: function( force){
8986         if(force || !this.disabled){
8987             clearTimeout(this.timer);
8988             if(this.pressClass){
8989                 this.el.removeClass(this.pressClass);
8990             }
8991             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
8992             this.el.removeAllListeners();
8993         }
8994         this.disabled = true;
8995     },
8996
8997     
8998     setDisabled: function(disabled){
8999         this[disabled ? 'disable' : 'enable']();
9000     },
9001
9002     eventOptions: function(e){
9003         if(this.preventDefault){
9004             e.preventDefault();
9005         }
9006         if(this.stopDefault){
9007             e.stopEvent();
9008         }
9009     },
9010
9011     
9012     destroy : function() {
9013         this.disable(true);
9014         Ext.destroy(this.el);
9015         this.purgeListeners();
9016     },
9017
9018     handleDblClick : function(){
9019         clearTimeout(this.timer);
9020         this.el.blur();
9021
9022         this.fireEvent("mousedown", this);
9023         this.fireEvent("click", this);
9024     },
9025
9026     
9027     handleMouseDown : function(){
9028         clearTimeout(this.timer);
9029         this.el.blur();
9030         if(this.pressClass){
9031             this.el.addClass(this.pressClass);
9032         }
9033         this.mousedownTime = new Date();
9034
9035         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
9036         this.el.on("mouseout", this.handleMouseOut, this);
9037
9038         this.fireEvent("mousedown", this);
9039         this.fireEvent("click", this);
9040
9041         
9042         if (this.accelerate) {
9043             this.delay = 400;
9044         }
9045         this.timer = this.click.defer(this.delay || this.interval, this);
9046     },
9047
9048     
9049     click : function(){
9050         this.fireEvent("click", this);
9051         this.timer = this.click.defer(this.accelerate ?
9052             this.easeOutExpo(this.mousedownTime.getElapsed(),
9053                 400,
9054                 -390,
9055                 12000) :
9056             this.interval, this);
9057     },
9058
9059     easeOutExpo : function (t, b, c, d) {
9060         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
9061     },
9062
9063     
9064     handleMouseOut : function(){
9065         clearTimeout(this.timer);
9066         if(this.pressClass){
9067             this.el.removeClass(this.pressClass);
9068         }
9069         this.el.on("mouseover", this.handleMouseReturn, this);
9070     },
9071
9072     
9073     handleMouseReturn : function(){
9074         this.el.un("mouseover", this.handleMouseReturn, this);
9075         if(this.pressClass){
9076             this.el.addClass(this.pressClass);
9077         }
9078         this.click();
9079     },
9080
9081     
9082     handleMouseUp : function(){
9083         clearTimeout(this.timer);
9084         this.el.un("mouseover", this.handleMouseReturn, this);
9085         this.el.un("mouseout", this.handleMouseOut, this);
9086         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
9087         this.el.removeClass(this.pressClass);
9088         this.fireEvent("mouseup", this);
9089     }
9090 });
9091 Ext.KeyNav = function(el, config){
9092     this.el = Ext.get(el);
9093     Ext.apply(this, config);
9094     if(!this.disabled){
9095         this.disabled = true;
9096         this.enable();
9097     }
9098 };
9099
9100 Ext.KeyNav.prototype = {
9101     
9102     disabled : false,
9103     
9104     defaultEventAction: "stopEvent",
9105     
9106     forceKeyDown : false,
9107
9108     
9109     relay : function(e){
9110         var k = e.getKey();
9111         var h = this.keyToHandler[k];
9112         if(h && this[h]){
9113             if(this.doRelay(e, this[h], h) !== true){
9114                 e[this.defaultEventAction]();
9115             }
9116         }
9117     },
9118
9119     
9120     doRelay : function(e, h, hname){
9121         return h.call(this.scope || this, e);
9122     },
9123
9124     
9125     enter : false,
9126     left : false,
9127     right : false,
9128     up : false,
9129     down : false,
9130     tab : false,
9131     esc : false,
9132     pageUp : false,
9133     pageDown : false,
9134     del : false,
9135     home : false,
9136     end : false,
9137
9138     
9139     keyToHandler : {
9140         37 : "left",
9141         39 : "right",
9142         38 : "up",
9143         40 : "down",
9144         33 : "pageUp",
9145         34 : "pageDown",
9146         46 : "del",
9147         36 : "home",
9148         35 : "end",
9149         13 : "enter",
9150         27 : "esc",
9151         9  : "tab"
9152     },
9153     
9154     stopKeyUp: function(e) {
9155         var k = e.getKey();
9156
9157         if (k >= 37 && k <= 40) {
9158             
9159             
9160             e.stopEvent();
9161         }
9162     },
9163     
9164     
9165     destroy: function(){
9166         this.disable();    
9167     },
9168
9169         
9170         enable: function() {
9171         if (this.disabled) {
9172             if (Ext.isSafari2) {
9173                 
9174                 this.el.on('keyup', this.stopKeyUp, this);
9175             }
9176
9177             this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
9178             this.disabled = false;
9179         }
9180     },
9181
9182         
9183         disable: function() {
9184         if (!this.disabled) {
9185             if (Ext.isSafari2) {
9186                 
9187                 this.el.un('keyup', this.stopKeyUp, this);
9188             }
9189
9190             this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
9191             this.disabled = true;
9192         }
9193     },
9194     
9195     
9196     setDisabled : function(disabled){
9197         this[disabled ? "disable" : "enable"]();
9198     },
9199     
9200     
9201     isKeydown: function(){
9202         return this.forceKeyDown || Ext.EventManager.useKeydown;
9203     }
9204 };
9205
9206 Ext.KeyMap = function(el, config, eventName){
9207     this.el  = Ext.get(el);
9208     this.eventName = eventName || "keydown";
9209     this.bindings = [];
9210     if(config){
9211         this.addBinding(config);
9212     }
9213     this.enable();
9214 };
9215
9216 Ext.KeyMap.prototype = {
9217     
9218     stopEvent : false,
9219
9220     
9221         addBinding : function(config){
9222         if(Ext.isArray(config)){
9223             Ext.each(config, function(c){
9224                 this.addBinding(c);
9225             }, this);
9226             return;
9227         }
9228         var keyCode = config.key,
9229             fn = config.fn || config.handler,
9230             scope = config.scope;
9231
9232         if (config.stopEvent) {
9233             this.stopEvent = config.stopEvent;    
9234         }       
9235
9236         if(typeof keyCode == "string"){
9237             var ks = [];
9238             var keyString = keyCode.toUpperCase();
9239             for(var j = 0, len = keyString.length; j < len; j++){
9240                 ks.push(keyString.charCodeAt(j));
9241             }
9242             keyCode = ks;
9243         }
9244         var keyArray = Ext.isArray(keyCode);
9245         
9246         var handler = function(e){
9247             if(this.checkModifiers(config, e)){
9248                 var k = e.getKey();
9249                 if(keyArray){
9250                     for(var i = 0, len = keyCode.length; i < len; i++){
9251                         if(keyCode[i] == k){
9252                           if(this.stopEvent){
9253                               e.stopEvent();
9254                           }
9255                           fn.call(scope || window, k, e);
9256                           return;
9257                         }
9258                     }
9259                 }else{
9260                     if(k == keyCode){
9261                         if(this.stopEvent){
9262                            e.stopEvent();
9263                         }
9264                         fn.call(scope || window, k, e);
9265                     }
9266                 }
9267             }
9268         };
9269         this.bindings.push(handler);
9270         },
9271     
9272     
9273     checkModifiers: function(config, e){
9274         var val, key, keys = ['shift', 'ctrl', 'alt'];
9275         for (var i = 0, len = keys.length; i < len; ++i){
9276             key = keys[i];
9277             val = config[key];
9278             if(!(val === undefined || (val === e[key + 'Key']))){
9279                 return false;
9280             }
9281         }
9282         return true;
9283     },
9284
9285     
9286     on : function(key, fn, scope){
9287         var keyCode, shift, ctrl, alt;
9288         if(typeof key == "object" && !Ext.isArray(key)){
9289             keyCode = key.key;
9290             shift = key.shift;
9291             ctrl = key.ctrl;
9292             alt = key.alt;
9293         }else{
9294             keyCode = key;
9295         }
9296         this.addBinding({
9297             key: keyCode,
9298             shift: shift,
9299             ctrl: ctrl,
9300             alt: alt,
9301             fn: fn,
9302             scope: scope
9303         });
9304     },
9305
9306     
9307     handleKeyDown : function(e){
9308             if(this.enabled){ 
9309             var b = this.bindings;
9310             for(var i = 0, len = b.length; i < len; i++){
9311                 b[i].call(this, e);
9312             }
9313             }
9314         },
9315
9316         
9317         isEnabled : function(){
9318             return this.enabled;
9319         },
9320
9321         
9322         enable: function(){
9323                 if(!this.enabled){
9324                     this.el.on(this.eventName, this.handleKeyDown, this);
9325                     this.enabled = true;
9326                 }
9327         },
9328
9329         
9330         disable: function(){
9331                 if(this.enabled){
9332                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
9333                     this.enabled = false;
9334                 }
9335         },
9336     
9337     
9338     setDisabled : function(disabled){
9339         this[disabled ? "disable" : "enable"]();
9340     }
9341 };
9342 Ext.util.TextMetrics = function(){
9343     var shared;
9344     return {
9345         
9346         measure : function(el, text, fixedWidth){
9347             if(!shared){
9348                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
9349             }
9350             shared.bind(el);
9351             shared.setFixedWidth(fixedWidth || 'auto');
9352             return shared.getSize(text);
9353         },
9354
9355         
9356         createInstance : function(el, fixedWidth){
9357             return Ext.util.TextMetrics.Instance(el, fixedWidth);
9358         }
9359     };
9360 }();
9361
9362 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
9363     var ml = new Ext.Element(document.createElement('div'));
9364     document.body.appendChild(ml.dom);
9365     ml.position('absolute');
9366     ml.setLeftTop(-1000, -1000);
9367     ml.hide();
9368
9369     if(fixedWidth){
9370         ml.setWidth(fixedWidth);
9371     }
9372
9373     var instance = {
9374         
9375         getSize : function(text){
9376             ml.update(text);
9377             var s = ml.getSize();
9378             ml.update('');
9379             return s;
9380         },
9381
9382         
9383         bind : function(el){
9384             ml.setStyle(
9385                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
9386             );
9387         },
9388
9389         
9390         setFixedWidth : function(width){
9391             ml.setWidth(width);
9392         },
9393
9394         
9395         getWidth : function(text){
9396             ml.dom.style.width = 'auto';
9397             return this.getSize(text).width;
9398         },
9399
9400         
9401         getHeight : function(text){
9402             return this.getSize(text).height;
9403         }
9404     };
9405
9406     instance.bind(bindTo);
9407
9408     return instance;
9409 };
9410
9411 Ext.Element.addMethods({
9412     
9413     getTextWidth : function(text, min, max){
9414         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
9415     }
9416 });
9417
9418 Ext.util.Cookies = {
9419     
9420     set : function(name, value){
9421         var argv = arguments;
9422         var argc = arguments.length;
9423         var expires = (argc > 2) ? argv[2] : null;
9424         var path = (argc > 3) ? argv[3] : '/';
9425         var domain = (argc > 4) ? argv[4] : null;
9426         var secure = (argc > 5) ? argv[5] : false;
9427         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
9428     },
9429
9430     
9431     get : function(name){
9432         var arg = name + "=";
9433         var alen = arg.length;
9434         var clen = document.cookie.length;
9435         var i = 0;
9436         var j = 0;
9437         while(i < clen){
9438             j = i + alen;
9439             if(document.cookie.substring(i, j) == arg){
9440                 return Ext.util.Cookies.getCookieVal(j);
9441             }
9442             i = document.cookie.indexOf(" ", i) + 1;
9443             if(i === 0){
9444                 break;
9445             }
9446         }
9447         return null;
9448     },
9449
9450     
9451     clear : function(name){
9452         if(Ext.util.Cookies.get(name)){
9453             document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
9454         }
9455     },
9456     
9457     getCookieVal : function(offset){
9458         var endstr = document.cookie.indexOf(";", offset);
9459         if(endstr == -1){
9460             endstr = document.cookie.length;
9461         }
9462         return unescape(document.cookie.substring(offset, endstr));
9463     }
9464 };
9465 Ext.handleError = function(e) {
9466     throw e;
9467 };
9468
9469
9470 Ext.Error = function(message) {
9471     
9472     this.message = (this.lang[message]) ? this.lang[message] : message;
9473 };
9474
9475 Ext.Error.prototype = new Error();
9476 Ext.apply(Ext.Error.prototype, {
9477     
9478     lang: {},
9479
9480     name: 'Ext.Error',
9481     
9482     getName : function() {
9483         return this.name;
9484     },
9485     
9486     getMessage : function() {
9487         return this.message;
9488     },
9489     
9490     toJson : function() {
9491         return Ext.encode(this);
9492     }
9493 });
9494
9495 Ext.ComponentMgr = function(){
9496     var all = new Ext.util.MixedCollection();
9497     var types = {};
9498     var ptypes = {};
9499
9500     return {
9501         
9502         register : function(c){
9503             all.add(c);
9504         },
9505
9506         
9507         unregister : function(c){
9508             all.remove(c);
9509         },
9510
9511         
9512         get : function(id){
9513             return all.get(id);
9514         },
9515
9516         
9517         onAvailable : function(id, fn, scope){
9518             all.on("add", function(index, o){
9519                 if(o.id == id){
9520                     fn.call(scope || o, o);
9521                     all.un("add", fn, scope);
9522                 }
9523             });
9524         },
9525
9526         
9527         all : all,
9528         
9529         
9530         types : types,
9531         
9532         
9533         ptypes: ptypes,
9534         
9535         
9536         isRegistered : function(xtype){
9537             return types[xtype] !== undefined;    
9538         },
9539         
9540         
9541         isPluginRegistered : function(ptype){
9542             return ptypes[ptype] !== undefined;    
9543         },        
9544
9545         
9546         registerType : function(xtype, cls){
9547             types[xtype] = cls;
9548             cls.xtype = xtype;
9549         },
9550
9551         
9552         create : function(config, defaultType){
9553             return config.render ? config : new types[config.xtype || defaultType](config);
9554         },
9555
9556         
9557         registerPlugin : function(ptype, cls){
9558             ptypes[ptype] = cls;
9559             cls.ptype = ptype;
9560         },
9561
9562         
9563         createPlugin : function(config, defaultType){
9564             var PluginCls = ptypes[config.ptype || defaultType];
9565             if (PluginCls.init) {
9566                 return PluginCls;                
9567             } else {
9568                 return new PluginCls(config);
9569             }            
9570         }
9571     };
9572 }();
9573
9574
9575 Ext.reg = Ext.ComponentMgr.registerType; 
9576
9577 Ext.preg = Ext.ComponentMgr.registerPlugin;
9578
9579 Ext.create = Ext.ComponentMgr.create;
9580 Ext.Component = function(config){
9581     config = config || {};
9582     if(config.initialConfig){
9583         if(config.isAction){           
9584             this.baseAction = config;
9585         }
9586         config = config.initialConfig; 
9587     }else if(config.tagName || config.dom || Ext.isString(config)){ 
9588         config = {applyTo: config, id: config.id || config};
9589     }
9590
9591     
9592     this.initialConfig = config;
9593
9594     Ext.apply(this, config);
9595     this.addEvents(
9596         
9597         'added',
9598         
9599         'disable',
9600         
9601         'enable',
9602         
9603         'beforeshow',
9604         
9605         'show',
9606         
9607         'beforehide',
9608         
9609         'hide',
9610         
9611         'removed',
9612         
9613         'beforerender',
9614         
9615         'render',
9616         
9617         'afterrender',
9618         
9619         'beforedestroy',
9620         
9621         'destroy',
9622         
9623         'beforestaterestore',
9624         
9625         'staterestore',
9626         
9627         'beforestatesave',
9628         
9629         'statesave'
9630     );
9631     this.getId();
9632     Ext.ComponentMgr.register(this);
9633     Ext.Component.superclass.constructor.call(this);
9634
9635     if(this.baseAction){
9636         this.baseAction.addComponent(this);
9637     }
9638
9639     this.initComponent();
9640
9641     if(this.plugins){
9642         if(Ext.isArray(this.plugins)){
9643             for(var i = 0, len = this.plugins.length; i < len; i++){
9644                 this.plugins[i] = this.initPlugin(this.plugins[i]);
9645             }
9646         }else{
9647             this.plugins = this.initPlugin(this.plugins);
9648         }
9649     }
9650
9651     if(this.stateful !== false){
9652         this.initState();
9653     }
9654
9655     if(this.applyTo){
9656         this.applyToMarkup(this.applyTo);
9657         delete this.applyTo;
9658     }else if(this.renderTo){
9659         this.render(this.renderTo);
9660         delete this.renderTo;
9661     }
9662 };
9663
9664
9665 Ext.Component.AUTO_ID = 1000;
9666
9667 Ext.extend(Ext.Component, Ext.util.Observable, {
9668     
9669     
9670     
9671     
9672     
9673     
9674     
9675
9676     
9677     
9678     
9679     
9680     
9681     
9682     
9683     
9684     
9685     disabled : false,
9686     
9687     hidden : false,
9688     
9689     
9690     
9691     
9692     
9693     
9694     
9695     autoEl : 'div',
9696
9697     
9698     disabledClass : 'x-item-disabled',
9699     
9700     allowDomMove : true,
9701     
9702     autoShow : false,
9703     
9704     hideMode : 'display',
9705     
9706     hideParent : false,
9707     
9708     
9709     
9710     
9711     
9712     rendered : false,
9713
9714     
9715     
9716
9717     
9718
9719     
9720     tplWriteMode : 'overwrite',
9721
9722     
9723     
9724     
9725     bubbleEvents: [],
9726
9727
9728     
9729     ctype : 'Ext.Component',
9730
9731     
9732     actionMode : 'el',
9733
9734     
9735     getActionEl : function(){
9736         return this[this.actionMode];
9737     },
9738
9739     initPlugin : function(p){
9740         if(p.ptype && !Ext.isFunction(p.init)){
9741             p = Ext.ComponentMgr.createPlugin(p);
9742         }else if(Ext.isString(p)){
9743             p = Ext.ComponentMgr.createPlugin({
9744                 ptype: p
9745             });
9746         }
9747         p.init(this);
9748         return p;
9749     },
9750
9751     
9752     initComponent : function(){
9753         
9754         if(this.listeners){
9755             this.on(this.listeners);
9756             delete this.listeners;
9757         }
9758         this.enableBubble(this.bubbleEvents);
9759     },
9760
9761     
9762     render : function(container, position){
9763         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
9764             if(!container && this.el){
9765                 this.el = Ext.get(this.el);
9766                 container = this.el.dom.parentNode;
9767                 this.allowDomMove = false;
9768             }
9769             this.container = Ext.get(container);
9770             if(this.ctCls){
9771                 this.container.addClass(this.ctCls);
9772             }
9773             this.rendered = true;
9774             if(position !== undefined){
9775                 if(Ext.isNumber(position)){
9776                     position = this.container.dom.childNodes[position];
9777                 }else{
9778                     position = Ext.getDom(position);
9779                 }
9780             }
9781             this.onRender(this.container, position || null);
9782             if(this.autoShow){
9783                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
9784             }
9785             if(this.cls){
9786                 this.el.addClass(this.cls);
9787                 delete this.cls;
9788             }
9789             if(this.style){
9790                 this.el.applyStyles(this.style);
9791                 delete this.style;
9792             }
9793             if(this.overCls){
9794                 this.el.addClassOnOver(this.overCls);
9795             }
9796             this.fireEvent('render', this);
9797
9798
9799             
9800             
9801             var contentTarget = this.getContentTarget();
9802             if (this.html){
9803                 contentTarget.update(Ext.DomHelper.markup(this.html));
9804                 delete this.html;
9805             }
9806             if (this.contentEl){
9807                 var ce = Ext.getDom(this.contentEl);
9808                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
9809                 contentTarget.appendChild(ce);
9810             }
9811             if (this.tpl) {
9812                 if (!this.tpl.compile) {
9813                     this.tpl = new Ext.XTemplate(this.tpl);
9814                 }
9815                 if (this.data) {
9816                     this.tpl[this.tplWriteMode](contentTarget, this.data);
9817                     delete this.data;
9818                 }
9819             }
9820             this.afterRender(this.container);
9821
9822
9823             if(this.hidden){
9824                 
9825                 this.doHide();
9826             }
9827             if(this.disabled){
9828                 
9829                 this.disable(true);
9830             }
9831
9832             if(this.stateful !== false){
9833                 this.initStateEvents();
9834             }
9835             this.fireEvent('afterrender', this);
9836         }
9837         return this;
9838     },
9839
9840
9841     
9842     update: function(htmlOrData, loadScripts, cb) {
9843         var contentTarget = this.getContentTarget();
9844         if (this.tpl && typeof htmlOrData !== "string") {
9845             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
9846         } else {
9847             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
9848             contentTarget.update(html, loadScripts, cb);
9849         }
9850     },
9851
9852
9853     
9854     onAdded : function(container, pos) {
9855         this.ownerCt = container;
9856         this.initRef();
9857         this.fireEvent('added', this, container, pos);
9858     },
9859
9860     
9861     onRemoved : function() {
9862         this.removeRef();
9863         this.fireEvent('removed', this, this.ownerCt);
9864         delete this.ownerCt;
9865     },
9866
9867     
9868     initRef : function() {
9869         
9870         if(this.ref && !this.refOwner){
9871             var levels = this.ref.split('/'),
9872                 last = levels.length,
9873                 i = 0,
9874                 t = this;
9875
9876             while(t && i < last){
9877                 t = t.ownerCt;
9878                 ++i;
9879             }
9880             if(t){
9881                 t[this.refName = levels[--i]] = this;
9882                 
9883                 this.refOwner = t;
9884             }
9885         }
9886     },
9887
9888     removeRef : function() {
9889         if (this.refOwner && this.refName) {
9890             delete this.refOwner[this.refName];
9891             delete this.refOwner;
9892         }
9893     },
9894
9895     
9896     initState : function(){
9897         if(Ext.state.Manager){
9898             var id = this.getStateId();
9899             if(id){
9900                 var state = Ext.state.Manager.get(id);
9901                 if(state){
9902                     if(this.fireEvent('beforestaterestore', this, state) !== false){
9903                         this.applyState(Ext.apply({}, state));
9904                         this.fireEvent('staterestore', this, state);
9905                     }
9906                 }
9907             }
9908         }
9909     },
9910
9911     
9912     getStateId : function(){
9913         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
9914     },
9915
9916     
9917     initStateEvents : function(){
9918         if(this.stateEvents){
9919             for(var i = 0, e; e = this.stateEvents[i]; i++){
9920                 this.on(e, this.saveState, this, {delay:100});
9921             }
9922         }
9923     },
9924
9925     
9926     applyState : function(state){
9927         if(state){
9928             Ext.apply(this, state);
9929         }
9930     },
9931
9932     
9933     getState : function(){
9934         return null;
9935     },
9936
9937     
9938     saveState : function(){
9939         if(Ext.state.Manager && this.stateful !== false){
9940             var id = this.getStateId();
9941             if(id){
9942                 var state = this.getState();
9943                 if(this.fireEvent('beforestatesave', this, state) !== false){
9944                     Ext.state.Manager.set(id, state);
9945                     this.fireEvent('statesave', this, state);
9946                 }
9947             }
9948         }
9949     },
9950
9951     
9952     applyToMarkup : function(el){
9953         this.allowDomMove = false;
9954         this.el = Ext.get(el);
9955         this.render(this.el.dom.parentNode);
9956     },
9957
9958     
9959     addClass : function(cls){
9960         if(this.el){
9961             this.el.addClass(cls);
9962         }else{
9963             this.cls = this.cls ? this.cls + ' ' + cls : cls;
9964         }
9965         return this;
9966     },
9967
9968     
9969     removeClass : function(cls){
9970         if(this.el){
9971             this.el.removeClass(cls);
9972         }else if(this.cls){
9973             this.cls = this.cls.split(' ').remove(cls).join(' ');
9974         }
9975         return this;
9976     },
9977
9978     
9979     
9980     onRender : function(ct, position){
9981         if(!this.el && this.autoEl){
9982             if(Ext.isString(this.autoEl)){
9983                 this.el = document.createElement(this.autoEl);
9984             }else{
9985                 var div = document.createElement('div');
9986                 Ext.DomHelper.overwrite(div, this.autoEl);
9987                 this.el = div.firstChild;
9988             }
9989             if (!this.el.id) {
9990                 this.el.id = this.getId();
9991             }
9992         }
9993         if(this.el){
9994             this.el = Ext.get(this.el);
9995             if(this.allowDomMove !== false){
9996                 ct.dom.insertBefore(this.el.dom, position);
9997                 if (div) {
9998                     Ext.removeNode(div);
9999                     div = null;
10000                 }
10001             }
10002         }
10003     },
10004
10005     
10006     getAutoCreate : function(){
10007         var cfg = Ext.isObject(this.autoCreate) ?
10008                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
10009         if(this.id && !cfg.id){
10010             cfg.id = this.id;
10011         }
10012         return cfg;
10013     },
10014
10015     
10016     afterRender : Ext.emptyFn,
10017
10018     
10019     destroy : function(){
10020         if(!this.isDestroyed){
10021             if(this.fireEvent('beforedestroy', this) !== false){
10022                 this.destroying = true;
10023                 this.beforeDestroy();
10024                 if(this.ownerCt && this.ownerCt.remove){
10025                     this.ownerCt.remove(this, false);
10026                 }
10027                 if(this.rendered){
10028                     this.el.remove();
10029                     if(this.actionMode == 'container' || this.removeMode == 'container'){
10030                         this.container.remove();
10031                     }
10032                 }
10033                 
10034                 if(this.focusTask && this.focusTask.cancel){
10035                     this.focusTask.cancel();
10036                 }
10037                 this.onDestroy();
10038                 Ext.ComponentMgr.unregister(this);
10039                 this.fireEvent('destroy', this);
10040                 this.purgeListeners();
10041                 this.destroying = false;
10042                 this.isDestroyed = true;
10043             }
10044         }
10045     },
10046
10047     deleteMembers : function(){
10048         var args = arguments;
10049         for(var i = 0, len = args.length; i < len; ++i){
10050             delete this[args[i]];
10051         }
10052     },
10053
10054     
10055     beforeDestroy : Ext.emptyFn,
10056
10057     
10058     onDestroy  : Ext.emptyFn,
10059
10060     
10061     getEl : function(){
10062         return this.el;
10063     },
10064
10065     
10066     getContentTarget : function(){
10067         return this.el;
10068     },
10069
10070     
10071     getId : function(){
10072         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
10073     },
10074
10075     
10076     getItemId : function(){
10077         return this.itemId || this.getId();
10078     },
10079
10080     
10081     focus : function(selectText, delay){
10082         if(delay){
10083             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
10084             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
10085             return;
10086         }
10087         if(this.rendered && !this.isDestroyed){
10088             this.el.focus();
10089             if(selectText === true){
10090                 this.el.dom.select();
10091             }
10092         }
10093         return this;
10094     },
10095
10096     
10097     blur : function(){
10098         if(this.rendered){
10099             this.el.blur();
10100         }
10101         return this;
10102     },
10103
10104     
10105     disable : function( silent){
10106         if(this.rendered){
10107             this.onDisable();
10108         }
10109         this.disabled = true;
10110         if(silent !== true){
10111             this.fireEvent('disable', this);
10112         }
10113         return this;
10114     },
10115
10116     
10117     onDisable : function(){
10118         this.getActionEl().addClass(this.disabledClass);
10119         this.el.dom.disabled = true;
10120     },
10121
10122     
10123     enable : function(){
10124         if(this.rendered){
10125             this.onEnable();
10126         }
10127         this.disabled = false;
10128         this.fireEvent('enable', this);
10129         return this;
10130     },
10131
10132     
10133     onEnable : function(){
10134         this.getActionEl().removeClass(this.disabledClass);
10135         this.el.dom.disabled = false;
10136     },
10137
10138     
10139     setDisabled : function(disabled){
10140         return this[disabled ? 'disable' : 'enable']();
10141     },
10142
10143     
10144     show : function(){
10145         if(this.fireEvent('beforeshow', this) !== false){
10146             this.hidden = false;
10147             if(this.autoRender){
10148                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
10149             }
10150             if(this.rendered){
10151                 this.onShow();
10152             }
10153             this.fireEvent('show', this);
10154         }
10155         return this;
10156     },
10157
10158     
10159     onShow : function(){
10160         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
10161     },
10162
10163     
10164     hide : function(){
10165         if(this.fireEvent('beforehide', this) !== false){
10166             this.doHide();
10167             this.fireEvent('hide', this);
10168         }
10169         return this;
10170     },
10171
10172     
10173     doHide: function(){
10174         this.hidden = true;
10175         if(this.rendered){
10176             this.onHide();
10177         }
10178     },
10179
10180     
10181     onHide : function(){
10182         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
10183     },
10184
10185     
10186     getVisibilityEl : function(){
10187         return this.hideParent ? this.container : this.getActionEl();
10188     },
10189
10190     
10191     setVisible : function(visible){
10192         return this[visible ? 'show' : 'hide']();
10193     },
10194
10195     
10196     isVisible : function(){
10197         return this.rendered && this.getVisibilityEl().isVisible();
10198     },
10199
10200     
10201     cloneConfig : function(overrides){
10202         overrides = overrides || {};
10203         var id = overrides.id || Ext.id();
10204         var cfg = Ext.applyIf(overrides, this.initialConfig);
10205         cfg.id = id; 
10206         return new this.constructor(cfg);
10207     },
10208
10209     
10210     getXType : function(){
10211         return this.constructor.xtype;
10212     },
10213
10214     
10215     isXType : function(xtype, shallow){
10216         
10217         if (Ext.isFunction(xtype)){
10218             xtype = xtype.xtype; 
10219         }else if (Ext.isObject(xtype)){
10220             xtype = xtype.constructor.xtype; 
10221         }
10222
10223         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
10224     },
10225
10226     
10227     getXTypes : function(){
10228         var tc = this.constructor;
10229         if(!tc.xtypes){
10230             var c = [], sc = this;
10231             while(sc && sc.constructor.xtype){
10232                 c.unshift(sc.constructor.xtype);
10233                 sc = sc.constructor.superclass;
10234             }
10235             tc.xtypeChain = c;
10236             tc.xtypes = c.join('/');
10237         }
10238         return tc.xtypes;
10239     },
10240
10241     
10242     findParentBy : function(fn) {
10243         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
10244         return p || null;
10245     },
10246
10247     
10248     findParentByType : function(xtype) {
10249         return Ext.isFunction(xtype) ?
10250             this.findParentBy(function(p){
10251                 return p.constructor === xtype;
10252             }) :
10253             this.findParentBy(function(p){
10254                 return p.constructor.xtype === xtype;
10255             });
10256     },
10257
10258     
10259     getPositionEl : function(){
10260         return this.positionEl || this.el;
10261     },
10262
10263     
10264     purgeListeners : function(){
10265         Ext.Component.superclass.purgeListeners.call(this);
10266         if(this.mons){
10267             this.on('beforedestroy', this.clearMons, this, {single: true});
10268         }
10269     },
10270
10271     
10272     clearMons : function(){
10273         Ext.each(this.mons, function(m){
10274             m.item.un(m.ename, m.fn, m.scope);
10275         }, this);
10276         this.mons = [];
10277     },
10278
10279     
10280     createMons: function(){
10281         if(!this.mons){
10282             this.mons = [];
10283             this.on('beforedestroy', this.clearMons, this, {single: true});
10284         }
10285     },
10286
10287     
10288     mon : function(item, ename, fn, scope, opt){
10289         this.createMons();
10290         if(Ext.isObject(ename)){
10291             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
10292
10293             var o = ename;
10294             for(var e in o){
10295                 if(propRe.test(e)){
10296                     continue;
10297                 }
10298                 if(Ext.isFunction(o[e])){
10299                     
10300                     this.mons.push({
10301                         item: item, ename: e, fn: o[e], scope: o.scope
10302                     });
10303                     item.on(e, o[e], o.scope, o);
10304                 }else{
10305                     
10306                     this.mons.push({
10307                         item: item, ename: e, fn: o[e], scope: o.scope
10308                     });
10309                     item.on(e, o[e]);
10310                 }
10311             }
10312             return;
10313         }
10314
10315         this.mons.push({
10316             item: item, ename: ename, fn: fn, scope: scope
10317         });
10318         item.on(ename, fn, scope, opt);
10319     },
10320
10321     
10322     mun : function(item, ename, fn, scope){
10323         var found, mon;
10324         this.createMons();
10325         for(var i = 0, len = this.mons.length; i < len; ++i){
10326             mon = this.mons[i];
10327             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
10328                 this.mons.splice(i, 1);
10329                 item.un(ename, fn, scope);
10330                 found = true;
10331                 break;
10332             }
10333         }
10334         return found;
10335     },
10336
10337     
10338     nextSibling : function(){
10339         if(this.ownerCt){
10340             var index = this.ownerCt.items.indexOf(this);
10341             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
10342                 return this.ownerCt.items.itemAt(index+1);
10343             }
10344         }
10345         return null;
10346     },
10347
10348     
10349     previousSibling : function(){
10350         if(this.ownerCt){
10351             var index = this.ownerCt.items.indexOf(this);
10352             if(index > 0){
10353                 return this.ownerCt.items.itemAt(index-1);
10354             }
10355         }
10356         return null;
10357     },
10358
10359     
10360     getBubbleTarget : function(){
10361         return this.ownerCt;
10362     }
10363 });
10364
10365 Ext.reg('component', Ext.Component);
10366 Ext.Action = Ext.extend(Object, {
10367     
10368     
10369     
10370     
10371     
10372     
10373     
10374
10375     constructor : function(config){
10376         this.initialConfig = config;
10377         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
10378         this.items = [];
10379     },
10380     
10381     
10382     isAction : true,
10383
10384     
10385     setText : function(text){
10386         this.initialConfig.text = text;
10387         this.callEach('setText', [text]);
10388     },
10389
10390     
10391     getText : function(){
10392         return this.initialConfig.text;
10393     },
10394
10395     
10396     setIconClass : function(cls){
10397         this.initialConfig.iconCls = cls;
10398         this.callEach('setIconClass', [cls]);
10399     },
10400
10401     
10402     getIconClass : function(){
10403         return this.initialConfig.iconCls;
10404     },
10405
10406     
10407     setDisabled : function(v){
10408         this.initialConfig.disabled = v;
10409         this.callEach('setDisabled', [v]);
10410     },
10411
10412     
10413     enable : function(){
10414         this.setDisabled(false);
10415     },
10416
10417     
10418     disable : function(){
10419         this.setDisabled(true);
10420     },
10421
10422     
10423     isDisabled : function(){
10424         return this.initialConfig.disabled;
10425     },
10426
10427     
10428     setHidden : function(v){
10429         this.initialConfig.hidden = v;
10430         this.callEach('setVisible', [!v]);
10431     },
10432
10433     
10434     show : function(){
10435         this.setHidden(false);
10436     },
10437
10438     
10439     hide : function(){
10440         this.setHidden(true);
10441     },
10442
10443     
10444     isHidden : function(){
10445         return this.initialConfig.hidden;
10446     },
10447
10448     
10449     setHandler : function(fn, scope){
10450         this.initialConfig.handler = fn;
10451         this.initialConfig.scope = scope;
10452         this.callEach('setHandler', [fn, scope]);
10453     },
10454
10455     
10456     each : function(fn, scope){
10457         Ext.each(this.items, fn, scope);
10458     },
10459
10460     
10461     callEach : function(fnName, args){
10462         var cs = this.items;
10463         for(var i = 0, len = cs.length; i < len; i++){
10464             cs[i][fnName].apply(cs[i], args);
10465         }
10466     },
10467
10468     
10469     addComponent : function(comp){
10470         this.items.push(comp);
10471         comp.on('destroy', this.removeComponent, this);
10472     },
10473
10474     
10475     removeComponent : function(comp){
10476         this.items.remove(comp);
10477     },
10478
10479     
10480     execute : function(){
10481         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
10482     }
10483 });
10484
10485 (function(){
10486 Ext.Layer = function(config, existingEl){
10487     config = config || {};
10488     var dh = Ext.DomHelper;
10489     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
10490     if(existingEl){
10491         this.dom = Ext.getDom(existingEl);
10492     }
10493     if(!this.dom){
10494         var o = config.dh || {tag: 'div', cls: 'x-layer'};
10495         this.dom = dh.append(pel, o);
10496     }
10497     if(config.cls){
10498         this.addClass(config.cls);
10499     }
10500     this.constrain = config.constrain !== false;
10501     this.setVisibilityMode(Ext.Element.VISIBILITY);
10502     if(config.id){
10503         this.id = this.dom.id = config.id;
10504     }else{
10505         this.id = Ext.id(this.dom);
10506     }
10507     this.zindex = config.zindex || this.getZIndex();
10508     this.position('absolute', this.zindex);
10509     if(config.shadow){
10510         this.shadowOffset = config.shadowOffset || 4;
10511         this.shadow = new Ext.Shadow({
10512             offset : this.shadowOffset,
10513             mode : config.shadow
10514         });
10515     }else{
10516         this.shadowOffset = 0;
10517     }
10518     this.useShim = config.shim !== false && Ext.useShims;
10519     this.useDisplay = config.useDisplay;
10520     this.hide();
10521 };
10522
10523 var supr = Ext.Element.prototype;
10524
10525
10526 var shims = [];
10527
10528 Ext.extend(Ext.Layer, Ext.Element, {
10529
10530     getZIndex : function(){
10531         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
10532     },
10533
10534     getShim : function(){
10535         if(!this.useShim){
10536             return null;
10537         }
10538         if(this.shim){
10539             return this.shim;
10540         }
10541         var shim = shims.shift();
10542         if(!shim){
10543             shim = this.createShim();
10544             shim.enableDisplayMode('block');
10545             shim.dom.style.display = 'none';
10546             shim.dom.style.visibility = 'visible';
10547         }
10548         var pn = this.dom.parentNode;
10549         if(shim.dom.parentNode != pn){
10550             pn.insertBefore(shim.dom, this.dom);
10551         }
10552         shim.setStyle('z-index', this.getZIndex()-2);
10553         this.shim = shim;
10554         return shim;
10555     },
10556
10557     hideShim : function(){
10558         if(this.shim){
10559             this.shim.setDisplayed(false);
10560             shims.push(this.shim);
10561             delete this.shim;
10562         }
10563     },
10564
10565     disableShadow : function(){
10566         if(this.shadow){
10567             this.shadowDisabled = true;
10568             this.shadow.hide();
10569             this.lastShadowOffset = this.shadowOffset;
10570             this.shadowOffset = 0;
10571         }
10572     },
10573
10574     enableShadow : function(show){
10575         if(this.shadow){
10576             this.shadowDisabled = false;
10577             this.shadowOffset = this.lastShadowOffset;
10578             delete this.lastShadowOffset;
10579             if(show){
10580                 this.sync(true);
10581             }
10582         }
10583     },
10584
10585     
10586     
10587     
10588     sync : function(doShow){
10589         var shadow = this.shadow;
10590         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
10591             var shim = this.getShim(),
10592                 w = this.getWidth(),
10593                 h = this.getHeight(),
10594                 l = this.getLeft(true),
10595                 t = this.getTop(true);
10596
10597             if(shadow && !this.shadowDisabled){
10598                 if(doShow && !shadow.isVisible()){
10599                     shadow.show(this);
10600                 }else{
10601                     shadow.realign(l, t, w, h);
10602                 }
10603                 if(shim){
10604                     if(doShow){
10605                        shim.show();
10606                     }
10607                     
10608                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
10609                         shadowSize = shadow.el.getSize();
10610                     shimStyle.left = (shadowAdj[0])+'px';
10611                     shimStyle.top = (shadowAdj[1])+'px';
10612                     shimStyle.width = (shadowSize.width)+'px';
10613                     shimStyle.height = (shadowSize.height)+'px';
10614                 }
10615             }else if(shim){
10616                 if(doShow){
10617                    shim.show();
10618                 }
10619                 shim.setSize(w, h);
10620                 shim.setLeftTop(l, t);
10621             }
10622         }
10623     },
10624
10625     
10626     destroy : function(){
10627         this.hideShim();
10628         if(this.shadow){
10629             this.shadow.hide();
10630         }
10631         this.removeAllListeners();
10632         Ext.removeNode(this.dom);
10633         delete this.dom;
10634     },
10635
10636     remove : function(){
10637         this.destroy();
10638     },
10639
10640     
10641     beginUpdate : function(){
10642         this.updating = true;
10643     },
10644
10645     
10646     endUpdate : function(){
10647         this.updating = false;
10648         this.sync(true);
10649     },
10650
10651     
10652     hideUnders : function(negOffset){
10653         if(this.shadow){
10654             this.shadow.hide();
10655         }
10656         this.hideShim();
10657     },
10658
10659     
10660     constrainXY : function(){
10661         if(this.constrain){
10662             var vw = Ext.lib.Dom.getViewWidth(),
10663                 vh = Ext.lib.Dom.getViewHeight();
10664             var s = Ext.getDoc().getScroll();
10665
10666             var xy = this.getXY();
10667             var x = xy[0], y = xy[1];
10668             var so = this.shadowOffset;
10669             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
10670             
10671             var moved = false;
10672             
10673             if((x + w) > vw+s.left){
10674                 x = vw - w - so;
10675                 moved = true;
10676             }
10677             if((y + h) > vh+s.top){
10678                 y = vh - h - so;
10679                 moved = true;
10680             }
10681             
10682             if(x < s.left){
10683                 x = s.left;
10684                 moved = true;
10685             }
10686             if(y < s.top){
10687                 y = s.top;
10688                 moved = true;
10689             }
10690             if(moved){
10691                 if(this.avoidY){
10692                     var ay = this.avoidY;
10693                     if(y <= ay && (y+h) >= ay){
10694                         y = ay-h-5;
10695                     }
10696                 }
10697                 xy = [x, y];
10698                 this.storeXY(xy);
10699                 supr.setXY.call(this, xy);
10700                 this.sync();
10701             }
10702         }
10703         return this;
10704     },
10705
10706     isVisible : function(){
10707         return this.visible;
10708     },
10709
10710     
10711     showAction : function(){
10712         this.visible = true; 
10713         if(this.useDisplay === true){
10714             this.setDisplayed('');
10715         }else if(this.lastXY){
10716             supr.setXY.call(this, this.lastXY);
10717         }else if(this.lastLT){
10718             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
10719         }
10720     },
10721
10722     
10723     hideAction : function(){
10724         this.visible = false;
10725         if(this.useDisplay === true){
10726             this.setDisplayed(false);
10727         }else{
10728             this.setLeftTop(-10000,-10000);
10729         }
10730     },
10731
10732     
10733     setVisible : function(v, a, d, c, e){
10734         if(v){
10735             this.showAction();
10736         }
10737         if(a && v){
10738             var cb = function(){
10739                 this.sync(true);
10740                 if(c){
10741                     c();
10742                 }
10743             }.createDelegate(this);
10744             supr.setVisible.call(this, true, true, d, cb, e);
10745         }else{
10746             if(!v){
10747                 this.hideUnders(true);
10748             }
10749             var cb = c;
10750             if(a){
10751                 cb = function(){
10752                     this.hideAction();
10753                     if(c){
10754                         c();
10755                     }
10756                 }.createDelegate(this);
10757             }
10758             supr.setVisible.call(this, v, a, d, cb, e);
10759             if(v){
10760                 this.sync(true);
10761             }else if(!a){
10762                 this.hideAction();
10763             }
10764         }
10765         return this;
10766     },
10767
10768     storeXY : function(xy){
10769         delete this.lastLT;
10770         this.lastXY = xy;
10771     },
10772
10773     storeLeftTop : function(left, top){
10774         delete this.lastXY;
10775         this.lastLT = [left, top];
10776     },
10777
10778     
10779     beforeFx : function(){
10780         this.beforeAction();
10781         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
10782     },
10783
10784     
10785     afterFx : function(){
10786         Ext.Layer.superclass.afterFx.apply(this, arguments);
10787         this.sync(this.isVisible());
10788     },
10789
10790     
10791     beforeAction : function(){
10792         if(!this.updating && this.shadow){
10793             this.shadow.hide();
10794         }
10795     },
10796
10797     
10798     setLeft : function(left){
10799         this.storeLeftTop(left, this.getTop(true));
10800         supr.setLeft.apply(this, arguments);
10801         this.sync();
10802         return this;
10803     },
10804
10805     setTop : function(top){
10806         this.storeLeftTop(this.getLeft(true), top);
10807         supr.setTop.apply(this, arguments);
10808         this.sync();
10809         return this;
10810     },
10811
10812     setLeftTop : function(left, top){
10813         this.storeLeftTop(left, top);
10814         supr.setLeftTop.apply(this, arguments);
10815         this.sync();
10816         return this;
10817     },
10818
10819     setXY : function(xy, a, d, c, e){
10820         this.fixDisplay();
10821         this.beforeAction();
10822         this.storeXY(xy);
10823         var cb = this.createCB(c);
10824         supr.setXY.call(this, xy, a, d, cb, e);
10825         if(!a){
10826             cb();
10827         }
10828         return this;
10829     },
10830
10831     
10832     createCB : function(c){
10833         var el = this;
10834         return function(){
10835             el.constrainXY();
10836             el.sync(true);
10837             if(c){
10838                 c();
10839             }
10840         };
10841     },
10842
10843     
10844     setX : function(x, a, d, c, e){
10845         this.setXY([x, this.getY()], a, d, c, e);
10846         return this;
10847     },
10848
10849     
10850     setY : function(y, a, d, c, e){
10851         this.setXY([this.getX(), y], a, d, c, e);
10852         return this;
10853     },
10854
10855     
10856     setSize : function(w, h, a, d, c, e){
10857         this.beforeAction();
10858         var cb = this.createCB(c);
10859         supr.setSize.call(this, w, h, a, d, cb, e);
10860         if(!a){
10861             cb();
10862         }
10863         return this;
10864     },
10865
10866     
10867     setWidth : function(w, a, d, c, e){
10868         this.beforeAction();
10869         var cb = this.createCB(c);
10870         supr.setWidth.call(this, w, a, d, cb, e);
10871         if(!a){
10872             cb();
10873         }
10874         return this;
10875     },
10876
10877     
10878     setHeight : function(h, a, d, c, e){
10879         this.beforeAction();
10880         var cb = this.createCB(c);
10881         supr.setHeight.call(this, h, a, d, cb, e);
10882         if(!a){
10883             cb();
10884         }
10885         return this;
10886     },
10887
10888     
10889     setBounds : function(x, y, w, h, a, d, c, e){
10890         this.beforeAction();
10891         var cb = this.createCB(c);
10892         if(!a){
10893             this.storeXY([x, y]);
10894             supr.setXY.call(this, [x, y]);
10895             supr.setSize.call(this, w, h, a, d, cb, e);
10896             cb();
10897         }else{
10898             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
10899         }
10900         return this;
10901     },
10902
10903     
10904     setZIndex : function(zindex){
10905         this.zindex = zindex;
10906         this.setStyle('z-index', zindex + 2);
10907         if(this.shadow){
10908             this.shadow.setZIndex(zindex + 1);
10909         }
10910         if(this.shim){
10911             this.shim.setStyle('z-index', zindex);
10912         }
10913         return this;
10914     }
10915 });
10916 })();
10917
10918 Ext.Shadow = function(config){
10919     Ext.apply(this, config);
10920     if(typeof this.mode != "string"){
10921         this.mode = this.defaultMode;
10922     }
10923     var o = this.offset, a = {h: 0};
10924     var rad = Math.floor(this.offset/2);
10925     switch(this.mode.toLowerCase()){ 
10926         case "drop":
10927             a.w = 0;
10928             a.l = a.t = o;
10929             a.t -= 1;
10930             if(Ext.isIE){
10931                 a.l -= this.offset + rad;
10932                 a.t -= this.offset + rad;
10933                 a.w -= rad;
10934                 a.h -= rad;
10935                 a.t += 1;
10936             }
10937         break;
10938         case "sides":
10939             a.w = (o*2);
10940             a.l = -o;
10941             a.t = o-1;
10942             if(Ext.isIE){
10943                 a.l -= (this.offset - rad);
10944                 a.t -= this.offset + rad;
10945                 a.l += 1;
10946                 a.w -= (this.offset - rad)*2;
10947                 a.w -= rad + 1;
10948                 a.h -= 1;
10949             }
10950         break;
10951         case "frame":
10952             a.w = a.h = (o*2);
10953             a.l = a.t = -o;
10954             a.t += 1;
10955             a.h -= 2;
10956             if(Ext.isIE){
10957                 a.l -= (this.offset - rad);
10958                 a.t -= (this.offset - rad);
10959                 a.l += 1;
10960                 a.w -= (this.offset + rad + 1);
10961                 a.h -= (this.offset + rad);
10962                 a.h += 1;
10963             }
10964         break;
10965     };
10966
10967     this.adjusts = a;
10968 };
10969
10970 Ext.Shadow.prototype = {
10971     
10972     
10973     offset: 4,
10974
10975     
10976     defaultMode: "drop",
10977
10978     
10979     show : function(target){
10980         target = Ext.get(target);
10981         if(!this.el){
10982             this.el = Ext.Shadow.Pool.pull();
10983             if(this.el.dom.nextSibling != target.dom){
10984                 this.el.insertBefore(target);
10985             }
10986         }
10987         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
10988         if(Ext.isIE){
10989             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
10990         }
10991         this.realign(
10992             target.getLeft(true),
10993             target.getTop(true),
10994             target.getWidth(),
10995             target.getHeight()
10996         );
10997         this.el.dom.style.display = "block";
10998     },
10999
11000     
11001     isVisible : function(){
11002         return this.el ? true : false;  
11003     },
11004
11005     
11006     realign : function(l, t, w, h){
11007         if(!this.el){
11008             return;
11009         }
11010         var a = this.adjusts, d = this.el.dom, s = d.style;
11011         var iea = 0;
11012         s.left = (l+a.l)+"px";
11013         s.top = (t+a.t)+"px";
11014         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
11015         if(s.width != sws || s.height != shs){
11016             s.width = sws;
11017             s.height = shs;
11018             if(!Ext.isIE){
11019                 var cn = d.childNodes;
11020                 var sww = Math.max(0, (sw-12))+"px";
11021                 cn[0].childNodes[1].style.width = sww;
11022                 cn[1].childNodes[1].style.width = sww;
11023                 cn[2].childNodes[1].style.width = sww;
11024                 cn[1].style.height = Math.max(0, (sh-12))+"px";
11025             }
11026         }
11027     },
11028
11029     
11030     hide : function(){
11031         if(this.el){
11032             this.el.dom.style.display = "none";
11033             Ext.Shadow.Pool.push(this.el);
11034             delete this.el;
11035         }
11036     },
11037
11038     
11039     setZIndex : function(z){
11040         this.zIndex = z;
11041         if(this.el){
11042             this.el.setStyle("z-index", z);
11043         }
11044     }
11045 };
11046
11047
11048 Ext.Shadow.Pool = function(){
11049     var p = [];
11050     var markup = Ext.isIE ?
11051                  '<div class="x-ie-shadow"></div>' :
11052                  '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
11053     return {
11054         pull : function(){
11055             var sh = p.shift();
11056             if(!sh){
11057                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
11058                 sh.autoBoxAdjust = false;
11059             }
11060             return sh;
11061         },
11062
11063         push : function(sh){
11064             p.push(sh);
11065         }
11066     };
11067 }();
11068 Ext.BoxComponent = Ext.extend(Ext.Component, {
11069
11070     
11071     
11072     
11073     
11074     
11075     
11076     
11077     
11078     
11079     
11080     
11081     
11082     
11083     
11084     
11085     
11086     
11087     
11088     
11089     
11090     
11091     
11092     
11093
11094     
11095
11096     
11097     initComponent : function(){
11098         Ext.BoxComponent.superclass.initComponent.call(this);
11099         this.addEvents(
11100             
11101             'resize',
11102             
11103             'move'
11104         );
11105     },
11106
11107     
11108     boxReady : false,
11109     
11110     deferHeight: false,
11111
11112     
11113     setSize : function(w, h){
11114
11115         
11116         if(typeof w == 'object'){
11117             h = w.height;
11118             w = w.width;
11119         }
11120         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
11121             w = this.boxMinWidth;
11122         }
11123         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
11124             h = this.boxMinHeight;
11125         }
11126         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
11127             w = this.boxMaxWidth;
11128         }
11129         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
11130             h = this.boxMaxHeight;
11131         }
11132         
11133         if(!this.boxReady){
11134             this.width  = w;
11135             this.height = h;
11136             return this;
11137         }
11138
11139         
11140         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
11141             return this;
11142         }
11143         this.lastSize = {width: w, height: h};
11144         var adj = this.adjustSize(w, h),
11145             aw = adj.width,
11146             ah = adj.height,
11147             rz;
11148         if(aw !== undefined || ah !== undefined){ 
11149             rz = this.getResizeEl();
11150             if(!this.deferHeight && aw !== undefined && ah !== undefined){
11151                 rz.setSize(aw, ah);
11152             }else if(!this.deferHeight && ah !== undefined){
11153                 rz.setHeight(ah);
11154             }else if(aw !== undefined){
11155                 rz.setWidth(aw);
11156             }
11157             this.onResize(aw, ah, w, h);
11158             this.fireEvent('resize', this, aw, ah, w, h);
11159         }
11160         return this;
11161     },
11162
11163     
11164     setWidth : function(width){
11165         return this.setSize(width);
11166     },
11167
11168     
11169     setHeight : function(height){
11170         return this.setSize(undefined, height);
11171     },
11172
11173     
11174     getSize : function(){
11175         return this.getResizeEl().getSize();
11176     },
11177
11178     
11179     getWidth : function(){
11180         return this.getResizeEl().getWidth();
11181     },
11182
11183     
11184     getHeight : function(){
11185         return this.getResizeEl().getHeight();
11186     },
11187
11188     
11189     getOuterSize : function(){
11190         var el = this.getResizeEl();
11191         return {width: el.getWidth() + el.getMargins('lr'),
11192                 height: el.getHeight() + el.getMargins('tb')};
11193     },
11194
11195     
11196     getPosition : function(local){
11197         var el = this.getPositionEl();
11198         if(local === true){
11199             return [el.getLeft(true), el.getTop(true)];
11200         }
11201         return this.xy || el.getXY();
11202     },
11203
11204     
11205     getBox : function(local){
11206         var pos = this.getPosition(local);
11207         var s = this.getSize();
11208         s.x = pos[0];
11209         s.y = pos[1];
11210         return s;
11211     },
11212
11213     
11214     updateBox : function(box){
11215         this.setSize(box.width, box.height);
11216         this.setPagePosition(box.x, box.y);
11217         return this;
11218     },
11219
11220     
11221     getResizeEl : function(){
11222         return this.resizeEl || this.el;
11223     },
11224
11225     
11226     setAutoScroll : function(scroll){
11227         if(this.rendered){
11228             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
11229         }
11230         this.autoScroll = scroll;
11231         return this;
11232     },
11233
11234     
11235     setPosition : function(x, y){
11236         if(x && typeof x[1] == 'number'){
11237             y = x[1];
11238             x = x[0];
11239         }
11240         this.x = x;
11241         this.y = y;
11242         if(!this.boxReady){
11243             return this;
11244         }
11245         var adj = this.adjustPosition(x, y);
11246         var ax = adj.x, ay = adj.y;
11247
11248         var el = this.getPositionEl();
11249         if(ax !== undefined || ay !== undefined){
11250             if(ax !== undefined && ay !== undefined){
11251                 el.setLeftTop(ax, ay);
11252             }else if(ax !== undefined){
11253                 el.setLeft(ax);
11254             }else if(ay !== undefined){
11255                 el.setTop(ay);
11256             }
11257             this.onPosition(ax, ay);
11258             this.fireEvent('move', this, ax, ay);
11259         }
11260         return this;
11261     },
11262
11263     
11264     setPagePosition : function(x, y){
11265         if(x && typeof x[1] == 'number'){
11266             y = x[1];
11267             x = x[0];
11268         }
11269         this.pageX = x;
11270         this.pageY = y;
11271         if(!this.boxReady){
11272             return;
11273         }
11274         if(x === undefined || y === undefined){ 
11275             return;
11276         }
11277         var p = this.getPositionEl().translatePoints(x, y);
11278         this.setPosition(p.left, p.top);
11279         return this;
11280     },
11281
11282     
11283     afterRender : function(){
11284         Ext.BoxComponent.superclass.afterRender.call(this);
11285         if(this.resizeEl){
11286             this.resizeEl = Ext.get(this.resizeEl);
11287         }
11288         if(this.positionEl){
11289             this.positionEl = Ext.get(this.positionEl);
11290         }
11291         this.boxReady = true;
11292         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
11293         this.setSize(this.width, this.height);
11294         if(this.x || this.y){
11295             this.setPosition(this.x, this.y);
11296         }else if(this.pageX || this.pageY){
11297             this.setPagePosition(this.pageX, this.pageY);
11298         }
11299     },
11300
11301     
11302     syncSize : function(){
11303         delete this.lastSize;
11304         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
11305         return this;
11306     },
11307
11308     
11309     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
11310     },
11311
11312     
11313     onPosition : function(x, y){
11314
11315     },
11316
11317     
11318     adjustSize : function(w, h){
11319         if(this.autoWidth){
11320             w = 'auto';
11321         }
11322         if(this.autoHeight){
11323             h = 'auto';
11324         }
11325         return {width : w, height: h};
11326     },
11327
11328     
11329     adjustPosition : function(x, y){
11330         return {x : x, y: y};
11331     }
11332 });
11333 Ext.reg('box', Ext.BoxComponent);
11334
11335
11336
11337 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
11338     autoEl:'div'
11339 });
11340 Ext.reg('spacer', Ext.Spacer);
11341 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
11342
11343     
11344     this.el = Ext.get(dragElement, true);
11345     this.el.dom.unselectable = "on";
11346     
11347     this.resizingEl = Ext.get(resizingElement, true);
11348
11349     
11350     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
11351
11352     
11353     
11354     this.minSize = 0;
11355
11356     
11357     this.maxSize = 2000;
11358
11359     
11360     this.animate = false;
11361
11362     
11363     this.useShim = false;
11364
11365     
11366     this.shim = null;
11367
11368     if(!existingProxy){
11369         
11370         this.proxy = Ext.SplitBar.createProxy(this.orientation);
11371     }else{
11372         this.proxy = Ext.get(existingProxy).dom;
11373     }
11374     
11375     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
11376
11377     
11378     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
11379
11380     
11381     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
11382
11383     
11384     this.dragSpecs = {};
11385
11386     
11387     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
11388     this.adapter.init(this);
11389
11390     if(this.orientation == Ext.SplitBar.HORIZONTAL){
11391         
11392         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
11393         this.el.addClass("x-splitbar-h");
11394     }else{
11395         
11396         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
11397         this.el.addClass("x-splitbar-v");
11398     }
11399
11400     this.addEvents(
11401         
11402         "resize",
11403         
11404         "moved",
11405         
11406         "beforeresize",
11407
11408         "beforeapply"
11409     );
11410
11411     Ext.SplitBar.superclass.constructor.call(this);
11412 };
11413
11414 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
11415     onStartProxyDrag : function(x, y){
11416         this.fireEvent("beforeresize", this);
11417         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
11418         this.overlay.unselectable();
11419         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
11420         this.overlay.show();
11421         Ext.get(this.proxy).setDisplayed("block");
11422         var size = this.adapter.getElementSize(this);
11423         this.activeMinSize = this.getMinimumSize();
11424         this.activeMaxSize = this.getMaximumSize();
11425         var c1 = size - this.activeMinSize;
11426         var c2 = Math.max(this.activeMaxSize - size, 0);
11427         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11428             this.dd.resetConstraints();
11429             this.dd.setXConstraint(
11430                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
11431                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
11432                 this.tickSize
11433             );
11434             this.dd.setYConstraint(0, 0);
11435         }else{
11436             this.dd.resetConstraints();
11437             this.dd.setXConstraint(0, 0);
11438             this.dd.setYConstraint(
11439                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
11440                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
11441                 this.tickSize
11442             );
11443          }
11444         this.dragSpecs.startSize = size;
11445         this.dragSpecs.startPoint = [x, y];
11446         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
11447     },
11448
11449     
11450     onEndProxyDrag : function(e){
11451         Ext.get(this.proxy).setDisplayed(false);
11452         var endPoint = Ext.lib.Event.getXY(e);
11453         if(this.overlay){
11454             Ext.destroy(this.overlay);
11455             delete this.overlay;
11456         }
11457         var newSize;
11458         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11459             newSize = this.dragSpecs.startSize +
11460                 (this.placement == Ext.SplitBar.LEFT ?
11461                     endPoint[0] - this.dragSpecs.startPoint[0] :
11462                     this.dragSpecs.startPoint[0] - endPoint[0]
11463                 );
11464         }else{
11465             newSize = this.dragSpecs.startSize +
11466                 (this.placement == Ext.SplitBar.TOP ?
11467                     endPoint[1] - this.dragSpecs.startPoint[1] :
11468                     this.dragSpecs.startPoint[1] - endPoint[1]
11469                 );
11470         }
11471         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
11472         if(newSize != this.dragSpecs.startSize){
11473             if(this.fireEvent('beforeapply', this, newSize) !== false){
11474                 this.adapter.setElementSize(this, newSize);
11475                 this.fireEvent("moved", this, newSize);
11476                 this.fireEvent("resize", this, newSize);
11477             }
11478         }
11479     },
11480
11481     
11482     getAdapter : function(){
11483         return this.adapter;
11484     },
11485
11486     
11487     setAdapter : function(adapter){
11488         this.adapter = adapter;
11489         this.adapter.init(this);
11490     },
11491
11492     
11493     getMinimumSize : function(){
11494         return this.minSize;
11495     },
11496
11497     
11498     setMinimumSize : function(minSize){
11499         this.minSize = minSize;
11500     },
11501
11502     
11503     getMaximumSize : function(){
11504         return this.maxSize;
11505     },
11506
11507     
11508     setMaximumSize : function(maxSize){
11509         this.maxSize = maxSize;
11510     },
11511
11512     
11513     setCurrentSize : function(size){
11514         var oldAnimate = this.animate;
11515         this.animate = false;
11516         this.adapter.setElementSize(this, size);
11517         this.animate = oldAnimate;
11518     },
11519
11520     
11521     destroy : function(removeEl){
11522         Ext.destroy(this.shim, Ext.get(this.proxy));
11523         this.dd.unreg();
11524         if(removeEl){
11525             this.el.remove();
11526         }
11527         this.purgeListeners();
11528     }
11529 });
11530
11531
11532 Ext.SplitBar.createProxy = function(dir){
11533     var proxy = new Ext.Element(document.createElement("div"));
11534     document.body.appendChild(proxy.dom);
11535     proxy.unselectable();
11536     var cls = 'x-splitbar-proxy';
11537     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
11538     return proxy.dom;
11539 };
11540
11541
11542 Ext.SplitBar.BasicLayoutAdapter = function(){
11543 };
11544
11545 Ext.SplitBar.BasicLayoutAdapter.prototype = {
11546     
11547     init : function(s){
11548
11549     },
11550     
11551      getElementSize : function(s){
11552         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11553             return s.resizingEl.getWidth();
11554         }else{
11555             return s.resizingEl.getHeight();
11556         }
11557     },
11558
11559     
11560     setElementSize : function(s, newSize, onComplete){
11561         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11562             if(!s.animate){
11563                 s.resizingEl.setWidth(newSize);
11564                 if(onComplete){
11565                     onComplete(s, newSize);
11566                 }
11567             }else{
11568                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
11569             }
11570         }else{
11571
11572             if(!s.animate){
11573                 s.resizingEl.setHeight(newSize);
11574                 if(onComplete){
11575                     onComplete(s, newSize);
11576                 }
11577             }else{
11578                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
11579             }
11580         }
11581     }
11582 };
11583
11584
11585 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
11586     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
11587     this.container = Ext.get(container);
11588 };
11589
11590 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
11591     init : function(s){
11592         this.basic.init(s);
11593     },
11594
11595     getElementSize : function(s){
11596         return this.basic.getElementSize(s);
11597     },
11598
11599     setElementSize : function(s, newSize, onComplete){
11600         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
11601     },
11602
11603     moveSplitter : function(s){
11604         var yes = Ext.SplitBar;
11605         switch(s.placement){
11606             case yes.LEFT:
11607                 s.el.setX(s.resizingEl.getRight());
11608                 break;
11609             case yes.RIGHT:
11610                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
11611                 break;
11612             case yes.TOP:
11613                 s.el.setY(s.resizingEl.getBottom());
11614                 break;
11615             case yes.BOTTOM:
11616                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
11617                 break;
11618         }
11619     }
11620 };
11621
11622
11623 Ext.SplitBar.VERTICAL = 1;
11624
11625
11626 Ext.SplitBar.HORIZONTAL = 2;
11627
11628
11629 Ext.SplitBar.LEFT = 1;
11630
11631
11632 Ext.SplitBar.RIGHT = 2;
11633
11634
11635 Ext.SplitBar.TOP = 3;
11636
11637
11638 Ext.SplitBar.BOTTOM = 4;
11639
11640 Ext.Container = Ext.extend(Ext.BoxComponent, {
11641     
11642     
11643     
11644     
11645     bufferResize: 50,
11646
11647     
11648     
11649     
11650
11651
11652     
11653     autoDestroy : true,
11654
11655     
11656     forceLayout: false,
11657
11658     
11659     
11660     defaultType : 'panel',
11661
11662     
11663     resizeEvent: 'resize',
11664
11665     
11666     bubbleEvents: ['add', 'remove'],
11667
11668     
11669     initComponent : function(){
11670         Ext.Container.superclass.initComponent.call(this);
11671
11672         this.addEvents(
11673             
11674             'afterlayout',
11675             
11676             'beforeadd',
11677             
11678             'beforeremove',
11679             
11680             'add',
11681             
11682             'remove'
11683         );
11684
11685         
11686         var items = this.items;
11687         if(items){
11688             delete this.items;
11689             this.add(items);
11690         }
11691     },
11692
11693     
11694     initItems : function(){
11695         if(!this.items){
11696             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
11697             this.getLayout(); 
11698         }
11699     },
11700
11701     
11702     setLayout : function(layout){
11703         if(this.layout && this.layout != layout){
11704             this.layout.setContainer(null);
11705         }
11706         this.layout = layout;
11707         this.initItems();
11708         layout.setContainer(this);
11709     },
11710
11711     afterRender: function(){
11712         
11713         
11714         Ext.Container.superclass.afterRender.call(this);
11715         if(!this.layout){
11716             this.layout = 'auto';
11717         }
11718         if(Ext.isObject(this.layout) && !this.layout.layout){
11719             this.layoutConfig = this.layout;
11720             this.layout = this.layoutConfig.type;
11721         }
11722         if(Ext.isString(this.layout)){
11723             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
11724         }
11725         this.setLayout(this.layout);
11726
11727         
11728         if(this.activeItem !== undefined){
11729             var item = this.activeItem;
11730             delete this.activeItem;
11731             this.layout.setActiveItem(item);
11732         }
11733
11734         
11735         if(!this.ownerCt){
11736             this.doLayout(false, true);
11737         }
11738
11739         
11740         
11741         if(this.monitorResize === true){
11742             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
11743         }
11744     },
11745
11746     
11747     getLayoutTarget : function(){
11748         return this.el;
11749     },
11750
11751     
11752     getComponentId : function(comp){
11753         return comp.getItemId();
11754     },
11755
11756     
11757     add : function(comp){
11758         this.initItems();
11759         var args = arguments.length > 1;
11760         if(args || Ext.isArray(comp)){
11761             var result = [];
11762             Ext.each(args ? arguments : comp, function(c){
11763                 result.push(this.add(c));
11764             }, this);
11765             return result;
11766         }
11767         var c = this.lookupComponent(this.applyDefaults(comp));
11768         var index = this.items.length;
11769         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11770             this.items.add(c);
11771             
11772             c.onAdded(this, index);
11773             this.onAdd(c);
11774             this.fireEvent('add', this, c, index);
11775         }
11776         return c;
11777     },
11778
11779     onAdd : function(c){
11780         
11781     },
11782
11783     
11784     onAdded : function(container, pos) {
11785         
11786         this.ownerCt = container;
11787         this.initRef();
11788         
11789         this.cascade(function(c){
11790             c.initRef();
11791         });
11792         this.fireEvent('added', this, container, pos);
11793     },
11794
11795     
11796     insert : function(index, comp){
11797         this.initItems();
11798         var a = arguments, len = a.length;
11799         if(len > 2){
11800             var result = [];
11801             for(var i = len-1; i >= 1; --i) {
11802                 result.push(this.insert(index, a[i]));
11803             }
11804             return result;
11805         }
11806         var c = this.lookupComponent(this.applyDefaults(comp));
11807         index = Math.min(index, this.items.length);
11808         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11809             if(c.ownerCt == this){
11810                 this.items.remove(c);
11811             }
11812             this.items.insert(index, c);
11813             c.onAdded(this, index);
11814             this.onAdd(c);
11815             this.fireEvent('add', this, c, index);
11816         }
11817         return c;
11818     },
11819
11820     
11821     applyDefaults : function(c){
11822         var d = this.defaults;
11823         if(d){
11824             if(Ext.isFunction(d)){
11825                 d = d.call(this, c);
11826             }
11827             if(Ext.isString(c)){
11828                 c = Ext.ComponentMgr.get(c);
11829                 Ext.apply(c, d);
11830             }else if(!c.events){
11831                 Ext.applyIf(c, d);
11832             }else{
11833                 Ext.apply(c, d);
11834             }
11835         }
11836         return c;
11837     },
11838
11839     
11840     onBeforeAdd : function(item){
11841         if(item.ownerCt){
11842             item.ownerCt.remove(item, false);
11843         }
11844         if(this.hideBorders === true){
11845             item.border = (item.border === true);
11846         }
11847     },
11848
11849     
11850     remove : function(comp, autoDestroy){
11851         this.initItems();
11852         var c = this.getComponent(comp);
11853         if(c && this.fireEvent('beforeremove', this, c) !== false){
11854             this.doRemove(c, autoDestroy);
11855             this.fireEvent('remove', this, c);
11856         }
11857         return c;
11858     },
11859
11860     onRemove: function(c){
11861         
11862     },
11863
11864     
11865     doRemove: function(c, autoDestroy){
11866         var l = this.layout,
11867             hasLayout = l && this.rendered;
11868
11869         if(hasLayout){
11870             l.onRemove(c);
11871         }
11872         this.items.remove(c);
11873         c.onRemoved();
11874         this.onRemove(c);
11875         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
11876             c.destroy();
11877         }
11878         if(hasLayout){
11879             l.afterRemove(c);
11880         }
11881     },
11882
11883     
11884     removeAll: function(autoDestroy){
11885         this.initItems();
11886         var item, rem = [], items = [];
11887         this.items.each(function(i){
11888             rem.push(i);
11889         });
11890         for (var i = 0, len = rem.length; i < len; ++i){
11891             item = rem[i];
11892             this.remove(item, autoDestroy);
11893             if(item.ownerCt !== this){
11894                 items.push(item);
11895             }
11896         }
11897         return items;
11898     },
11899
11900     
11901     getComponent : function(comp){
11902         if(Ext.isObject(comp)){
11903             comp = comp.getItemId();
11904         }
11905         return this.items.get(comp);
11906     },
11907
11908     
11909     lookupComponent : function(comp){
11910         if(Ext.isString(comp)){
11911             return Ext.ComponentMgr.get(comp);
11912         }else if(!comp.events){
11913             return this.createComponent(comp);
11914         }
11915         return comp;
11916     },
11917
11918     
11919     createComponent : function(config, defaultType){
11920         if (config.render) {
11921             return config;
11922         }
11923         
11924         
11925         var c = Ext.create(Ext.apply({
11926             ownerCt: this
11927         }, config), defaultType || this.defaultType);
11928         delete c.initialConfig.ownerCt;
11929         delete c.ownerCt;
11930         return c;
11931     },
11932
11933     
11934     canLayout : function() {
11935         var el = this.getVisibilityEl();
11936         return el && el.dom && !el.isStyle("display", "none");
11937     },
11938
11939     
11940
11941     doLayout : function(shallow, force){
11942         var rendered = this.rendered,
11943             forceLayout = force || this.forceLayout;
11944
11945         if(this.collapsed || !this.canLayout()){
11946             this.deferLayout = this.deferLayout || !shallow;
11947             if(!forceLayout){
11948                 return;
11949             }
11950             shallow = shallow && !this.deferLayout;
11951         } else {
11952             delete this.deferLayout;
11953         }
11954         if(rendered && this.layout){
11955             this.layout.layout();
11956         }
11957         if(shallow !== true && this.items){
11958             var cs = this.items.items;
11959             for(var i = 0, len = cs.length; i < len; i++){
11960                 var c = cs[i];
11961                 if(c.doLayout){
11962                     c.doLayout(false, forceLayout);
11963                 }
11964             }
11965         }
11966         if(rendered){
11967             this.onLayout(shallow, forceLayout);
11968         }
11969         
11970         this.hasLayout = true;
11971         delete this.forceLayout;
11972     },
11973
11974     onLayout : Ext.emptyFn,
11975
11976     
11977     shouldBufferLayout: function(){
11978         
11979         var hl = this.hasLayout;
11980         if(this.ownerCt){
11981             
11982             return hl ? !this.hasLayoutPending() : false;
11983         }
11984         
11985         return hl;
11986     },
11987
11988     
11989     hasLayoutPending: function(){
11990         
11991         var pending = false;
11992         this.ownerCt.bubble(function(c){
11993             if(c.layoutPending){
11994                 pending = true;
11995                 return false;
11996             }
11997         });
11998         return pending;
11999     },
12000
12001     onShow : function(){
12002         
12003         Ext.Container.superclass.onShow.call(this);
12004         
12005         if(Ext.isDefined(this.deferLayout)){
12006             delete this.deferLayout;
12007             this.doLayout(true);
12008         }
12009     },
12010
12011     
12012     getLayout : function(){
12013         if(!this.layout){
12014             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
12015             this.setLayout(layout);
12016         }
12017         return this.layout;
12018     },
12019
12020     
12021     beforeDestroy : function(){
12022         var c;
12023         if(this.items){
12024             while(c = this.items.first()){
12025                 this.doRemove(c, true);
12026             }
12027         }
12028         if(this.monitorResize){
12029             Ext.EventManager.removeResizeListener(this.doLayout, this);
12030         }
12031         Ext.destroy(this.layout);
12032         Ext.Container.superclass.beforeDestroy.call(this);
12033     },
12034
12035     
12036     bubble : function(fn, scope, args){
12037         var p = this;
12038         while(p){
12039             if(fn.apply(scope || p, args || [p]) === false){
12040                 break;
12041             }
12042             p = p.ownerCt;
12043         }
12044         return this;
12045     },
12046
12047     
12048     cascade : function(fn, scope, args){
12049         if(fn.apply(scope || this, args || [this]) !== false){
12050             if(this.items){
12051                 var cs = this.items.items;
12052                 for(var i = 0, len = cs.length; i < len; i++){
12053                     if(cs[i].cascade){
12054                         cs[i].cascade(fn, scope, args);
12055                     }else{
12056                         fn.apply(scope || cs[i], args || [cs[i]]);
12057                     }
12058                 }
12059             }
12060         }
12061         return this;
12062     },
12063
12064     
12065     findById : function(id){
12066         var m, ct = this;
12067         this.cascade(function(c){
12068             if(ct != c && c.id === id){
12069                 m = c;
12070                 return false;
12071             }
12072         });
12073         return m || null;
12074     },
12075
12076     
12077     findByType : function(xtype, shallow){
12078         return this.findBy(function(c){
12079             return c.isXType(xtype, shallow);
12080         });
12081     },
12082
12083     
12084     find : function(prop, value){
12085         return this.findBy(function(c){
12086             return c[prop] === value;
12087         });
12088     },
12089
12090     
12091     findBy : function(fn, scope){
12092         var m = [], ct = this;
12093         this.cascade(function(c){
12094             if(ct != c && fn.call(scope || c, c, ct) === true){
12095                 m.push(c);
12096             }
12097         });
12098         return m;
12099     },
12100
12101     
12102     get : function(key){
12103         return this.items.get(key);
12104     }
12105 });
12106
12107 Ext.Container.LAYOUTS = {};
12108 Ext.reg('container', Ext.Container);
12109
12110 Ext.layout.ContainerLayout = Ext.extend(Object, {
12111     
12112     
12113
12114     
12115
12116     
12117     monitorResize:false,
12118     
12119     activeItem : null,
12120
12121     constructor : function(config){
12122         this.id = Ext.id(null, 'ext-layout-');
12123         Ext.apply(this, config);
12124     },
12125
12126     type: 'container',
12127
12128     
12129     IEMeasureHack : function(target, viewFlag) {
12130         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
12131         for (i = 0 ; i < tLen ; i++) {
12132             c = tChildren[i];
12133             e = Ext.get(c);
12134             if (e) {
12135                 d[i] = e.getStyle('display');
12136                 e.setStyle({display: 'none'});
12137             }
12138         }
12139         ret = target ? target.getViewSize(viewFlag) : {};
12140         for (i = 0 ; i < tLen ; i++) {
12141             c = tChildren[i];
12142             e = Ext.get(c);
12143             if (e) {
12144                 e.setStyle({display: d[i]});
12145             }
12146         }
12147         return ret;
12148     },
12149
12150     
12151     getLayoutTargetSize : Ext.EmptyFn,
12152
12153     
12154     layout : function(){
12155         var ct = this.container, target = ct.getLayoutTarget();
12156         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
12157             target.addClass(this.targetCls);
12158         }
12159         this.onLayout(ct, target);
12160         ct.fireEvent('afterlayout', ct, this);
12161     },
12162
12163     
12164     onLayout : function(ct, target){
12165         this.renderAll(ct, target);
12166     },
12167
12168     
12169     isValidParent : function(c, target){
12170         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
12171     },
12172
12173     
12174     renderAll : function(ct, target){
12175         var items = ct.items.items, i, c, len = items.length;
12176         for(i = 0; i < len; i++) {
12177             c = items[i];
12178             if(c && (!c.rendered || !this.isValidParent(c, target))){
12179                 this.renderItem(c, i, target);
12180             }
12181         }
12182     },
12183
12184     
12185     renderItem : function(c, position, target){
12186         if (c) {
12187             if (!c.rendered) {
12188                 c.render(target, position);
12189                 this.configureItem(c, position);
12190             } else if (!this.isValidParent(c, target)) {
12191                 if (Ext.isNumber(position)) {
12192                     position = target.dom.childNodes[position];
12193                 }
12194                 
12195                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
12196                 c.container = target;
12197                 this.configureItem(c, position);
12198             }
12199         }
12200     },
12201
12202     
12203     
12204     getRenderedItems: function(ct){
12205         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
12206         for (i = 0; i < len; i++) {
12207             if((c = cti[i]).rendered && this.isValidParent(c, t)){
12208                 items.push(c);
12209             }
12210         };
12211         return items;
12212     },
12213
12214     
12215     configureItem: function(c, position){
12216         if (this.extraCls) {
12217             var t = c.getPositionEl ? c.getPositionEl() : c;
12218             t.addClass(this.extraCls);
12219         }
12220         
12221         
12222         if (c.doLayout && this.forceLayout) {
12223             c.doLayout();
12224         }
12225         if (this.renderHidden && c != this.activeItem) {
12226             c.hide();
12227         }
12228     },
12229
12230     onRemove: function(c){
12231         if(this.activeItem == c){
12232             delete this.activeItem;
12233         }
12234         if(c.rendered && this.extraCls){
12235             var t = c.getPositionEl ? c.getPositionEl() : c;
12236             t.removeClass(this.extraCls);
12237         }
12238     },
12239
12240     afterRemove: function(c){
12241         if(c.removeRestore){
12242             c.removeMode = 'container';
12243             delete c.removeRestore;
12244         }
12245     },
12246
12247     
12248     onResize: function(){
12249         var ct = this.container,
12250             b;
12251         if(ct.collapsed){
12252             return;
12253         }
12254         if(b = ct.bufferResize && ct.shouldBufferLayout()){
12255             if(!this.resizeTask){
12256                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
12257                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
12258             }
12259             ct.layoutPending = true;
12260             this.resizeTask.delay(this.resizeBuffer);
12261         }else{
12262             this.runLayout();
12263         }
12264     },
12265
12266     runLayout: function(){
12267         var ct = this.container;
12268         this.layout();
12269         ct.onLayout();
12270         delete ct.layoutPending;
12271     },
12272
12273     
12274     setContainer : function(ct){
12275         
12276         if(this.monitorResize && ct != this.container){
12277             var old = this.container;
12278             if(old){
12279                 old.un(old.resizeEvent, this.onResize, this);
12280             }
12281             if(ct){
12282                 ct.on(ct.resizeEvent, this.onResize, this);
12283             }
12284         }
12285         this.container = ct;
12286     },
12287
12288     
12289     parseMargins : function(v){
12290         if (Ext.isNumber(v)) {
12291             v = v.toString();
12292         }
12293         var ms  = v.split(' '),
12294             len = ms.length;
12295             
12296         if (len == 1) {
12297             ms[1] = ms[2] = ms[3] = ms[0];
12298         } else if(len == 2) {
12299             ms[2] = ms[0];
12300             ms[3] = ms[1];
12301         } else if(len == 3) {
12302             ms[3] = ms[1];
12303         }
12304         
12305         return {
12306             top   :parseInt(ms[0], 10) || 0,
12307             right :parseInt(ms[1], 10) || 0,
12308             bottom:parseInt(ms[2], 10) || 0,
12309             left  :parseInt(ms[3], 10) || 0
12310         };
12311     },
12312
12313     
12314     fieldTpl: (function() {
12315         var t = new Ext.Template(
12316             '<div class="x-form-item {itemCls}" tabIndex="-1">',
12317                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
12318                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
12319                 '</div><div class="{clearCls}"></div>',
12320             '</div>'
12321         );
12322         t.disableFormats = true;
12323         return t.compile();
12324     })(),
12325
12326     
12327     destroy : function(){
12328         
12329         if(this.resizeTask && this.resizeTask.cancel){
12330             this.resizeTask.cancel();
12331         }
12332         if(!Ext.isEmpty(this.targetCls)){
12333             var target = this.container.getLayoutTarget();
12334             if(target){
12335                 target.removeClass(this.targetCls);
12336             }
12337         }
12338     }
12339 });
12340 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
12341     type: 'auto',
12342
12343     monitorResize: true,
12344
12345     onLayout : function(ct, target){
12346         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
12347         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
12348         for(i = 0; i < len; i++){
12349             c = cs[i];
12350             if (c.doLayout){
12351                 
12352                 c.doLayout(true);
12353             }
12354         }
12355     }
12356 });
12357
12358 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
12359
12360 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
12361     
12362     monitorResize:true,
12363
12364     type: 'fit',
12365
12366     getLayoutTargetSize : function() {
12367         var target = this.container.getLayoutTarget();
12368         if (!target) {
12369             return {};
12370         }
12371         
12372         return target.getStyleSize();
12373     },
12374
12375     
12376     onLayout : function(ct, target){
12377         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
12378         if(!ct.collapsed){
12379             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
12380         }
12381     },
12382
12383     
12384     setItemSize : function(item, size){
12385         if(item && size.height > 0){ 
12386             item.setSize(size);
12387         }
12388     }
12389 });
12390 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
12391 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
12392     
12393     deferredRender : false,
12394
12395     
12396     layoutOnCardChange : false,
12397
12398     
12399     
12400     renderHidden : true,
12401
12402     type: 'card',
12403
12404     
12405     setActiveItem : function(item){
12406         var ai = this.activeItem,
12407             ct = this.container;
12408         item = ct.getComponent(item);
12409
12410         
12411         if(item && ai != item){
12412
12413             
12414             if(ai){
12415                 ai.hide();
12416                 if (ai.hidden !== true) {
12417                     return false;
12418                 }
12419                 ai.fireEvent('deactivate', ai);
12420             }
12421
12422             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
12423
12424             
12425             this.activeItem = item;
12426
12427             
12428             
12429             delete item.deferLayout;
12430
12431             
12432             item.show();
12433
12434             this.layout();
12435
12436             if(layout){
12437                 item.doLayout();
12438             }
12439             item.fireEvent('activate', item);
12440         }
12441     },
12442
12443     
12444     renderAll : function(ct, target){
12445         if(this.deferredRender){
12446             this.renderItem(this.activeItem, undefined, target);
12447         }else{
12448             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
12449         }
12450     }
12451 });
12452 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
12453
12454 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
12455     
12456
12457     
12458     monitorResize : true,
12459
12460     type : 'anchor',
12461
12462     
12463     defaultAnchor : '100%',
12464
12465     parseAnchorRE : /^(r|right|b|bottom)$/i,
12466
12467     getLayoutTargetSize : function() {
12468         var target = this.container.getLayoutTarget();
12469         if (!target) {
12470             return {};
12471         }
12472         
12473         return target.getStyleSize();
12474     },
12475
12476     
12477     onLayout : function(ct, target){
12478         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
12479         var size = this.getLayoutTargetSize();
12480
12481         var w = size.width, h = size.height;
12482
12483         if(w < 20 && h < 20){
12484             return;
12485         }
12486
12487         
12488         var aw, ah;
12489         if(ct.anchorSize){
12490             if(typeof ct.anchorSize == 'number'){
12491                 aw = ct.anchorSize;
12492             }else{
12493                 aw = ct.anchorSize.width;
12494                 ah = ct.anchorSize.height;
12495             }
12496         }else{
12497             aw = ct.initialConfig.width;
12498             ah = ct.initialConfig.height;
12499         }
12500
12501         var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
12502         for(i = 0; i < len; i++){
12503             c = cs[i];
12504             el = c.getPositionEl();
12505
12506             
12507             if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
12508                 c.anchor = this.defaultAnchor;
12509             }
12510
12511             if(c.anchor){
12512                 a = c.anchorSpec;
12513                 if(!a){ 
12514                     vs = c.anchor.split(' ');
12515                     c.anchorSpec = a = {
12516                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
12517                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
12518                     };
12519                 }
12520                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
12521                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
12522
12523                 if(cw || ch){
12524                     boxes.push({
12525                         comp: c,
12526                         width: cw || undefined,
12527                         height: ch || undefined
12528                     });
12529                 }
12530             }
12531         }
12532         for (i = 0, len = boxes.length; i < len; i++) {
12533             c = boxes[i];
12534             c.comp.setSize(c.width, c.height);
12535         }
12536     },
12537
12538     
12539     parseAnchor : function(a, start, cstart){
12540         if(a && a != 'none'){
12541             var last;
12542             
12543             if(this.parseAnchorRE.test(a)){
12544                 var diff = cstart - start;
12545                 return function(v){
12546                     if(v !== last){
12547                         last = v;
12548                         return v - diff;
12549                     }
12550                 }
12551             
12552             }else if(a.indexOf('%') != -1){
12553                 var ratio = parseFloat(a.replace('%', ''))*.01;
12554                 return function(v){
12555                     if(v !== last){
12556                         last = v;
12557                         return Math.floor(v*ratio);
12558                     }
12559                 }
12560             
12561             }else{
12562                 a = parseInt(a, 10);
12563                 if(!isNaN(a)){
12564                     return function(v){
12565                         if(v !== last){
12566                             last = v;
12567                             return v + a;
12568                         }
12569                     }
12570                 }
12571             }
12572         }
12573         return false;
12574     },
12575
12576     
12577     adjustWidthAnchor : function(value, comp){
12578         return value;
12579     },
12580
12581     
12582     adjustHeightAnchor : function(value, comp){
12583         return value;
12584     }
12585
12586     
12587 });
12588 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
12589
12590 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
12591     
12592     monitorResize:true,
12593
12594     type: 'column',
12595
12596     extraCls: 'x-column',
12597
12598     scrollOffset : 0,
12599
12600     
12601
12602     targetCls: 'x-column-layout-ct',
12603
12604     isValidParent : function(c, target){
12605         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
12606     },
12607
12608     getLayoutTargetSize : function() {
12609         var target = this.container.getLayoutTarget(), ret;
12610         if (target) {
12611             ret = target.getViewSize();
12612
12613             
12614             
12615             
12616             if (Ext.isIE && Ext.isStrict && ret.width == 0){
12617                 ret =  target.getStyleSize();
12618             }
12619
12620             ret.width -= target.getPadding('lr');
12621             ret.height -= target.getPadding('tb');
12622         }
12623         return ret;
12624     },
12625
12626     renderAll : function(ct, target) {
12627         if(!this.innerCt){
12628             
12629             
12630             this.innerCt = target.createChild({cls:'x-column-inner'});
12631             this.innerCt.createChild({cls:'x-clear'});
12632         }
12633         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
12634     },
12635
12636     
12637     onLayout : function(ct, target){
12638         var cs = ct.items.items,
12639             len = cs.length,
12640             c,
12641             i,
12642             m,
12643             margins = [];
12644
12645         this.renderAll(ct, target);
12646
12647         var size = this.getLayoutTargetSize();
12648
12649         if(size.width < 1 && size.height < 1){ 
12650             return;
12651         }
12652
12653         var w = size.width - this.scrollOffset,
12654             h = size.height,
12655             pw = w;
12656
12657         this.innerCt.setWidth(w);
12658
12659         
12660         
12661
12662         for(i = 0; i < len; i++){
12663             c = cs[i];
12664             m = c.getPositionEl().getMargins('lr');
12665             margins[i] = m;
12666             if(!c.columnWidth){
12667                 pw -= (c.getWidth() + m);
12668             }
12669         }
12670
12671         pw = pw < 0 ? 0 : pw;
12672
12673         for(i = 0; i < len; i++){
12674             c = cs[i];
12675             m = margins[i];
12676             if(c.columnWidth){
12677                 c.setSize(Math.floor(c.columnWidth * pw) - m);
12678             }
12679         }
12680
12681         
12682         
12683         if (Ext.isIE) {
12684             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
12685                 var ts = this.getLayoutTargetSize();
12686                 if (ts.width != size.width){
12687                     this.adjustmentPass = true;
12688                     this.onLayout(ct, target);
12689                 }
12690             }
12691         }
12692         delete this.adjustmentPass;
12693     }
12694
12695     
12696 });
12697
12698 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
12699
12700 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
12701     
12702     monitorResize:true,
12703     
12704     rendered : false,
12705
12706     type: 'border',
12707
12708     targetCls: 'x-border-layout-ct',
12709
12710     getLayoutTargetSize : function() {
12711         var target = this.container.getLayoutTarget();
12712         return target ? target.getViewSize() : {};
12713     },
12714
12715     
12716     onLayout : function(ct, target){
12717         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
12718         if(!this.rendered){
12719             collapsed = [];
12720             for(i = 0; i < len; i++) {
12721                 c = items[i];
12722                 pos = c.region;
12723                 if(c.collapsed){
12724                     collapsed.push(c);
12725                 }
12726                 c.collapsed = false;
12727                 if(!c.rendered){
12728                     c.render(target, i);
12729                     c.getPositionEl().addClass('x-border-panel');
12730                 }
12731                 this[pos] = pos != 'center' && c.split ?
12732                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
12733                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
12734                 this[pos].render(target, c);
12735             }
12736             this.rendered = true;
12737         }
12738
12739         var size = this.getLayoutTargetSize();
12740         if(size.width < 20 || size.height < 20){ 
12741             if(collapsed){
12742                 this.restoreCollapsed = collapsed;
12743             }
12744             return;
12745         }else if(this.restoreCollapsed){
12746             collapsed = this.restoreCollapsed;
12747             delete this.restoreCollapsed;
12748         }
12749
12750         var w = size.width, h = size.height,
12751             centerW = w, centerH = h, centerY = 0, centerX = 0,
12752             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
12753             b, m, totalWidth, totalHeight;
12754         if(!c && Ext.layout.BorderLayout.WARN !== false){
12755             throw 'No center region defined in BorderLayout ' + ct.id;
12756         }
12757
12758         if(n && n.isVisible()){
12759             b = n.getSize();
12760             m = n.getMargins();
12761             b.width = w - (m.left+m.right);
12762             b.x = m.left;
12763             b.y = m.top;
12764             centerY = b.height + b.y + m.bottom;
12765             centerH -= centerY;
12766             n.applyLayout(b);
12767         }
12768         if(s && s.isVisible()){
12769             b = s.getSize();
12770             m = s.getMargins();
12771             b.width = w - (m.left+m.right);
12772             b.x = m.left;
12773             totalHeight = (b.height + m.top + m.bottom);
12774             b.y = h - totalHeight + m.top;
12775             centerH -= totalHeight;
12776             s.applyLayout(b);
12777         }
12778         if(west && west.isVisible()){
12779             b = west.getSize();
12780             m = west.getMargins();
12781             b.height = centerH - (m.top+m.bottom);
12782             b.x = m.left;
12783             b.y = centerY + m.top;
12784             totalWidth = (b.width + m.left + m.right);
12785             centerX += totalWidth;
12786             centerW -= totalWidth;
12787             west.applyLayout(b);
12788         }
12789         if(e && e.isVisible()){
12790             b = e.getSize();
12791             m = e.getMargins();
12792             b.height = centerH - (m.top+m.bottom);
12793             totalWidth = (b.width + m.left + m.right);
12794             b.x = w - totalWidth + m.left;
12795             b.y = centerY + m.top;
12796             centerW -= totalWidth;
12797             e.applyLayout(b);
12798         }
12799         if(c){
12800             m = c.getMargins();
12801             var centerBox = {
12802                 x: centerX + m.left,
12803                 y: centerY + m.top,
12804                 width: centerW - (m.left+m.right),
12805                 height: centerH - (m.top+m.bottom)
12806             };
12807             c.applyLayout(centerBox);
12808         }
12809         if(collapsed){
12810             for(i = 0, len = collapsed.length; i < len; i++){
12811                 collapsed[i].collapse(false);
12812             }
12813         }
12814         if(Ext.isIE && Ext.isStrict){ 
12815             target.repaint();
12816         }
12817         
12818         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
12819             var ts = this.getLayoutTargetSize();
12820             if (ts.width != size.width || ts.height != size.height){
12821                 this.adjustmentPass = true;
12822                 this.onLayout(ct, target);
12823             }
12824         }
12825         delete this.adjustmentPass;
12826     },
12827
12828     destroy: function() {
12829         var r = ['north', 'south', 'east', 'west'], i, region;
12830         for (i = 0; i < r.length; i++) {
12831             region = this[r[i]];
12832             if(region){
12833                 if(region.destroy){
12834                     region.destroy();
12835                 }else if (region.split){
12836                     region.split.destroy(true);
12837                 }
12838             }
12839         }
12840         Ext.layout.BorderLayout.superclass.destroy.call(this);
12841     }
12842
12843     
12844 });
12845
12846
12847 Ext.layout.BorderLayout.Region = function(layout, config, pos){
12848     Ext.apply(this, config);
12849     this.layout = layout;
12850     this.position = pos;
12851     this.state = {};
12852     if(typeof this.margins == 'string'){
12853         this.margins = this.layout.parseMargins(this.margins);
12854     }
12855     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
12856     if(this.collapsible){
12857         if(typeof this.cmargins == 'string'){
12858             this.cmargins = this.layout.parseMargins(this.cmargins);
12859         }
12860         if(this.collapseMode == 'mini' && !this.cmargins){
12861             this.cmargins = {left:0,top:0,right:0,bottom:0};
12862         }else{
12863             this.cmargins = Ext.applyIf(this.cmargins || {},
12864                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
12865         }
12866     }
12867 };
12868
12869 Ext.layout.BorderLayout.Region.prototype = {
12870     
12871     
12872     
12873     
12874     
12875     
12876     collapsible : false,
12877     
12878     split:false,
12879     
12880     floatable: true,
12881     
12882     minWidth:50,
12883     
12884     minHeight:50,
12885
12886     
12887     defaultMargins : {left:0,top:0,right:0,bottom:0},
12888     
12889     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
12890     
12891     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
12892     floatingZIndex: 100,
12893
12894     
12895     isCollapsed : false,
12896
12897     
12898     
12899     
12900
12901     
12902     render : function(ct, p){
12903         this.panel = p;
12904         p.el.enableDisplayMode();
12905         this.targetEl = ct;
12906         this.el = p.el;
12907
12908         var gs = p.getState, ps = this.position;
12909         p.getState = function(){
12910             return Ext.apply(gs.call(p) || {}, this.state);
12911         }.createDelegate(this);
12912
12913         if(ps != 'center'){
12914             p.allowQueuedExpand = false;
12915             p.on({
12916                 beforecollapse: this.beforeCollapse,
12917                 collapse: this.onCollapse,
12918                 beforeexpand: this.beforeExpand,
12919                 expand: this.onExpand,
12920                 hide: this.onHide,
12921                 show: this.onShow,
12922                 scope: this
12923             });
12924             if(this.collapsible || this.floatable){
12925                 p.collapseEl = 'el';
12926                 p.slideAnchor = this.getSlideAnchor();
12927             }
12928             if(p.tools && p.tools.toggle){
12929                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
12930                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
12931             }
12932         }
12933     },
12934
12935     
12936     getCollapsedEl : function(){
12937         if(!this.collapsedEl){
12938             if(!this.toolTemplate){
12939                 var tt = new Ext.Template(
12940                      '<div class="x-tool x-tool-{id}">&#160;</div>'
12941                 );
12942                 tt.disableFormats = true;
12943                 tt.compile();
12944                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
12945             }
12946             this.collapsedEl = this.targetEl.createChild({
12947                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
12948                 id: this.panel.id + '-xcollapsed'
12949             });
12950             this.collapsedEl.enableDisplayMode('block');
12951
12952             if(this.collapseMode == 'mini'){
12953                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
12954                 this.miniCollapsedEl = this.collapsedEl.createChild({
12955                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
12956                 });
12957                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
12958                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12959                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
12960             }else {
12961                 if(this.collapsible !== false && !this.hideCollapseTool) {
12962                     var t = this.toolTemplate.append(
12963                             this.collapsedEl.dom,
12964                             {id:'expand-'+this.position}, true);
12965                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
12966                     t.on('click', this.onExpandClick, this, {stopEvent:true});
12967                 }
12968                 if(this.floatable !== false || this.titleCollapse){
12969                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12970                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
12971                 }
12972             }
12973         }
12974         return this.collapsedEl;
12975     },
12976
12977     
12978     onExpandClick : function(e){
12979         if(this.isSlid){
12980             this.panel.expand(false);
12981         }else{
12982             this.panel.expand();
12983         }
12984     },
12985
12986     
12987     onCollapseClick : function(e){
12988         this.panel.collapse();
12989     },
12990
12991     
12992     beforeCollapse : function(p, animate){
12993         this.lastAnim = animate;
12994         if(this.splitEl){
12995             this.splitEl.hide();
12996         }
12997         this.getCollapsedEl().show();
12998         var el = this.panel.getEl();
12999         this.originalZIndex = el.getStyle('z-index');
13000         el.setStyle('z-index', 100);
13001         this.isCollapsed = true;
13002         this.layout.layout();
13003     },
13004
13005     
13006     onCollapse : function(animate){
13007         this.panel.el.setStyle('z-index', 1);
13008         if(this.lastAnim === false || this.panel.animCollapse === false){
13009             this.getCollapsedEl().dom.style.visibility = 'visible';
13010         }else{
13011             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
13012         }
13013         this.state.collapsed = true;
13014         this.panel.saveState();
13015     },
13016
13017     
13018     beforeExpand : function(animate){
13019         if(this.isSlid){
13020             this.afterSlideIn();
13021         }
13022         var c = this.getCollapsedEl();
13023         this.el.show();
13024         if(this.position == 'east' || this.position == 'west'){
13025             this.panel.setSize(undefined, c.getHeight());
13026         }else{
13027             this.panel.setSize(c.getWidth(), undefined);
13028         }
13029         c.hide();
13030         c.dom.style.visibility = 'hidden';
13031         this.panel.el.setStyle('z-index', this.floatingZIndex);
13032     },
13033
13034     
13035     onExpand : function(){
13036         this.isCollapsed = false;
13037         if(this.splitEl){
13038             this.splitEl.show();
13039         }
13040         this.layout.layout();
13041         this.panel.el.setStyle('z-index', this.originalZIndex);
13042         this.state.collapsed = false;
13043         this.panel.saveState();
13044     },
13045
13046     
13047     collapseClick : function(e){
13048         if(this.isSlid){
13049            e.stopPropagation();
13050            this.slideIn();
13051         }else{
13052            e.stopPropagation();
13053            this.slideOut();
13054         }
13055     },
13056
13057     
13058     onHide : function(){
13059         if(this.isCollapsed){
13060             this.getCollapsedEl().hide();
13061         }else if(this.splitEl){
13062             this.splitEl.hide();
13063         }
13064     },
13065
13066     
13067     onShow : function(){
13068         if(this.isCollapsed){
13069             this.getCollapsedEl().show();
13070         }else if(this.splitEl){
13071             this.splitEl.show();
13072         }
13073     },
13074
13075     
13076     isVisible : function(){
13077         return !this.panel.hidden;
13078     },
13079
13080     
13081     getMargins : function(){
13082         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
13083     },
13084
13085     
13086     getSize : function(){
13087         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
13088     },
13089
13090     
13091     setPanel : function(panel){
13092         this.panel = panel;
13093     },
13094
13095     
13096     getMinWidth: function(){
13097         return this.minWidth;
13098     },
13099
13100     
13101     getMinHeight: function(){
13102         return this.minHeight;
13103     },
13104
13105     
13106     applyLayoutCollapsed : function(box){
13107         var ce = this.getCollapsedEl();
13108         ce.setLeftTop(box.x, box.y);
13109         ce.setSize(box.width, box.height);
13110     },
13111
13112     
13113     applyLayout : function(box){
13114         if(this.isCollapsed){
13115             this.applyLayoutCollapsed(box);
13116         }else{
13117             this.panel.setPosition(box.x, box.y);
13118             this.panel.setSize(box.width, box.height);
13119         }
13120     },
13121
13122     
13123     beforeSlide: function(){
13124         this.panel.beforeEffect();
13125     },
13126
13127     
13128     afterSlide : function(){
13129         this.panel.afterEffect();
13130     },
13131
13132     
13133     initAutoHide : function(){
13134         if(this.autoHide !== false){
13135             if(!this.autoHideHd){
13136                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
13137                 this.autoHideHd = {
13138                     "mouseout": function(e){
13139                         if(!e.within(this.el, true)){
13140                             this.autoHideSlideTask.delay(500);
13141                         }
13142                     },
13143                     "mouseover" : function(e){
13144                         this.autoHideSlideTask.cancel();
13145                     },
13146                     scope : this
13147                 };
13148             }
13149             this.el.on(this.autoHideHd);
13150             this.collapsedEl.on(this.autoHideHd);
13151         }
13152     },
13153
13154     
13155     clearAutoHide : function(){
13156         if(this.autoHide !== false){
13157             this.el.un("mouseout", this.autoHideHd.mouseout);
13158             this.el.un("mouseover", this.autoHideHd.mouseover);
13159             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
13160             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
13161         }
13162     },
13163
13164     
13165     clearMonitor : function(){
13166         Ext.getDoc().un("click", this.slideInIf, this);
13167     },
13168
13169     
13170     slideOut : function(){
13171         if(this.isSlid || this.el.hasActiveFx()){
13172             return;
13173         }
13174         this.isSlid = true;
13175         var ts = this.panel.tools, dh, pc;
13176         if(ts && ts.toggle){
13177             ts.toggle.hide();
13178         }
13179         this.el.show();
13180
13181         
13182         pc = this.panel.collapsed;
13183         this.panel.collapsed = false;
13184
13185         if(this.position == 'east' || this.position == 'west'){
13186             
13187             dh = this.panel.deferHeight;
13188             this.panel.deferHeight = false;
13189
13190             this.panel.setSize(undefined, this.collapsedEl.getHeight());
13191
13192             
13193             this.panel.deferHeight = dh;
13194         }else{
13195             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
13196         }
13197
13198         
13199         this.panel.collapsed = pc;
13200
13201         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
13202         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
13203         this.el.setStyle("z-index", this.floatingZIndex+2);
13204         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
13205         if(this.animFloat !== false){
13206             this.beforeSlide();
13207             this.el.slideIn(this.getSlideAnchor(), {
13208                 callback: function(){
13209                     this.afterSlide();
13210                     this.initAutoHide();
13211                     Ext.getDoc().on("click", this.slideInIf, this);
13212                 },
13213                 scope: this,
13214                 block: true
13215             });
13216         }else{
13217             this.initAutoHide();
13218              Ext.getDoc().on("click", this.slideInIf, this);
13219         }
13220     },
13221
13222     
13223     afterSlideIn : function(){
13224         this.clearAutoHide();
13225         this.isSlid = false;
13226         this.clearMonitor();
13227         this.el.setStyle("z-index", "");
13228         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
13229         this.el.dom.style.left = this.restoreLT[0];
13230         this.el.dom.style.top = this.restoreLT[1];
13231
13232         var ts = this.panel.tools;
13233         if(ts && ts.toggle){
13234             ts.toggle.show();
13235         }
13236     },
13237
13238     
13239     slideIn : function(cb){
13240         if(!this.isSlid || this.el.hasActiveFx()){
13241             Ext.callback(cb);
13242             return;
13243         }
13244         this.isSlid = false;
13245         if(this.animFloat !== false){
13246             this.beforeSlide();
13247             this.el.slideOut(this.getSlideAnchor(), {
13248                 callback: function(){
13249                     this.el.hide();
13250                     this.afterSlide();
13251                     this.afterSlideIn();
13252                     Ext.callback(cb);
13253                 },
13254                 scope: this,
13255                 block: true
13256             });
13257         }else{
13258             this.el.hide();
13259             this.afterSlideIn();
13260         }
13261     },
13262
13263     
13264     slideInIf : function(e){
13265         if(!e.within(this.el)){
13266             this.slideIn();
13267         }
13268     },
13269
13270     
13271     anchors : {
13272         "west" : "left",
13273         "east" : "right",
13274         "north" : "top",
13275         "south" : "bottom"
13276     },
13277
13278     
13279     sanchors : {
13280         "west" : "l",
13281         "east" : "r",
13282         "north" : "t",
13283         "south" : "b"
13284     },
13285
13286     
13287     canchors : {
13288         "west" : "tl-tr",
13289         "east" : "tr-tl",
13290         "north" : "tl-bl",
13291         "south" : "bl-tl"
13292     },
13293
13294     
13295     getAnchor : function(){
13296         return this.anchors[this.position];
13297     },
13298
13299     
13300     getCollapseAnchor : function(){
13301         return this.canchors[this.position];
13302     },
13303
13304     
13305     getSlideAnchor : function(){
13306         return this.sanchors[this.position];
13307     },
13308
13309     
13310     getAlignAdj : function(){
13311         var cm = this.cmargins;
13312         switch(this.position){
13313             case "west":
13314                 return [0, 0];
13315             break;
13316             case "east":
13317                 return [0, 0];
13318             break;
13319             case "north":
13320                 return [0, 0];
13321             break;
13322             case "south":
13323                 return [0, 0];
13324             break;
13325         }
13326     },
13327
13328     
13329     getExpandAdj : function(){
13330         var c = this.collapsedEl, cm = this.cmargins;
13331         switch(this.position){
13332             case "west":
13333                 return [-(cm.right+c.getWidth()+cm.left), 0];
13334             break;
13335             case "east":
13336                 return [cm.right+c.getWidth()+cm.left, 0];
13337             break;
13338             case "north":
13339                 return [0, -(cm.top+cm.bottom+c.getHeight())];
13340             break;
13341             case "south":
13342                 return [0, cm.top+cm.bottom+c.getHeight()];
13343             break;
13344         }
13345     },
13346
13347     destroy : function(){
13348         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
13349             this.autoHideSlideTask.cancel();
13350         }
13351         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
13352     }
13353 };
13354
13355
13356 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
13357     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
13358     
13359     this.applyLayout = this.applyFns[pos];
13360 };
13361
13362 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
13363     
13364     
13365     splitTip : "Drag to resize.",
13366     
13367     collapsibleSplitTip : "Drag to resize. Double click to hide.",
13368     
13369     useSplitTips : false,
13370
13371     
13372     splitSettings : {
13373         north : {
13374             orientation: Ext.SplitBar.VERTICAL,
13375             placement: Ext.SplitBar.TOP,
13376             maxFn : 'getVMaxSize',
13377             minProp: 'minHeight',
13378             maxProp: 'maxHeight'
13379         },
13380         south : {
13381             orientation: Ext.SplitBar.VERTICAL,
13382             placement: Ext.SplitBar.BOTTOM,
13383             maxFn : 'getVMaxSize',
13384             minProp: 'minHeight',
13385             maxProp: 'maxHeight'
13386         },
13387         east : {
13388             orientation: Ext.SplitBar.HORIZONTAL,
13389             placement: Ext.SplitBar.RIGHT,
13390             maxFn : 'getHMaxSize',
13391             minProp: 'minWidth',
13392             maxProp: 'maxWidth'
13393         },
13394         west : {
13395             orientation: Ext.SplitBar.HORIZONTAL,
13396             placement: Ext.SplitBar.LEFT,
13397             maxFn : 'getHMaxSize',
13398             minProp: 'minWidth',
13399             maxProp: 'maxWidth'
13400         }
13401     },
13402
13403     
13404     applyFns : {
13405         west : function(box){
13406             if(this.isCollapsed){
13407                 return this.applyLayoutCollapsed(box);
13408             }
13409             var sd = this.splitEl.dom, s = sd.style;
13410             this.panel.setPosition(box.x, box.y);
13411             var sw = sd.offsetWidth;
13412             s.left = (box.x+box.width-sw)+'px';
13413             s.top = (box.y)+'px';
13414             s.height = Math.max(0, box.height)+'px';
13415             this.panel.setSize(box.width-sw, box.height);
13416         },
13417         east : function(box){
13418             if(this.isCollapsed){
13419                 return this.applyLayoutCollapsed(box);
13420             }
13421             var sd = this.splitEl.dom, s = sd.style;
13422             var sw = sd.offsetWidth;
13423             this.panel.setPosition(box.x+sw, box.y);
13424             s.left = (box.x)+'px';
13425             s.top = (box.y)+'px';
13426             s.height = Math.max(0, box.height)+'px';
13427             this.panel.setSize(box.width-sw, box.height);
13428         },
13429         north : function(box){
13430             if(this.isCollapsed){
13431                 return this.applyLayoutCollapsed(box);
13432             }
13433             var sd = this.splitEl.dom, s = sd.style;
13434             var sh = sd.offsetHeight;
13435             this.panel.setPosition(box.x, box.y);
13436             s.left = (box.x)+'px';
13437             s.top = (box.y+box.height-sh)+'px';
13438             s.width = Math.max(0, box.width)+'px';
13439             this.panel.setSize(box.width, box.height-sh);
13440         },
13441         south : function(box){
13442             if(this.isCollapsed){
13443                 return this.applyLayoutCollapsed(box);
13444             }
13445             var sd = this.splitEl.dom, s = sd.style;
13446             var sh = sd.offsetHeight;
13447             this.panel.setPosition(box.x, box.y+sh);
13448             s.left = (box.x)+'px';
13449             s.top = (box.y)+'px';
13450             s.width = Math.max(0, box.width)+'px';
13451             this.panel.setSize(box.width, box.height-sh);
13452         }
13453     },
13454
13455     
13456     render : function(ct, p){
13457         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
13458
13459         var ps = this.position;
13460
13461         this.splitEl = ct.createChild({
13462             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
13463             id: this.panel.id + '-xsplit'
13464         });
13465
13466         if(this.collapseMode == 'mini'){
13467             this.miniSplitEl = this.splitEl.createChild({
13468                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
13469             });
13470             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
13471             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
13472         }
13473
13474         var s = this.splitSettings[ps];
13475
13476         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
13477         this.split.tickSize = this.tickSize;
13478         this.split.placement = s.placement;
13479         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
13480         this.split.minSize = this.minSize || this[s.minProp];
13481         this.split.on("beforeapply", this.onSplitMove, this);
13482         this.split.useShim = this.useShim === true;
13483         this.maxSize = this.maxSize || this[s.maxProp];
13484
13485         if(p.hidden){
13486             this.splitEl.hide();
13487         }
13488
13489         if(this.useSplitTips){
13490             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
13491         }
13492         if(this.collapsible){
13493             this.splitEl.on("dblclick", this.onCollapseClick,  this);
13494         }
13495     },
13496
13497     
13498     getSize : function(){
13499         if(this.isCollapsed){
13500             return this.collapsedEl.getSize();
13501         }
13502         var s = this.panel.getSize();
13503         if(this.position == 'north' || this.position == 'south'){
13504             s.height += this.splitEl.dom.offsetHeight;
13505         }else{
13506             s.width += this.splitEl.dom.offsetWidth;
13507         }
13508         return s;
13509     },
13510
13511     
13512     getHMaxSize : function(){
13513          var cmax = this.maxSize || 10000;
13514          var center = this.layout.center;
13515          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
13516     },
13517
13518     
13519     getVMaxSize : function(){
13520         var cmax = this.maxSize || 10000;
13521         var center = this.layout.center;
13522         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
13523     },
13524
13525     
13526     onSplitMove : function(split, newSize){
13527         var s = this.panel.getSize();
13528         this.lastSplitSize = newSize;
13529         if(this.position == 'north' || this.position == 'south'){
13530             this.panel.setSize(s.width, newSize);
13531             this.state.height = newSize;
13532         }else{
13533             this.panel.setSize(newSize, s.height);
13534             this.state.width = newSize;
13535         }
13536         this.layout.layout();
13537         this.panel.saveState();
13538         return false;
13539     },
13540
13541     
13542     getSplitBar : function(){
13543         return this.split;
13544     },
13545
13546     
13547     destroy : function() {
13548         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
13549         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
13550     }
13551 });
13552
13553 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
13554 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
13555
13556     
13557     labelSeparator : ':',
13558
13559     
13560
13561     
13562     trackLabels: false,
13563
13564     type: 'form',
13565
13566     onRemove: function(c){
13567         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
13568         if(this.trackLabels){
13569             c.un('show', this.onFieldShow, this);
13570             c.un('hide', this.onFieldHide, this);
13571         }
13572         
13573         var el = c.getPositionEl(),
13574             ct = c.getItemCt && c.getItemCt();
13575         if (c.rendered && ct) {
13576             if (el && el.dom) {
13577                 el.insertAfter(ct);
13578             }
13579             Ext.destroy(ct);
13580             Ext.destroyMembers(c, 'label', 'itemCt');
13581             if (c.customItemCt) {
13582                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
13583             }
13584         }
13585     },
13586
13587     
13588     setContainer : function(ct){
13589         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
13590         if(ct.labelAlign){
13591             ct.addClass('x-form-label-'+ct.labelAlign);
13592         }
13593
13594         if(ct.hideLabels){
13595             Ext.apply(this, {
13596                 labelStyle: 'display:none',
13597                 elementStyle: 'padding-left:0;',
13598                 labelAdjust: 0
13599             });
13600         }else{
13601             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
13602             ct.labelWidth = ct.labelWidth || 100;
13603             if(Ext.isNumber(ct.labelWidth)){
13604                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
13605                 Ext.apply(this, {
13606                     labelAdjust: ct.labelWidth + pad,
13607                     labelStyle: 'width:' + ct.labelWidth + 'px;',
13608                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
13609                 });
13610             }
13611             if(ct.labelAlign == 'top'){
13612                 Ext.apply(this, {
13613                     labelStyle: 'width:auto;',
13614                     labelAdjust: 0,
13615                     elementStyle: 'padding-left:0;'
13616                 });
13617             }
13618         }
13619     },
13620
13621     
13622     isHide: function(c){
13623         return c.hideLabel || this.container.hideLabels;
13624     },
13625
13626     onFieldShow: function(c){
13627         c.getItemCt().removeClass('x-hide-' + c.hideMode);
13628
13629         
13630         if (c.isComposite) {
13631             c.doLayout();
13632         }
13633     },
13634
13635     onFieldHide: function(c){
13636         c.getItemCt().addClass('x-hide-' + c.hideMode);
13637     },
13638
13639     
13640     getLabelStyle: function(s){
13641         var ls = '', items = [this.labelStyle, s];
13642         for (var i = 0, len = items.length; i < len; ++i){
13643             if (items[i]){
13644                 ls += items[i];
13645                 if (ls.substr(-1, 1) != ';'){
13646                     ls += ';';
13647                 }
13648             }
13649         }
13650         return ls;
13651     },
13652
13653     
13654
13655     
13656     renderItem : function(c, position, target){
13657         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
13658             var args = this.getTemplateArgs(c);
13659             if(Ext.isNumber(position)){
13660                 position = target.dom.childNodes[position] || null;
13661             }
13662             if(position){
13663                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
13664             }else{
13665                 c.itemCt = this.fieldTpl.append(target, args, true);
13666             }
13667             if(!c.getItemCt){
13668                 
13669                 
13670                 Ext.apply(c, {
13671                     getItemCt: function(){
13672                         return c.itemCt;
13673                     },
13674                     customItemCt: true
13675                 });
13676             }
13677             c.label = c.getItemCt().child('label.x-form-item-label');
13678             if(!c.rendered){
13679                 c.render('x-form-el-' + c.id);
13680             }else if(!this.isValidParent(c, target)){
13681                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
13682             }
13683             if(this.trackLabels){
13684                 if(c.hidden){
13685                     this.onFieldHide(c);
13686                 }
13687                 c.on({
13688                     scope: this,
13689                     show: this.onFieldShow,
13690                     hide: this.onFieldHide
13691                 });
13692             }
13693             this.configureItem(c);
13694         }else {
13695             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
13696         }
13697     },
13698
13699     
13700     getTemplateArgs: function(field) {
13701         var noLabelSep = !field.fieldLabel || field.hideLabel;
13702
13703         return {
13704             id            : field.id,
13705             label         : field.fieldLabel,
13706             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
13707             clearCls      : field.clearCls || 'x-form-clear-left',
13708             labelStyle    : this.getLabelStyle(field.labelStyle),
13709             elementStyle  : this.elementStyle || '',
13710             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
13711         };
13712     },
13713
13714     
13715     adjustWidthAnchor: function(value, c){
13716         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
13717             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
13718             return value - this.labelAdjust + (adjust ? -3 : 0);
13719         }
13720         return value;
13721     },
13722
13723     adjustHeightAnchor : function(value, c){
13724         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
13725             return value - c.label.getHeight();
13726         }
13727         return value;
13728     },
13729
13730     
13731     isValidParent : function(c, target){
13732         return target && this.container.getEl().contains(c.getPositionEl());
13733     }
13734
13735     
13736 });
13737
13738 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
13739
13740 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
13741     
13742     fill : true,
13743     
13744     autoWidth : true,
13745     
13746     titleCollapse : true,
13747     
13748     hideCollapseTool : false,
13749     
13750     collapseFirst : false,
13751     
13752     animate : false,
13753     
13754     sequence : false,
13755     
13756     activeOnTop : false,
13757
13758     type: 'accordion',
13759
13760     renderItem : function(c){
13761         if(this.animate === false){
13762             c.animCollapse = false;
13763         }
13764         c.collapsible = true;
13765         if(this.autoWidth){
13766             c.autoWidth = true;
13767         }
13768         if(this.titleCollapse){
13769             c.titleCollapse = true;
13770         }
13771         if(this.hideCollapseTool){
13772             c.hideCollapseTool = true;
13773         }
13774         if(this.collapseFirst !== undefined){
13775             c.collapseFirst = this.collapseFirst;
13776         }
13777         if(!this.activeItem && !c.collapsed){
13778             this.setActiveItem(c, true);
13779         }else if(this.activeItem && this.activeItem != c){
13780             c.collapsed = true;
13781         }
13782         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
13783         c.header.addClass('x-accordion-hd');
13784         c.on('beforeexpand', this.beforeExpand, this);
13785     },
13786
13787     onRemove: function(c){
13788         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
13789         if(c.rendered){
13790             c.header.removeClass('x-accordion-hd');
13791         }
13792         c.un('beforeexpand', this.beforeExpand, this);
13793     },
13794
13795     
13796     beforeExpand : function(p, anim){
13797         var ai = this.activeItem;
13798         if(ai){
13799             if(this.sequence){
13800                 delete this.activeItem;
13801                 if (!ai.collapsed){
13802                     ai.collapse({callback:function(){
13803                         p.expand(anim || true);
13804                     }, scope: this});
13805                     return false;
13806                 }
13807             }else{
13808                 ai.collapse(this.animate);
13809             }
13810         }
13811         this.setActive(p);
13812         if(this.activeOnTop){
13813             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
13814         }
13815         
13816         this.layout();
13817     },
13818
13819     
13820     setItemSize : function(item, size){
13821         if(this.fill && item){
13822             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
13823             
13824             for (i = 0; i < len; i++) {
13825                 if((p = ct[i]) != item && !p.hidden){
13826                     hh += p.header.getHeight();
13827                 }
13828             };
13829             
13830             size.height -= hh;
13831             
13832             
13833             item.setSize(size);
13834         }
13835     },
13836
13837     
13838     setActiveItem : function(item){
13839         this.setActive(item, true);
13840     },
13841
13842     
13843     setActive : function(item, expand){
13844         var ai = this.activeItem;
13845         item = this.container.getComponent(item);
13846         if(ai != item){
13847             if(item.rendered && item.collapsed && expand){
13848                 item.expand();
13849             }else{
13850                 if(ai){
13851                    ai.fireEvent('deactivate', ai);
13852                 }
13853                 this.activeItem = item;
13854                 item.fireEvent('activate', item);
13855             }
13856         }
13857     }
13858 });
13859 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
13860
13861
13862 Ext.layout.Accordion = Ext.layout.AccordionLayout;
13863 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
13864     
13865
13866     
13867     monitorResize:false,
13868
13869     type: 'table',
13870
13871     targetCls: 'x-table-layout-ct',
13872
13873     
13874     tableAttrs:null,
13875
13876     
13877     setContainer : function(ct){
13878         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
13879
13880         this.currentRow = 0;
13881         this.currentColumn = 0;
13882         this.cells = [];
13883     },
13884     
13885     
13886     onLayout : function(ct, target){
13887         var cs = ct.items.items, len = cs.length, c, i;
13888
13889         if(!this.table){
13890             target.addClass('x-table-layout-ct');
13891
13892             this.table = target.createChild(
13893                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
13894         }
13895         this.renderAll(ct, target);
13896     },
13897
13898     
13899     getRow : function(index){
13900         var row = this.table.tBodies[0].childNodes[index];
13901         if(!row){
13902             row = document.createElement('tr');
13903             this.table.tBodies[0].appendChild(row);
13904         }
13905         return row;
13906     },
13907
13908     
13909     getNextCell : function(c){
13910         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
13911         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
13912         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
13913             if(!this.cells[rowIndex]){
13914                 this.cells[rowIndex] = [];
13915             }
13916             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
13917                 this.cells[rowIndex][colIndex] = true;
13918             }
13919         }
13920         var td = document.createElement('td');
13921         if(c.cellId){
13922             td.id = c.cellId;
13923         }
13924         var cls = 'x-table-layout-cell';
13925         if(c.cellCls){
13926             cls += ' ' + c.cellCls;
13927         }
13928         td.className = cls;
13929         if(c.colspan){
13930             td.colSpan = c.colspan;
13931         }
13932         if(c.rowspan){
13933             td.rowSpan = c.rowspan;
13934         }
13935         this.getRow(curRow).appendChild(td);
13936         return td;
13937     },
13938
13939     
13940     getNextNonSpan: function(colIndex, rowIndex){
13941         var cols = this.columns;
13942         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
13943             if(cols && colIndex >= cols){
13944                 rowIndex++;
13945                 colIndex = 0;
13946             }else{
13947                 colIndex++;
13948             }
13949         }
13950         return [colIndex, rowIndex];
13951     },
13952
13953     
13954     renderItem : function(c, position, target){
13955         
13956         if(!this.table){
13957             this.table = target.createChild(
13958                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
13959         }
13960         if(c && !c.rendered){
13961             c.render(this.getNextCell(c));
13962             this.configureItem(c, position);
13963         }else if(c && !this.isValidParent(c, target)){
13964             var container = this.getNextCell(c);
13965             container.insertBefore(c.getPositionEl().dom, null);
13966             c.container = Ext.get(container);
13967             this.configureItem(c, position);
13968         }
13969     },
13970
13971     
13972     isValidParent : function(c, target){
13973         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
13974     }
13975
13976     
13977 });
13978
13979 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
13980 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
13981
13982     extraCls: 'x-abs-layout-item',
13983
13984     type: 'absolute',
13985
13986     onLayout : function(ct, target){
13987         target.position();
13988         this.paddingLeft = target.getPadding('l');
13989         this.paddingTop = target.getPadding('t');
13990         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
13991     },
13992
13993     
13994     adjustWidthAnchor : function(value, comp){
13995         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
13996     },
13997
13998     
13999     adjustHeightAnchor : function(value, comp){
14000         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
14001     }
14002     
14003 });
14004 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
14005
14006 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
14007     
14008     defaultMargins : {left:0,top:0,right:0,bottom:0},
14009     
14010     padding : '0',
14011     
14012     pack : 'start',
14013
14014     
14015     monitorResize : true,
14016     type: 'box',
14017     scrollOffset : 0,
14018     extraCls : 'x-box-item',
14019     targetCls : 'x-box-layout-ct',
14020     innerCls : 'x-box-inner',
14021
14022     constructor : function(config){
14023         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
14024
14025         if (Ext.isString(this.defaultMargins)) {
14026             this.defaultMargins = this.parseMargins(this.defaultMargins);
14027         }
14028     },
14029
14030     
14031     onLayout: function(container, target) {
14032         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
14033
14034         var items = this.getVisibleItems(container),
14035             tSize = this.getLayoutTargetSize();
14036
14037         
14038         this.layoutTargetLastSize = tSize;
14039
14040         
14041         this.childBoxCache = this.calculateChildBoxes(items, tSize);
14042
14043         this.updateInnerCtSize(tSize, this.childBoxCache);
14044         this.updateChildBoxes(this.childBoxCache.boxes);
14045
14046         
14047         this.handleTargetOverflow(tSize, container, target);
14048     },
14049
14050     
14051     updateChildBoxes: function(boxes) {
14052         for (var i = 0, length = boxes.length; i < length; i++) {
14053             var box  = boxes[i],
14054                 comp = box.component;
14055
14056             if (box.dirtySize) {
14057                 comp.setSize(box.width, box.height);
14058             }
14059             
14060             if (isNaN(box.left) || isNaN(box.top)) {
14061                 continue;
14062             }
14063             comp.setPosition(box.left, box.top);
14064         }
14065     },
14066
14067     
14068     updateInnerCtSize: Ext.emptyFn,
14069
14070     
14071     handleTargetOverflow: function(previousTargetSize, container, target) {
14072         var overflow = target.getStyle('overflow');
14073
14074         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
14075             var newTargetSize = this.getLayoutTargetSize();
14076             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
14077                 this.adjustmentPass = true;
14078                 this.onLayout(container, target);
14079             }
14080         }
14081
14082         delete this.adjustmentPass;
14083     },
14084
14085     
14086     isValidParent : function(c, target){
14087         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
14088     },
14089
14090     
14091     getVisibleItems: function(ct) {
14092         var ct  = ct || this.container,
14093             t   = ct.getLayoutTarget(),
14094             cti = ct.items.items,
14095             len = cti.length,
14096
14097             i, c, items = [];
14098
14099         for (i = 0; i < len; i++) {
14100             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
14101                 items.push(c);
14102             }
14103         }
14104
14105         return items;
14106     },
14107
14108     
14109     renderAll : function(ct, target){
14110         if(!this.innerCt){
14111             
14112             
14113             this.innerCt = target.createChild({cls:this.innerCls});
14114             this.padding = this.parseMargins(this.padding);
14115         }
14116         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
14117     },
14118
14119     getLayoutTargetSize : function(){
14120         var target = this.container.getLayoutTarget(), ret;
14121         if (target) {
14122             ret = target.getViewSize();
14123
14124             
14125             
14126             
14127             if (Ext.isIE && Ext.isStrict && ret.width == 0){
14128                 ret =  target.getStyleSize();
14129             }
14130
14131             ret.width -= target.getPadding('lr');
14132             ret.height -= target.getPadding('tb');
14133         }
14134         return ret;
14135     },
14136
14137     
14138     renderItem : function(c){
14139         if(Ext.isString(c.margins)){
14140             c.margins = this.parseMargins(c.margins);
14141         }else if(!c.margins){
14142             c.margins = this.defaultMargins;
14143         }
14144         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
14145     }
14146 });
14147
14148
14149 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
14150     
14151     align : 'left', 
14152     type: 'vbox',
14153
14154     
14155
14156     
14157
14158     
14159     updateInnerCtSize: function(tSize, calcs) {
14160         var innerCtHeight = tSize.height,
14161             innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
14162
14163         if (this.align == 'stretch') {
14164             innerCtWidth = tSize.width;
14165         } else if (this.align == 'center') {
14166             innerCtWidth = Math.max(tSize.width, innerCtWidth);
14167         }
14168
14169         
14170         
14171         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
14172     },
14173
14174     
14175     calculateChildBoxes: function(visibleItems, targetSize) {
14176         var visibleCount = visibleItems.length,
14177
14178             padding      = this.padding,
14179             topOffset    = padding.top,
14180             leftOffset   = padding.left,
14181             paddingVert  = topOffset  + padding.bottom,
14182             paddingHoriz = leftOffset + padding.right,
14183
14184             width        = targetSize.width - this.scrollOffset,
14185             height       = targetSize.height,
14186             availWidth   = Math.max(0, width - paddingHoriz),
14187
14188             isStart      = this.pack == 'start',
14189             isCenter     = this.pack == 'center',
14190             isEnd        = this.pack == 'end',
14191
14192             nonFlexHeight= 0,
14193             maxWidth     = 0,
14194             totalFlex    = 0,
14195
14196             
14197             boxes        = [],
14198
14199             
14200             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
14201
14202             
14203             for (i = 0; i < visibleCount; i++) {
14204                 child = visibleItems[i];
14205                 childHeight = child.height;
14206                 childWidth  = child.width;
14207                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
14208
14209
14210                 
14211                 if (!Ext.isNumber(childHeight)) {
14212
14213                     
14214                     if (child.flex && !childHeight) {
14215                         totalFlex += child.flex;
14216
14217                     
14218                     } else {
14219                         
14220                         
14221                         if (!childHeight && canLayout) {
14222                             child.doLayout();
14223                         }
14224
14225                         childSize = child.getSize();
14226                         childWidth = childSize.width;
14227                         childHeight = childSize.height;
14228                     }
14229                 }
14230
14231                 childMargins = child.margins;
14232
14233                 nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
14234
14235                 
14236                 if (!Ext.isNumber(childWidth)) {
14237                     if (canLayout) {
14238                         child.doLayout();
14239                     }
14240                     childWidth = child.getWidth();
14241                 }
14242
14243                 maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
14244
14245                 
14246                 boxes.push({
14247                     component: child,
14248                     height   : childHeight || undefined,
14249                     width    : childWidth || undefined
14250                 });
14251             }
14252
14253             
14254             var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
14255
14256             if (isCenter) {
14257                 topOffset += availableHeight / 2;
14258             } else if (isEnd) {
14259                 topOffset += availableHeight;
14260             }
14261
14262             
14263             var remainingHeight = availableHeight,
14264                 remainingFlex   = totalFlex;
14265
14266             
14267             for (i = 0; i < visibleCount; i++) {
14268                 child = visibleItems[i];
14269                 calcs = boxes[i];
14270
14271                 childMargins = child.margins;
14272                 horizMargins = childMargins.left + childMargins.right;
14273
14274                 topOffset   += childMargins.top;
14275
14276                 if (isStart && child.flex && !child.height) {
14277                     flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
14278                     remainingHeight -= flexedHeight;
14279                     remainingFlex   -= child.flex;
14280
14281                     calcs.height = flexedHeight;
14282                     calcs.dirtySize = true;
14283                 }
14284
14285                 calcs.left = leftOffset + childMargins.left;
14286                 calcs.top  = topOffset;
14287
14288                 switch (this.align) {
14289                     case 'stretch':
14290                         stretchWidth = availWidth - horizMargins;
14291                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
14292                         calcs.dirtySize = true;
14293                         break;
14294                     case 'stretchmax':
14295                         stretchWidth = maxWidth - horizMargins;
14296                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
14297                         calcs.dirtySize = true;
14298                         break;
14299                     case 'center':
14300                         var diff = availWidth - calcs.width - horizMargins;
14301                         if (diff > 0) {
14302                             calcs.left = leftOffset + horizMargins + (diff / 2);
14303                         }
14304                 }
14305
14306                 topOffset += calcs.height + childMargins.bottom;
14307             }
14308
14309         return {
14310             boxes: boxes,
14311             meta : {
14312                 maxWidth: maxWidth
14313             }
14314         };
14315     }
14316 });
14317
14318 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
14319
14320
14321 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
14322     
14323     align: 'top', 
14324
14325     type : 'hbox',
14326
14327     
14328     updateInnerCtSize: function(tSize, calcs) {
14329         var innerCtWidth  = tSize.width,
14330             innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
14331
14332         if (this.align == 'stretch') {
14333             innerCtHeight = tSize.height;
14334         } else if (this.align == 'middle') {
14335             innerCtHeight = Math.max(tSize.height, innerCtHeight);
14336         }
14337
14338         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
14339     },
14340
14341     
14342     
14343
14344     
14345     calculateChildBoxes: function(visibleItems, targetSize) {
14346         var visibleCount = visibleItems.length,
14347
14348             padding      = this.padding,
14349             topOffset    = padding.top,
14350             leftOffset   = padding.left,
14351             paddingVert  = topOffset  + padding.bottom,
14352             paddingHoriz = leftOffset + padding.right,
14353
14354             width        = targetSize.width - this.scrollOffset,
14355             height       = targetSize.height,
14356             availHeight  = Math.max(0, height - paddingVert),
14357
14358             isStart      = this.pack == 'start',
14359             isCenter     = this.pack == 'center',
14360             isEnd        = this.pack == 'end',
14361             
14362
14363             nonFlexWidth = 0,
14364             maxHeight    = 0,
14365             totalFlex    = 0,
14366
14367             
14368             boxes        = [],
14369
14370             
14371             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
14372
14373             
14374             for (i = 0; i < visibleCount; i++) {
14375                 child       = visibleItems[i];
14376                 childHeight = child.height;
14377                 childWidth  = child.width;
14378                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
14379
14380                 
14381                 if (!Ext.isNumber(childWidth)) {
14382
14383                     
14384                     if (child.flex && !childWidth) {
14385                         totalFlex += child.flex;
14386
14387                     
14388                     } else {
14389                         
14390                         
14391                         if (!childWidth && canLayout) {
14392                             child.doLayout();
14393                         }
14394
14395                         childSize   = child.getSize();
14396                         childWidth  = childSize.width;
14397                         childHeight = childSize.height;
14398                     }
14399                 }
14400
14401                 childMargins = child.margins;
14402
14403                 nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
14404
14405                 
14406                 if (!Ext.isNumber(childHeight)) {
14407                     if (canLayout) {
14408                         child.doLayout();
14409                     }
14410                     childHeight = child.getHeight();
14411                 }
14412
14413                 maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
14414
14415                 
14416                 boxes.push({
14417                     component: child,
14418                     height   : childHeight || undefined,
14419                     width    : childWidth || undefined
14420                 });
14421             }
14422
14423             
14424             var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
14425
14426             if (isCenter) {
14427                 leftOffset += availableWidth / 2;
14428             } else if (isEnd) {
14429                 leftOffset += availableWidth;
14430             }
14431
14432             
14433             var remainingWidth = availableWidth,
14434                 remainingFlex  = totalFlex;
14435
14436             
14437             for (i = 0; i < visibleCount; i++) {
14438                 child = visibleItems[i];
14439                 calcs = boxes[i];
14440
14441                 childMargins = child.margins;
14442                 vertMargins  = childMargins.top + childMargins.bottom;
14443
14444                 leftOffset  += childMargins.left;
14445
14446                 if (isStart && child.flex && !child.width) {
14447                     flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
14448                     remainingWidth -= flexedWidth;
14449                     remainingFlex  -= child.flex;
14450
14451                     calcs.width = flexedWidth;
14452                     calcs.dirtySize = true;
14453                 }
14454
14455                 calcs.left = leftOffset;
14456                 calcs.top  = topOffset + childMargins.top;
14457
14458                 switch (this.align) {
14459                     case 'stretch':
14460                         stretchHeight = availHeight - vertMargins;
14461                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
14462                         calcs.dirtySize = true;
14463                         break;
14464                     case 'stretchmax':
14465                         stretchHeight = maxHeight - vertMargins;
14466                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
14467                         calcs.dirtySize = true;
14468                         break;
14469                     case 'middle':
14470                         var diff = availHeight - calcs.height - vertMargins;
14471                         if (diff > 0) {
14472                             calcs.top = topOffset + vertMargins + (diff / 2);
14473                         }
14474                 }
14475                 leftOffset += calcs.width + childMargins.right;
14476             }
14477
14478         return {
14479             boxes: boxes,
14480             meta : {
14481                 maxHeight: maxHeight
14482             }
14483         };
14484     }
14485 });
14486
14487 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
14488
14489 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
14490     monitorResize : true,
14491
14492     type: 'toolbar',
14493
14494     
14495     triggerWidth: 18,
14496
14497     
14498     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
14499
14500     
14501     lastOverflow: false,
14502
14503     
14504     tableHTML: [
14505         '<table cellspacing="0" class="x-toolbar-ct">',
14506             '<tbody>',
14507                 '<tr>',
14508                     '<td class="x-toolbar-left" align="{0}">',
14509                         '<table cellspacing="0">',
14510                             '<tbody>',
14511                                 '<tr class="x-toolbar-left-row"></tr>',
14512                             '</tbody>',
14513                         '</table>',
14514                     '</td>',
14515                     '<td class="x-toolbar-right" align="right">',
14516                         '<table cellspacing="0" class="x-toolbar-right-ct">',
14517                             '<tbody>',
14518                                 '<tr>',
14519                                     '<td>',
14520                                         '<table cellspacing="0">',
14521                                             '<tbody>',
14522                                                 '<tr class="x-toolbar-right-row"></tr>',
14523                                             '</tbody>',
14524                                         '</table>',
14525                                     '</td>',
14526                                     '<td>',
14527                                         '<table cellspacing="0">',
14528                                             '<tbody>',
14529                                                 '<tr class="x-toolbar-extras-row"></tr>',
14530                                             '</tbody>',
14531                                         '</table>',
14532                                     '</td>',
14533                                 '</tr>',
14534                             '</tbody>',
14535                         '</table>',
14536                     '</td>',
14537                 '</tr>',
14538             '</tbody>',
14539         '</table>'
14540     ].join(""),
14541
14542     
14543     onLayout : function(ct, target) {
14544         
14545         if (!this.leftTr) {
14546             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
14547
14548             target.addClass('x-toolbar-layout-ct');
14549             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
14550
14551             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
14552             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
14553             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
14554
14555             if (this.hiddenItem == undefined) {
14556                 
14557                 this.hiddenItems = [];
14558             }
14559         }
14560
14561         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
14562             items    = ct.items.items,
14563             position = 0;
14564
14565         
14566         for (var i = 0, len = items.length, c; i < len; i++, position++) {
14567             c = items[i];
14568
14569             if (c.isFill) {
14570                 side   = this.rightTr;
14571                 position = -1;
14572             } else if (!c.rendered) {
14573                 c.render(this.insertCell(c, side, position));
14574             } else {
14575                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
14576                     var td = this.insertCell(c, side, position);
14577                     td.appendChild(c.getPositionEl().dom);
14578                     c.container = Ext.get(td);
14579                 }
14580             }
14581         }
14582
14583         
14584         this.cleanup(this.leftTr);
14585         this.cleanup(this.rightTr);
14586         this.cleanup(this.extrasTr);
14587         this.fitToSize(target);
14588     },
14589
14590     
14591     cleanup : function(el) {
14592         var cn = el.childNodes, i, c;
14593
14594         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
14595             if (!c.firstChild) {
14596                 el.removeChild(c);
14597             }
14598         }
14599     },
14600
14601     
14602     insertCell : function(c, target, position) {
14603         var td = document.createElement('td');
14604         td.className = 'x-toolbar-cell';
14605
14606         target.insertBefore(td, target.childNodes[position] || null);
14607
14608         return td;
14609     },
14610
14611     
14612     hideItem : function(item) {
14613         this.hiddenItems.push(item);
14614
14615         item.xtbHidden = true;
14616         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
14617         item.hide();
14618     },
14619
14620     
14621     unhideItem : function(item) {
14622         item.show();
14623         item.xtbHidden = false;
14624         this.hiddenItems.remove(item);
14625     },
14626
14627     
14628     getItemWidth : function(c) {
14629         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
14630     },
14631
14632     
14633     fitToSize : function(target) {
14634         if (this.container.enableOverflow === false) {
14635             return;
14636         }
14637
14638         var width       = target.dom.clientWidth,
14639             tableWidth  = target.dom.firstChild.offsetWidth,
14640             clipWidth   = width - this.triggerWidth,
14641             lastWidth   = this.lastWidth || 0,
14642
14643             hiddenItems = this.hiddenItems,
14644             hasHiddens  = hiddenItems.length != 0,
14645             isLarger    = width >= lastWidth;
14646
14647         this.lastWidth  = width;
14648
14649         if (tableWidth > width || (hasHiddens && isLarger)) {
14650             var items     = this.container.items.items,
14651                 len       = items.length,
14652                 loopWidth = 0,
14653                 item;
14654
14655             for (var i = 0; i < len; i++) {
14656                 item = items[i];
14657
14658                 if (!item.isFill) {
14659                     loopWidth += this.getItemWidth(item);
14660                     if (loopWidth > clipWidth) {
14661                         if (!(item.hidden || item.xtbHidden)) {
14662                             this.hideItem(item);
14663                         }
14664                     } else if (item.xtbHidden) {
14665                         this.unhideItem(item);
14666                     }
14667                 }
14668             }
14669         }
14670
14671         
14672         hasHiddens = hiddenItems.length != 0;
14673
14674         if (hasHiddens) {
14675             this.initMore();
14676
14677             if (!this.lastOverflow) {
14678                 this.container.fireEvent('overflowchange', this.container, true);
14679                 this.lastOverflow = true;
14680             }
14681         } else if (this.more) {
14682             this.clearMenu();
14683             this.more.destroy();
14684             delete this.more;
14685
14686             if (this.lastOverflow) {
14687                 this.container.fireEvent('overflowchange', this.container, false);
14688                 this.lastOverflow = false;
14689             }
14690         }
14691     },
14692
14693     
14694     createMenuConfig : function(component, hideOnClick){
14695         var config = Ext.apply({}, component.initialConfig),
14696             group  = component.toggleGroup;
14697
14698         Ext.copyTo(config, component, [
14699             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
14700         ]);
14701
14702         Ext.apply(config, {
14703             text       : component.overflowText || component.text,
14704             hideOnClick: hideOnClick
14705         });
14706
14707         if (group || component.enableToggle) {
14708             Ext.apply(config, {
14709                 group  : group,
14710                 checked: component.pressed,
14711                 listeners: {
14712                     checkchange: function(item, checked){
14713                         component.toggle(checked);
14714                     }
14715                 }
14716             });
14717         }
14718
14719         delete config.ownerCt;
14720         delete config.xtype;
14721         delete config.id;
14722
14723         return config;
14724     },
14725
14726     
14727     addComponentToMenu : function(menu, component) {
14728         if (component instanceof Ext.Toolbar.Separator) {
14729             menu.add('-');
14730
14731         } else if (Ext.isFunction(component.isXType)) {
14732             if (component.isXType('splitbutton')) {
14733                 menu.add(this.createMenuConfig(component, true));
14734
14735             } else if (component.isXType('button')) {
14736                 menu.add(this.createMenuConfig(component, !component.menu));
14737
14738             } else if (component.isXType('buttongroup')) {
14739                 component.items.each(function(item){
14740                      this.addComponentToMenu(menu, item);
14741                 }, this);
14742             }
14743         }
14744     },
14745
14746     
14747     clearMenu : function(){
14748         var menu = this.moreMenu;
14749         if (menu && menu.items) {
14750             menu.items.each(function(item){
14751                 delete item.menu;
14752             });
14753         }
14754     },
14755
14756     
14757     beforeMoreShow : function(menu) {
14758         var items = this.container.items.items,
14759             len   = items.length,
14760             item,
14761             prev;
14762
14763         var needsSep = function(group, item){
14764             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
14765         };
14766
14767         this.clearMenu();
14768         menu.removeAll();
14769         for (var i = 0; i < len; i++) {
14770             item = items[i];
14771             if (item.xtbHidden) {
14772                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
14773                     menu.add('-');
14774                 }
14775                 this.addComponentToMenu(menu, item);
14776                 prev = item;
14777             }
14778         }
14779
14780         
14781         if (menu.items.length < 1) {
14782             menu.add(this.noItemsMenuText);
14783         }
14784     },
14785
14786     
14787     initMore : function(){
14788         if (!this.more) {
14789             
14790             this.moreMenu = new Ext.menu.Menu({
14791                 ownerCt : this.container,
14792                 listeners: {
14793                     beforeshow: this.beforeMoreShow,
14794                     scope: this
14795                 }
14796             });
14797
14798             
14799             this.more = new Ext.Button({
14800                 iconCls: 'x-toolbar-more-icon',
14801                 cls    : 'x-toolbar-more',
14802                 menu   : this.moreMenu,
14803                 ownerCt: this.container
14804             });
14805
14806             var td = this.insertCell(this.more, this.extrasTr, 100);
14807             this.more.render(td);
14808         }
14809     },
14810
14811     destroy : function(){
14812         Ext.destroy(this.more, this.moreMenu);
14813         delete this.leftTr;
14814         delete this.rightTr;
14815         delete this.extrasTr;
14816         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
14817     }
14818 });
14819
14820 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
14821
14822  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
14823     monitorResize : true,
14824
14825     type: 'menu',
14826
14827     setContainer : function(ct){
14828         this.monitorResize = !ct.floating;
14829         
14830         
14831         ct.on('autosize', this.doAutoSize, this);
14832         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
14833     },
14834
14835     renderItem : function(c, position, target){
14836         if (!this.itemTpl) {
14837             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
14838                 '<li id="{itemId}" class="{itemCls}">',
14839                     '<tpl if="needsIcon">',
14840                         '<img src="{icon}" class="{iconCls}"/>',
14841                     '</tpl>',
14842                 '</li>'
14843             );
14844         }
14845
14846         if(c && !c.rendered){
14847             if(Ext.isNumber(position)){
14848                 position = target.dom.childNodes[position];
14849             }
14850             var a = this.getItemArgs(c);
14851
14852
14853             c.render(c.positionEl = position ?
14854                 this.itemTpl.insertBefore(position, a, true) :
14855                 this.itemTpl.append(target, a, true));
14856
14857
14858             c.positionEl.menuItemId = c.getItemId();
14859
14860
14861
14862             if (!a.isMenuItem && a.needsIcon) {
14863                 c.positionEl.addClass('x-menu-list-item-indent');
14864             }
14865             this.configureItem(c, position);
14866         }else if(c && !this.isValidParent(c, target)){
14867             if(Ext.isNumber(position)){
14868                 position = target.dom.childNodes[position];
14869             }
14870             target.dom.insertBefore(c.getActionEl().dom, position || null);
14871         }
14872     },
14873
14874     getItemArgs : function(c) {
14875         var isMenuItem = c instanceof Ext.menu.Item;
14876         return {
14877             isMenuItem: isMenuItem,
14878             needsIcon: !isMenuItem && (c.icon || c.iconCls),
14879             icon: c.icon || Ext.BLANK_IMAGE_URL,
14880             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
14881             itemId: 'x-menu-el-' + c.id,
14882             itemCls: 'x-menu-list-item '
14883         };
14884     },
14885
14886     
14887     isValidParent : function(c, target) {
14888         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
14889     },
14890
14891     onLayout : function(ct, target){
14892         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
14893         this.doAutoSize();
14894     },
14895
14896     doAutoSize : function(){
14897         var ct = this.container, w = ct.width;
14898         if(ct.floating){
14899             if(w){
14900                 ct.setWidth(w);
14901             }else if(Ext.isIE){
14902                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
14903                 var el = ct.getEl(), t = el.dom.offsetWidth; 
14904                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
14905             }
14906         }
14907     }
14908 });
14909 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
14910
14911 Ext.Viewport = Ext.extend(Ext.Container, {
14912     
14913     
14914     
14915     
14916     
14917     
14918     
14919     
14920     
14921     
14922     
14923     
14924
14925     initComponent : function() {
14926         Ext.Viewport.superclass.initComponent.call(this);
14927         document.getElementsByTagName('html')[0].className += ' x-viewport';
14928         this.el = Ext.getBody();
14929         this.el.setHeight = Ext.emptyFn;
14930         this.el.setWidth = Ext.emptyFn;
14931         this.el.setSize = Ext.emptyFn;
14932         this.el.dom.scroll = 'no';
14933         this.allowDomMove = false;
14934         this.autoWidth = true;
14935         this.autoHeight = true;
14936         Ext.EventManager.onWindowResize(this.fireResize, this);
14937         this.renderTo = this.el;
14938     },
14939
14940     fireResize : function(w, h){
14941         this.fireEvent('resize', this, w, h, w, h);
14942     }
14943 });
14944 Ext.reg('viewport', Ext.Viewport);
14945
14946 Ext.Panel = Ext.extend(Ext.Container, {
14947     
14948     
14949     
14950     
14951     
14952     
14953     
14954     
14955     
14956     
14957     
14958     
14959     
14960     
14961     
14962     
14963     
14964     
14965     
14966     
14967     
14968     
14969     
14970     
14971     
14972     
14973     
14974     
14975     
14976     
14977     
14978     
14979
14980     
14981     
14982     
14983     
14984     
14985     
14986     
14987     
14988
14989
14990     
14991     baseCls : 'x-panel',
14992     
14993     collapsedCls : 'x-panel-collapsed',
14994     
14995     maskDisabled : true,
14996     
14997     animCollapse : Ext.enableFx,
14998     
14999     headerAsText : true,
15000     
15001     buttonAlign : 'right',
15002     
15003     collapsed : false,
15004     
15005     collapseFirst : true,
15006     
15007     minButtonWidth : 75,
15008     
15009     
15010     elements : 'body',
15011     
15012     preventBodyReset : false,
15013
15014     
15015     padding: undefined,
15016
15017     
15018     resizeEvent: 'bodyresize',
15019
15020     
15021     
15022     
15023     toolTarget : 'header',
15024     collapseEl : 'bwrap',
15025     slideAnchor : 't',
15026     disabledClass : '',
15027
15028     
15029     deferHeight : true,
15030     
15031     expandDefaults: {
15032         duration : 0.25
15033     },
15034     
15035     collapseDefaults : {
15036         duration : 0.25
15037     },
15038
15039     
15040     initComponent : function(){
15041         Ext.Panel.superclass.initComponent.call(this);
15042
15043         this.addEvents(
15044             
15045             'bodyresize',
15046             
15047             'titlechange',
15048             
15049             'iconchange',
15050             
15051             'collapse',
15052             
15053             'expand',
15054             
15055             'beforecollapse',
15056             
15057             'beforeexpand',
15058             
15059             'beforeclose',
15060             
15061             'close',
15062             
15063             'activate',
15064             
15065             'deactivate'
15066         );
15067
15068         if(this.unstyled){
15069             this.baseCls = 'x-plain';
15070         }
15071
15072
15073         this.toolbars = [];
15074         
15075         if(this.tbar){
15076             this.elements += ',tbar';
15077             this.topToolbar = this.createToolbar(this.tbar);
15078             this.tbar = null;
15079
15080         }
15081         if(this.bbar){
15082             this.elements += ',bbar';
15083             this.bottomToolbar = this.createToolbar(this.bbar);
15084             this.bbar = null;
15085         }
15086
15087         if(this.header === true){
15088             this.elements += ',header';
15089             this.header = null;
15090         }else if(this.headerCfg || (this.title && this.header !== false)){
15091             this.elements += ',header';
15092         }
15093
15094         if(this.footerCfg || this.footer === true){
15095             this.elements += ',footer';
15096             this.footer = null;
15097         }
15098
15099         if(this.buttons){
15100             this.fbar = this.buttons;
15101             this.buttons = null;
15102         }
15103         if(this.fbar){
15104             this.createFbar(this.fbar);
15105         }
15106         if(this.autoLoad){
15107             this.on('render', this.doAutoLoad, this, {delay:10});
15108         }
15109     },
15110
15111     
15112     createFbar : function(fbar){
15113         var min = this.minButtonWidth;
15114         this.elements += ',footer';
15115         this.fbar = this.createToolbar(fbar, {
15116             buttonAlign: this.buttonAlign,
15117             toolbarCls: 'x-panel-fbar',
15118             enableOverflow: false,
15119             defaults: function(c){
15120                 return {
15121                     minWidth: c.minWidth || min
15122                 };
15123             }
15124         });
15125         
15126         
15127         
15128         this.fbar.items.each(function(c){
15129             c.minWidth = c.minWidth || this.minButtonWidth;
15130         }, this);
15131         this.buttons = this.fbar.items.items;
15132     },
15133
15134     
15135     createToolbar: function(tb, options){
15136         var result;
15137         
15138         if(Ext.isArray(tb)){
15139             tb = {
15140                 items: tb
15141             };
15142         }
15143         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
15144         this.toolbars.push(result);
15145         return result;
15146     },
15147
15148     
15149     createElement : function(name, pnode){
15150         if(this[name]){
15151             pnode.appendChild(this[name].dom);
15152             return;
15153         }
15154
15155         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
15156             if(this[name+'Cfg']){
15157                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
15158             }else{
15159                 var el = document.createElement('div');
15160                 el.className = this[name+'Cls'];
15161                 this[name] = Ext.get(pnode.appendChild(el));
15162             }
15163             if(this[name+'CssClass']){
15164                 this[name].addClass(this[name+'CssClass']);
15165             }
15166             if(this[name+'Style']){
15167                 this[name].applyStyles(this[name+'Style']);
15168             }
15169         }
15170     },
15171
15172     
15173     onRender : function(ct, position){
15174         Ext.Panel.superclass.onRender.call(this, ct, position);
15175         this.createClasses();
15176
15177         var el = this.el,
15178             d = el.dom,
15179             bw,
15180             ts;
15181
15182
15183         if(this.collapsible && !this.hideCollapseTool){
15184             this.tools = this.tools ? this.tools.slice(0) : [];
15185             this.tools[this.collapseFirst?'unshift':'push']({
15186                 id: 'toggle',
15187                 handler : this.toggleCollapse,
15188                 scope: this
15189             });
15190         }
15191
15192         if(this.tools){
15193             ts = this.tools;
15194             this.elements += (this.header !== false) ? ',header' : '';
15195         }
15196         this.tools = {};
15197
15198         el.addClass(this.baseCls);
15199         if(d.firstChild){ 
15200             this.header = el.down('.'+this.headerCls);
15201             this.bwrap = el.down('.'+this.bwrapCls);
15202             var cp = this.bwrap ? this.bwrap : el;
15203             this.tbar = cp.down('.'+this.tbarCls);
15204             this.body = cp.down('.'+this.bodyCls);
15205             this.bbar = cp.down('.'+this.bbarCls);
15206             this.footer = cp.down('.'+this.footerCls);
15207             this.fromMarkup = true;
15208         }
15209         if (this.preventBodyReset === true) {
15210             el.addClass('x-panel-reset');
15211         }
15212         if(this.cls){
15213             el.addClass(this.cls);
15214         }
15215
15216         if(this.buttons){
15217             this.elements += ',footer';
15218         }
15219
15220         
15221
15222         
15223         if(this.frame){
15224             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
15225
15226             this.createElement('header', d.firstChild.firstChild.firstChild);
15227             this.createElement('bwrap', d);
15228
15229             
15230             bw = this.bwrap.dom;
15231             var ml = d.childNodes[1], bl = d.childNodes[2];
15232             bw.appendChild(ml);
15233             bw.appendChild(bl);
15234
15235             var mc = bw.firstChild.firstChild.firstChild;
15236             this.createElement('tbar', mc);
15237             this.createElement('body', mc);
15238             this.createElement('bbar', mc);
15239             this.createElement('footer', bw.lastChild.firstChild.firstChild);
15240
15241             if(!this.footer){
15242                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
15243             }
15244             
15245             this.ft = Ext.get(this.bwrap.dom.lastChild);
15246             this.mc = Ext.get(mc);
15247         }else{
15248             this.createElement('header', d);
15249             this.createElement('bwrap', d);
15250
15251             
15252             bw = this.bwrap.dom;
15253             this.createElement('tbar', bw);
15254             this.createElement('body', bw);
15255             this.createElement('bbar', bw);
15256             this.createElement('footer', bw);
15257
15258             if(!this.header){
15259                 this.body.addClass(this.bodyCls + '-noheader');
15260                 if(this.tbar){
15261                     this.tbar.addClass(this.tbarCls + '-noheader');
15262                 }
15263             }
15264         }
15265
15266         if(Ext.isDefined(this.padding)){
15267             this.body.setStyle('padding', this.body.addUnits(this.padding));
15268         }
15269
15270         if(this.border === false){
15271             this.el.addClass(this.baseCls + '-noborder');
15272             this.body.addClass(this.bodyCls + '-noborder');
15273             if(this.header){
15274                 this.header.addClass(this.headerCls + '-noborder');
15275             }
15276             if(this.footer){
15277                 this.footer.addClass(this.footerCls + '-noborder');
15278             }
15279             if(this.tbar){
15280                 this.tbar.addClass(this.tbarCls + '-noborder');
15281             }
15282             if(this.bbar){
15283                 this.bbar.addClass(this.bbarCls + '-noborder');
15284             }
15285         }
15286
15287         if(this.bodyBorder === false){
15288            this.body.addClass(this.bodyCls + '-noborder');
15289         }
15290
15291         this.bwrap.enableDisplayMode('block');
15292
15293         if(this.header){
15294             this.header.unselectable();
15295
15296             
15297             if(this.headerAsText){
15298                 this.header.dom.innerHTML =
15299                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
15300
15301                 if(this.iconCls){
15302                     this.setIconClass(this.iconCls);
15303                 }
15304             }
15305         }
15306
15307         if(this.floating){
15308             this.makeFloating(this.floating);
15309         }
15310
15311         if(this.collapsible && this.titleCollapse && this.header){
15312             this.mon(this.header, 'click', this.toggleCollapse, this);
15313             this.header.setStyle('cursor', 'pointer');
15314         }
15315         if(ts){
15316             this.addTool.apply(this, ts);
15317         }
15318
15319         
15320         if(this.fbar){
15321             this.footer.addClass('x-panel-btns');
15322             this.fbar.ownerCt = this;
15323             this.fbar.render(this.footer);
15324             this.footer.createChild({cls:'x-clear'});
15325         }
15326         if(this.tbar && this.topToolbar){
15327             this.topToolbar.ownerCt = this;
15328             this.topToolbar.render(this.tbar);
15329         }
15330         if(this.bbar && this.bottomToolbar){
15331             this.bottomToolbar.ownerCt = this;
15332             this.bottomToolbar.render(this.bbar);
15333         }
15334     },
15335
15336     
15337     setIconClass : function(cls){
15338         var old = this.iconCls;
15339         this.iconCls = cls;
15340         if(this.rendered && this.header){
15341             if(this.frame){
15342                 this.header.addClass('x-panel-icon');
15343                 this.header.replaceClass(old, this.iconCls);
15344             }else{
15345                 var hd = this.header,
15346                     img = hd.child('img.x-panel-inline-icon');
15347                 if(img){
15348                     Ext.fly(img).replaceClass(old, this.iconCls);
15349                 }else{
15350                     var hdspan = hd.child('span.' + this.headerTextCls);
15351                     if (hdspan) {
15352                         Ext.DomHelper.insertBefore(hdspan.dom, {
15353                             tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
15354                         });
15355                     }
15356                  }
15357             }
15358         }
15359         this.fireEvent('iconchange', this, cls, old);
15360     },
15361
15362     
15363     makeFloating : function(cfg){
15364         this.floating = true;
15365         this.el = new Ext.Layer(Ext.apply({}, cfg, {
15366             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
15367             shadowOffset: this.shadowOffset,
15368             constrain:false,
15369             shim: this.shim === false ? false : undefined
15370         }), this.el);
15371     },
15372
15373     
15374     getTopToolbar : function(){
15375         return this.topToolbar;
15376     },
15377
15378     
15379     getBottomToolbar : function(){
15380         return this.bottomToolbar;
15381     },
15382
15383     
15384     getFooterToolbar : function() {
15385         return this.fbar;
15386     },
15387
15388     
15389     addButton : function(config, handler, scope){
15390         if(!this.fbar){
15391             this.createFbar([]);
15392         }
15393         if(handler){
15394             if(Ext.isString(config)){
15395                 config = {text: config};
15396             }
15397             config = Ext.apply({
15398                 handler: handler,
15399                 scope: scope
15400             }, config);
15401         }
15402         return this.fbar.add(config);
15403     },
15404
15405     
15406     addTool : function(){
15407         if(!this.rendered){
15408             if(!this.tools){
15409                 this.tools = [];
15410             }
15411             Ext.each(arguments, function(arg){
15412                 this.tools.push(arg);
15413             }, this);
15414             return;
15415         }
15416          
15417         if(!this[this.toolTarget]){
15418             return;
15419         }
15420         if(!this.toolTemplate){
15421             
15422             var tt = new Ext.Template(
15423                  '<div class="x-tool x-tool-{id}">&#160;</div>'
15424             );
15425             tt.disableFormats = true;
15426             tt.compile();
15427             Ext.Panel.prototype.toolTemplate = tt;
15428         }
15429         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
15430             var tc = a[i];
15431             if(!this.tools[tc.id]){
15432                 var overCls = 'x-tool-'+tc.id+'-over';
15433                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
15434                 this.tools[tc.id] = t;
15435                 t.enableDisplayMode('block');
15436                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
15437                 if(tc.on){
15438                     this.mon(t, tc.on);
15439                 }
15440                 if(tc.hidden){
15441                     t.hide();
15442                 }
15443                 if(tc.qtip){
15444                     if(Ext.isObject(tc.qtip)){
15445                         Ext.QuickTips.register(Ext.apply({
15446                               target: t.id
15447                         }, tc.qtip));
15448                     } else {
15449                         t.dom.qtip = tc.qtip;
15450                     }
15451                 }
15452                 t.addClassOnOver(overCls);
15453             }
15454         }
15455     },
15456
15457     onLayout : function(shallow, force){
15458         Ext.Panel.superclass.onLayout.apply(this, arguments);
15459         if(this.hasLayout && this.toolbars.length > 0){
15460             Ext.each(this.toolbars, function(tb){
15461                 tb.doLayout(undefined, force);
15462             });
15463             this.syncHeight();
15464         }
15465     },
15466
15467     syncHeight : function(){
15468         var h = this.toolbarHeight,
15469                 bd = this.body,
15470                 lsh = this.lastSize.height,
15471                 sz;
15472
15473         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
15474             return;
15475         }
15476
15477
15478         if(h != this.getToolbarHeight()){
15479             h = Math.max(0, lsh - this.getFrameHeight());
15480             bd.setHeight(h);
15481             sz = bd.getSize();
15482             this.toolbarHeight = this.getToolbarHeight();
15483             this.onBodyResize(sz.width, sz.height);
15484         }
15485     },
15486
15487     
15488     onShow : function(){
15489         if(this.floating){
15490             return this.el.show();
15491         }
15492         Ext.Panel.superclass.onShow.call(this);
15493     },
15494
15495     
15496     onHide : function(){
15497         if(this.floating){
15498             return this.el.hide();
15499         }
15500         Ext.Panel.superclass.onHide.call(this);
15501     },
15502
15503     
15504     createToolHandler : function(t, tc, overCls, panel){
15505         return function(e){
15506             t.removeClass(overCls);
15507             if(tc.stopEvent !== false){
15508                 e.stopEvent();
15509             }
15510             if(tc.handler){
15511                 tc.handler.call(tc.scope || t, e, t, panel, tc);
15512             }
15513         };
15514     },
15515
15516     
15517     afterRender : function(){
15518         if(this.floating && !this.hidden){
15519             this.el.show();
15520         }
15521         if(this.title){
15522             this.setTitle(this.title);
15523         }
15524         Ext.Panel.superclass.afterRender.call(this); 
15525         if (this.collapsed) {
15526             this.collapsed = false;
15527             this.collapse(false);
15528         }
15529         this.initEvents();
15530     },
15531
15532     
15533     getKeyMap : function(){
15534         if(!this.keyMap){
15535             this.keyMap = new Ext.KeyMap(this.el, this.keys);
15536         }
15537         return this.keyMap;
15538     },
15539
15540     
15541     initEvents : function(){
15542         if(this.keys){
15543             this.getKeyMap();
15544         }
15545         if(this.draggable){
15546             this.initDraggable();
15547         }
15548         if(this.toolbars.length > 0){
15549             Ext.each(this.toolbars, function(tb){
15550                 tb.doLayout();
15551                 tb.on({
15552                     scope: this,
15553                     afterlayout: this.syncHeight,
15554                     remove: this.syncHeight
15555                 });
15556             }, this);
15557             this.syncHeight();
15558         }
15559
15560     },
15561
15562     
15563     initDraggable : function(){
15564         
15565         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
15566     },
15567
15568     
15569     beforeEffect : function(anim){
15570         if(this.floating){
15571             this.el.beforeAction();
15572         }
15573         if(anim !== false){
15574             this.el.addClass('x-panel-animated');
15575         }
15576     },
15577
15578     
15579     afterEffect : function(anim){
15580         this.syncShadow();
15581         this.el.removeClass('x-panel-animated');
15582     },
15583
15584     
15585     createEffect : function(a, cb, scope){
15586         var o = {
15587             scope:scope,
15588             block:true
15589         };
15590         if(a === true){
15591             o.callback = cb;
15592             return o;
15593         }else if(!a.callback){
15594             o.callback = cb;
15595         }else { 
15596             o.callback = function(){
15597                 cb.call(scope);
15598                 Ext.callback(a.callback, a.scope);
15599             };
15600         }
15601         return Ext.applyIf(o, a);
15602     },
15603
15604     
15605     collapse : function(animate){
15606         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
15607             return;
15608         }
15609         var doAnim = animate === true || (animate !== false && this.animCollapse);
15610         this.beforeEffect(doAnim);
15611         this.onCollapse(doAnim, animate);
15612         return this;
15613     },
15614
15615     
15616     onCollapse : function(doAnim, animArg){
15617         if(doAnim){
15618             this[this.collapseEl].slideOut(this.slideAnchor,
15619                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
15620                         this.collapseDefaults));
15621         }else{
15622             this[this.collapseEl].hide(this.hideMode);
15623             this.afterCollapse(false);
15624         }
15625     },
15626
15627     
15628     afterCollapse : function(anim){
15629         this.collapsed = true;
15630         this.el.addClass(this.collapsedCls);
15631         if(anim !== false){
15632             this[this.collapseEl].hide(this.hideMode);
15633         }
15634         this.afterEffect(anim);
15635
15636         
15637         this.cascade(function(c) {
15638             if (c.lastSize) {
15639                 c.lastSize = { width: undefined, height: undefined };
15640             }
15641         });
15642         this.fireEvent('collapse', this);
15643     },
15644
15645     
15646     expand : function(animate){
15647         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
15648             return;
15649         }
15650         var doAnim = animate === true || (animate !== false && this.animCollapse);
15651         this.el.removeClass(this.collapsedCls);
15652         this.beforeEffect(doAnim);
15653         this.onExpand(doAnim, animate);
15654         return this;
15655     },
15656
15657     
15658     onExpand : function(doAnim, animArg){
15659         if(doAnim){
15660             this[this.collapseEl].slideIn(this.slideAnchor,
15661                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
15662                         this.expandDefaults));
15663         }else{
15664             this[this.collapseEl].show(this.hideMode);
15665             this.afterExpand(false);
15666         }
15667     },
15668
15669     
15670     afterExpand : function(anim){
15671         this.collapsed = false;
15672         if(anim !== false){
15673             this[this.collapseEl].show(this.hideMode);
15674         }
15675         this.afterEffect(anim);
15676         if (this.deferLayout) {
15677             delete this.deferLayout;
15678             this.doLayout(true);
15679         }
15680         this.fireEvent('expand', this);
15681     },
15682
15683     
15684     toggleCollapse : function(animate){
15685         this[this.collapsed ? 'expand' : 'collapse'](animate);
15686         return this;
15687     },
15688
15689     
15690     onDisable : function(){
15691         if(this.rendered && this.maskDisabled){
15692             this.el.mask();
15693         }
15694         Ext.Panel.superclass.onDisable.call(this);
15695     },
15696
15697     
15698     onEnable : function(){
15699         if(this.rendered && this.maskDisabled){
15700             this.el.unmask();
15701         }
15702         Ext.Panel.superclass.onEnable.call(this);
15703     },
15704
15705     
15706     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15707         var w = adjWidth,
15708             h = adjHeight;
15709
15710         if(Ext.isDefined(w) || Ext.isDefined(h)){
15711             if(!this.collapsed){
15712                 
15713                 
15714                 
15715
15716                 if(Ext.isNumber(w)){
15717                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
15718                 } else if (w == 'auto') {
15719                     w = this.body.setWidth('auto').dom.offsetWidth;
15720                 } else {
15721                     w = this.body.dom.offsetWidth;
15722                 }
15723
15724                 if(this.tbar){
15725                     this.tbar.setWidth(w);
15726                     if(this.topToolbar){
15727                         this.topToolbar.setSize(w);
15728                     }
15729                 }
15730                 if(this.bbar){
15731                     this.bbar.setWidth(w);
15732                     if(this.bottomToolbar){
15733                         this.bottomToolbar.setSize(w);
15734                         
15735                         if (Ext.isIE) {
15736                             this.bbar.setStyle('position', 'static');
15737                             this.bbar.setStyle('position', '');
15738                         }
15739                     }
15740                 }
15741                 if(this.footer){
15742                     this.footer.setWidth(w);
15743                     if(this.fbar){
15744                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
15745                     }
15746                 }
15747
15748                 
15749                 if(Ext.isNumber(h)){
15750                     h = Math.max(0, h - this.getFrameHeight());
15751                     
15752                     this.body.setHeight(h);
15753                 }else if(h == 'auto'){
15754                     this.body.setHeight(h);
15755                 }
15756
15757                 if(this.disabled && this.el._mask){
15758                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
15759                 }
15760             }else{
15761                 
15762                 this.queuedBodySize = {width: w, height: h};
15763                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
15764                     this.queuedExpand = true;
15765                     this.on('expand', function(){
15766                         delete this.queuedExpand;
15767                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
15768                     }, this, {single:true});
15769                 }
15770             }
15771             this.onBodyResize(w, h);
15772         }
15773         this.syncShadow();
15774         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
15775
15776     },
15777
15778     
15779     onBodyResize: function(w, h){
15780         this.fireEvent('bodyresize', this, w, h);
15781     },
15782
15783     
15784     getToolbarHeight: function(){
15785         var h = 0;
15786         if(this.rendered){
15787             Ext.each(this.toolbars, function(tb){
15788                 h += tb.getHeight();
15789             }, this);
15790         }
15791         return h;
15792     },
15793
15794     
15795     adjustBodyHeight : function(h){
15796         return h;
15797     },
15798
15799     
15800     adjustBodyWidth : function(w){
15801         return w;
15802     },
15803
15804     
15805     onPosition : function(){
15806         this.syncShadow();
15807     },
15808
15809     
15810     getFrameWidth : function(){
15811         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
15812
15813         if(this.frame){
15814             var l = this.bwrap.dom.firstChild;
15815             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
15816             w += this.mc.getFrameWidth('lr');
15817         }
15818         return w;
15819     },
15820
15821     
15822     getFrameHeight : function() {
15823         var h = Math.max(0, this.getHeight() - this.body.getHeight());
15824
15825         if (isNaN(h)) {
15826             h = 0;
15827         }
15828         return h;
15829
15830         
15831     },
15832
15833     
15834     getInnerWidth : function(){
15835         return this.getSize().width - this.getFrameWidth();
15836     },
15837
15838     
15839     getInnerHeight : function(){
15840         return this.body.getHeight();
15841         
15842     },
15843
15844     
15845     syncShadow : function(){
15846         if(this.floating){
15847             this.el.sync(true);
15848         }
15849     },
15850
15851     
15852     getLayoutTarget : function(){
15853         return this.body;
15854     },
15855
15856     
15857     getContentTarget : function(){
15858         return this.body;
15859     },
15860
15861     
15862     setTitle : function(title, iconCls){
15863         this.title = title;
15864         if(this.header && this.headerAsText){
15865             this.header.child('span').update(title);
15866         }
15867         if(iconCls){
15868             this.setIconClass(iconCls);
15869         }
15870         this.fireEvent('titlechange', this, title);
15871         return this;
15872     },
15873
15874     
15875     getUpdater : function(){
15876         return this.body.getUpdater();
15877     },
15878
15879      
15880     load : function(){
15881         var um = this.body.getUpdater();
15882         um.update.apply(um, arguments);
15883         return this;
15884     },
15885
15886     
15887     beforeDestroy : function(){
15888         Ext.Panel.superclass.beforeDestroy.call(this);
15889         if(this.header){
15890             this.header.removeAllListeners();
15891         }
15892         if(this.tools){
15893             for(var k in this.tools){
15894                 Ext.destroy(this.tools[k]);
15895             }
15896         }
15897         if(this.toolbars.length > 0){
15898             Ext.each(this.toolbars, function(tb){
15899                 tb.un('afterlayout', this.syncHeight, this);
15900                 tb.un('remove', this.syncHeight, this);
15901             }, this);
15902         }
15903         if(Ext.isArray(this.buttons)){
15904             while(this.buttons.length) {
15905                 Ext.destroy(this.buttons[0]);
15906             }
15907         }
15908         if(this.rendered){
15909             Ext.destroy(
15910                 this.ft,
15911                 this.header,
15912                 this.footer,
15913                 this.tbar,
15914                 this.bbar,
15915                 this.body,
15916                 this.mc,
15917                 this.bwrap,
15918                 this.dd
15919             );
15920             if (this.fbar) {
15921                 Ext.destroy(
15922                     this.fbar,
15923                     this.fbar.el
15924                 );
15925             }
15926         }
15927         Ext.destroy(this.toolbars);
15928     },
15929
15930     
15931     createClasses : function(){
15932         this.headerCls = this.baseCls + '-header';
15933         this.headerTextCls = this.baseCls + '-header-text';
15934         this.bwrapCls = this.baseCls + '-bwrap';
15935         this.tbarCls = this.baseCls + '-tbar';
15936         this.bodyCls = this.baseCls + '-body';
15937         this.bbarCls = this.baseCls + '-bbar';
15938         this.footerCls = this.baseCls + '-footer';
15939     },
15940
15941     
15942     createGhost : function(cls, useShim, appendTo){
15943         var el = document.createElement('div');
15944         el.className = 'x-panel-ghost ' + (cls ? cls : '');
15945         if(this.header){
15946             el.appendChild(this.el.dom.firstChild.cloneNode(true));
15947         }
15948         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
15949         el.style.width = this.el.dom.offsetWidth + 'px';;
15950         if(!appendTo){
15951             this.container.dom.appendChild(el);
15952         }else{
15953             Ext.getDom(appendTo).appendChild(el);
15954         }
15955         if(useShim !== false && this.el.useShim !== false){
15956             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
15957             layer.show();
15958             return layer;
15959         }else{
15960             return new Ext.Element(el);
15961         }
15962     },
15963
15964     
15965     doAutoLoad : function(){
15966         var u = this.body.getUpdater();
15967         if(this.renderer){
15968             u.setRenderer(this.renderer);
15969         }
15970         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
15971     },
15972
15973     
15974     getTool : function(id) {
15975         return this.tools[id];
15976     }
15977
15978
15979 });
15980 Ext.reg('panel', Ext.Panel);
15981
15982 Ext.Editor = function(field, config){
15983     if(field.field){
15984         this.field = Ext.create(field.field, 'textfield');
15985         config = Ext.apply({}, field); 
15986         delete config.field;
15987     }else{
15988         this.field = field;
15989     }
15990     Ext.Editor.superclass.constructor.call(this, config);
15991 };
15992
15993 Ext.extend(Ext.Editor, Ext.Component, {
15994     
15995     
15996     allowBlur: true,
15997     
15998     
15999     
16000     
16001     
16002     value : "",
16003     
16004     alignment: "c-c?",
16005     
16006     offsets: [0, 0],
16007     
16008     shadow : "frame",
16009     
16010     constrain : false,
16011     
16012     swallowKeys : true,
16013     
16014     completeOnEnter : true,
16015     
16016     cancelOnEsc : true,
16017     
16018     updateEl : false,
16019
16020     initComponent : function(){
16021         Ext.Editor.superclass.initComponent.call(this);
16022         this.addEvents(
16023             
16024             "beforestartedit",
16025             
16026             "startedit",
16027             
16028             "beforecomplete",
16029             
16030             "complete",
16031             
16032             "canceledit",
16033             
16034             "specialkey"
16035         );
16036     },
16037
16038     
16039     onRender : function(ct, position){
16040         this.el = new Ext.Layer({
16041             shadow: this.shadow,
16042             cls: "x-editor",
16043             parentEl : ct,
16044             shim : this.shim,
16045             shadowOffset: this.shadowOffset || 4,
16046             id: this.id,
16047             constrain: this.constrain
16048         });
16049         if(this.zIndex){
16050             this.el.setZIndex(this.zIndex);
16051         }
16052         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
16053         if(this.field.msgTarget != 'title'){
16054             this.field.msgTarget = 'qtip';
16055         }
16056         this.field.inEditor = true;
16057         this.mon(this.field, {
16058             scope: this,
16059             blur: this.onBlur,
16060             specialkey: this.onSpecialKey
16061         });
16062         if(this.field.grow){
16063             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
16064         }
16065         this.field.render(this.el).show();
16066         this.field.getEl().dom.name = '';
16067         if(this.swallowKeys){
16068             this.field.el.swallowEvent([
16069                 'keypress', 
16070                 'keydown'   
16071             ]);
16072         }
16073     },
16074
16075     
16076     onSpecialKey : function(field, e){
16077         var key = e.getKey(),
16078             complete = this.completeOnEnter && key == e.ENTER,
16079             cancel = this.cancelOnEsc && key == e.ESC;
16080         if(complete || cancel){
16081             e.stopEvent();
16082             if(complete){
16083                 this.completeEdit();
16084             }else{
16085                 this.cancelEdit();
16086             }
16087             if(field.triggerBlur){
16088                 field.triggerBlur();
16089             }
16090         }
16091         this.fireEvent('specialkey', field, e);
16092     },
16093
16094     
16095     startEdit : function(el, value){
16096         if(this.editing){
16097             this.completeEdit();
16098         }
16099         this.boundEl = Ext.get(el);
16100         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
16101         if(!this.rendered){
16102             this.render(this.parentEl || document.body);
16103         }
16104         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
16105             this.startValue = v;
16106             this.field.reset();
16107             this.field.setValue(v);
16108             this.realign(true);
16109             this.editing = true;
16110             this.show();
16111         }
16112     },
16113
16114     
16115     doAutoSize : function(){
16116         if(this.autoSize){
16117             var sz = this.boundEl.getSize(),
16118                 fs = this.field.getSize();
16119
16120             switch(this.autoSize){
16121                 case "width":
16122                     this.setSize(sz.width, fs.height);
16123                     break;
16124                 case "height":
16125                     this.setSize(fs.width, sz.height);
16126                     break;
16127                 case "none":
16128                     this.setSize(fs.width, fs.height);
16129                     break;
16130                 default:
16131                     this.setSize(sz.width, sz.height);
16132             }
16133         }
16134     },
16135
16136     
16137     setSize : function(w, h){
16138         delete this.field.lastSize;
16139         this.field.setSize(w, h);
16140         if(this.el){
16141             if(Ext.isGecko2 || Ext.isOpera){
16142                 
16143                 this.el.setSize(w, h);
16144             }
16145             this.el.sync();
16146         }
16147     },
16148
16149     
16150     realign : function(autoSize){
16151         if(autoSize === true){
16152             this.doAutoSize();
16153         }
16154         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
16155     },
16156
16157     
16158     completeEdit : function(remainVisible){
16159         if(!this.editing){
16160             return;
16161         }
16162         
16163         if (this.field.assertValue) {
16164             this.field.assertValue();
16165         }
16166         var v = this.getValue();
16167         if(!this.field.isValid()){
16168             if(this.revertInvalid !== false){
16169                 this.cancelEdit(remainVisible);
16170             }
16171             return;
16172         }
16173         if(String(v) === String(this.startValue) && this.ignoreNoChange){
16174             this.hideEdit(remainVisible);
16175             return;
16176         }
16177         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
16178             v = this.getValue();
16179             if(this.updateEl && this.boundEl){
16180                 this.boundEl.update(v);
16181             }
16182             this.hideEdit(remainVisible);
16183             this.fireEvent("complete", this, v, this.startValue);
16184         }
16185     },
16186
16187     
16188     onShow : function(){
16189         this.el.show();
16190         if(this.hideEl !== false){
16191             this.boundEl.hide();
16192         }
16193         this.field.show().focus(false, true);
16194         this.fireEvent("startedit", this.boundEl, this.startValue);
16195     },
16196
16197     
16198     cancelEdit : function(remainVisible){
16199         if(this.editing){
16200             var v = this.getValue();
16201             this.setValue(this.startValue);
16202             this.hideEdit(remainVisible);
16203             this.fireEvent("canceledit", this, v, this.startValue);
16204         }
16205     },
16206
16207     
16208     hideEdit: function(remainVisible){
16209         if(remainVisible !== true){
16210             this.editing = false;
16211             this.hide();
16212         }
16213     },
16214
16215     
16216     onBlur : function(){
16217         
16218         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
16219             this.completeEdit();
16220         }
16221     },
16222
16223     
16224     onHide : function(){
16225         if(this.editing){
16226             this.completeEdit();
16227             return;
16228         }
16229         this.field.blur();
16230         if(this.field.collapse){
16231             this.field.collapse();
16232         }
16233         this.el.hide();
16234         if(this.hideEl !== false){
16235             this.boundEl.show();
16236         }
16237     },
16238
16239     
16240     setValue : function(v){
16241         this.field.setValue(v);
16242     },
16243
16244     
16245     getValue : function(){
16246         return this.field.getValue();
16247     },
16248
16249     beforeDestroy : function(){
16250         Ext.destroyMembers(this, 'field');
16251
16252         delete this.parentEl;
16253         delete this.boundEl;
16254     }
16255 });
16256 Ext.reg('editor', Ext.Editor);
16257
16258 Ext.ColorPalette = Ext.extend(Ext.Component, {
16259         
16260     
16261     itemCls : 'x-color-palette',
16262     
16263     value : null,
16264     
16265     clickEvent :'click',
16266     
16267     ctype : 'Ext.ColorPalette',
16268
16269     
16270     allowReselect : false,
16271
16272     
16273     colors : [
16274         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
16275         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
16276         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
16277         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
16278         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
16279     ],
16280
16281     
16282     
16283     
16284     
16285     initComponent : function(){
16286         Ext.ColorPalette.superclass.initComponent.call(this);
16287         this.addEvents(
16288             
16289             'select'
16290         );
16291
16292         if(this.handler){
16293             this.on('select', this.handler, this.scope, true);
16294         }    
16295     },
16296
16297     
16298     onRender : function(container, position){
16299         this.autoEl = {
16300             tag: 'div',
16301             cls: this.itemCls
16302         };
16303         Ext.ColorPalette.superclass.onRender.call(this, container, position);
16304         var t = this.tpl || new Ext.XTemplate(
16305             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
16306         );
16307         t.overwrite(this.el, this.colors);
16308         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
16309         if(this.clickEvent != 'click'){
16310                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
16311         }
16312     },
16313
16314     
16315     afterRender : function(){
16316         Ext.ColorPalette.superclass.afterRender.call(this);
16317         if(this.value){
16318             var s = this.value;
16319             this.value = null;
16320             this.select(s, true);
16321         }
16322     },
16323
16324     
16325     handleClick : function(e, t){
16326         e.preventDefault();
16327         if(!this.disabled){
16328             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
16329             this.select(c.toUpperCase());
16330         }
16331     },
16332
16333     
16334     select : function(color, suppressEvent){
16335         color = color.replace('#', '');
16336         if(color != this.value || this.allowReselect){
16337             var el = this.el;
16338             if(this.value){
16339                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
16340             }
16341             el.child('a.color-'+color).addClass('x-color-palette-sel');
16342             this.value = color;
16343             if(suppressEvent !== true){
16344                 this.fireEvent('select', this, color);
16345             }
16346         }
16347     }
16348
16349     
16350 });
16351 Ext.reg('colorpalette', Ext.ColorPalette);
16352 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
16353     
16354     todayText : 'Today',
16355     
16356     okText : '&#160;OK&#160;',
16357     
16358     cancelText : 'Cancel',
16359     
16360     
16361     
16362     todayTip : '{0} (Spacebar)',
16363     
16364     minText : 'This date is before the minimum date',
16365     
16366     maxText : 'This date is after the maximum date',
16367     
16368     format : 'm/d/y',
16369     
16370     disabledDaysText : 'Disabled',
16371     
16372     disabledDatesText : 'Disabled',
16373     
16374     monthNames : Date.monthNames,
16375     
16376     dayNames : Date.dayNames,
16377     
16378     nextText : 'Next Month (Control+Right)',
16379     
16380     prevText : 'Previous Month (Control+Left)',
16381     
16382     monthYearText : 'Choose a month (Control+Up/Down to move years)',
16383     
16384     startDay : 0,
16385     
16386     showToday : true,
16387     
16388     
16389     
16390     
16391     
16392
16393     
16394     
16395     focusOnSelect: true,
16396
16397     
16398     
16399     initHour: 12, 
16400
16401     
16402     initComponent : function(){
16403         Ext.DatePicker.superclass.initComponent.call(this);
16404
16405         this.value = this.value ?
16406                  this.value.clearTime(true) : new Date().clearTime();
16407
16408         this.addEvents(
16409             
16410             'select'
16411         );
16412
16413         if(this.handler){
16414             this.on('select', this.handler,  this.scope || this);
16415         }
16416
16417         this.initDisabledDays();
16418     },
16419
16420     
16421     initDisabledDays : function(){
16422         if(!this.disabledDatesRE && this.disabledDates){
16423             var dd = this.disabledDates,
16424                 len = dd.length - 1,
16425                 re = '(?:';
16426
16427             Ext.each(dd, function(d, i){
16428                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
16429                 if(i != len){
16430                     re += '|';
16431                 }
16432             }, this);
16433             this.disabledDatesRE = new RegExp(re + ')');
16434         }
16435     },
16436
16437     
16438     setDisabledDates : function(dd){
16439         if(Ext.isArray(dd)){
16440             this.disabledDates = dd;
16441             this.disabledDatesRE = null;
16442         }else{
16443             this.disabledDatesRE = dd;
16444         }
16445         this.initDisabledDays();
16446         this.update(this.value, true);
16447     },
16448
16449     
16450     setDisabledDays : function(dd){
16451         this.disabledDays = dd;
16452         this.update(this.value, true);
16453     },
16454
16455     
16456     setMinDate : function(dt){
16457         this.minDate = dt;
16458         this.update(this.value, true);
16459     },
16460
16461     
16462     setMaxDate : function(dt){
16463         this.maxDate = dt;
16464         this.update(this.value, true);
16465     },
16466
16467     
16468     setValue : function(value){
16469         this.value = value.clearTime(true);
16470         this.update(this.value);
16471     },
16472
16473     
16474     getValue : function(){
16475         return this.value;
16476     },
16477
16478     
16479     focus : function(){
16480         this.update(this.activeDate);
16481     },
16482
16483     
16484     onEnable: function(initial){
16485         Ext.DatePicker.superclass.onEnable.call(this);
16486         this.doDisabled(false);
16487         this.update(initial ? this.value : this.activeDate);
16488         if(Ext.isIE){
16489             this.el.repaint();
16490         }
16491
16492     },
16493
16494     
16495     onDisable : function(){
16496         Ext.DatePicker.superclass.onDisable.call(this);
16497         this.doDisabled(true);
16498         if(Ext.isIE && !Ext.isIE8){
16499             
16500              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
16501                  Ext.fly(el).repaint();
16502              });
16503         }
16504     },
16505
16506     
16507     doDisabled : function(disabled){
16508         this.keyNav.setDisabled(disabled);
16509         this.prevRepeater.setDisabled(disabled);
16510         this.nextRepeater.setDisabled(disabled);
16511         if(this.showToday){
16512             this.todayKeyListener.setDisabled(disabled);
16513             this.todayBtn.setDisabled(disabled);
16514         }
16515     },
16516
16517     
16518     onRender : function(container, position){
16519         var m = [
16520              '<table cellspacing="0">',
16521                 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
16522                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
16523                 dn = this.dayNames,
16524                 i;
16525         for(i = 0; i < 7; i++){
16526             var d = this.startDay+i;
16527             if(d > 6){
16528                 d = d-7;
16529             }
16530             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
16531         }
16532         m[m.length] = '</tr></thead><tbody><tr>';
16533         for(i = 0; i < 42; i++) {
16534             if(i % 7 === 0 && i !== 0){
16535                 m[m.length] = '</tr><tr>';
16536             }
16537             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
16538         }
16539         m.push('</tr></tbody></table></td></tr>',
16540                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
16541                 '</table><div class="x-date-mp"></div>');
16542
16543         var el = document.createElement('div');
16544         el.className = 'x-date-picker';
16545         el.innerHTML = m.join('');
16546
16547         container.dom.insertBefore(el, position);
16548
16549         this.el = Ext.get(el);
16550         this.eventEl = Ext.get(el.firstChild);
16551
16552         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
16553             handler: this.showPrevMonth,
16554             scope: this,
16555             preventDefault:true,
16556             stopDefault:true
16557         });
16558
16559         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
16560             handler: this.showNextMonth,
16561             scope: this,
16562             preventDefault:true,
16563             stopDefault:true
16564         });
16565
16566         this.monthPicker = this.el.down('div.x-date-mp');
16567         this.monthPicker.enableDisplayMode('block');
16568
16569         this.keyNav = new Ext.KeyNav(this.eventEl, {
16570             'left' : function(e){
16571                 if(e.ctrlKey){
16572                     this.showPrevMonth();
16573                 }else{
16574                     this.update(this.activeDate.add('d', -1));
16575                 }
16576             },
16577
16578             'right' : function(e){
16579                 if(e.ctrlKey){
16580                     this.showNextMonth();
16581                 }else{
16582                     this.update(this.activeDate.add('d', 1));
16583                 }
16584             },
16585
16586             'up' : function(e){
16587                 if(e.ctrlKey){
16588                     this.showNextYear();
16589                 }else{
16590                     this.update(this.activeDate.add('d', -7));
16591                 }
16592             },
16593
16594             'down' : function(e){
16595                 if(e.ctrlKey){
16596                     this.showPrevYear();
16597                 }else{
16598                     this.update(this.activeDate.add('d', 7));
16599                 }
16600             },
16601
16602             'pageUp' : function(e){
16603                 this.showNextMonth();
16604             },
16605
16606             'pageDown' : function(e){
16607                 this.showPrevMonth();
16608             },
16609
16610             'enter' : function(e){
16611                 e.stopPropagation();
16612                 return true;
16613             },
16614
16615             scope : this
16616         });
16617
16618         this.el.unselectable();
16619
16620         this.cells = this.el.select('table.x-date-inner tbody td');
16621         this.textNodes = this.el.query('table.x-date-inner tbody span');
16622
16623         this.mbtn = new Ext.Button({
16624             text: '&#160;',
16625             tooltip: this.monthYearText,
16626             renderTo: this.el.child('td.x-date-middle', true)
16627         });
16628         this.mbtn.el.child('em').addClass('x-btn-arrow');
16629
16630         if(this.showToday){
16631             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
16632             var today = (new Date()).dateFormat(this.format);
16633             this.todayBtn = new Ext.Button({
16634                 renderTo: this.el.child('td.x-date-bottom', true),
16635                 text: String.format(this.todayText, today),
16636                 tooltip: String.format(this.todayTip, today),
16637                 handler: this.selectToday,
16638                 scope: this
16639             });
16640         }
16641         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
16642         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
16643         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
16644         this.onEnable(true);
16645     },
16646
16647     
16648     createMonthPicker : function(){
16649         if(!this.monthPicker.dom.firstChild){
16650             var buf = ['<table border="0" cellspacing="0">'];
16651             for(var i = 0; i < 6; i++){
16652                 buf.push(
16653                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
16654                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
16655                     i === 0 ?
16656                     '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
16657                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
16658                 );
16659             }
16660             buf.push(
16661                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
16662                     this.okText,
16663                     '</button><button type="button" class="x-date-mp-cancel">',
16664                     this.cancelText,
16665                     '</button></td></tr>',
16666                 '</table>'
16667             );
16668             this.monthPicker.update(buf.join(''));
16669
16670             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
16671             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
16672
16673             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
16674             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
16675
16676             this.mpMonths.each(function(m, a, i){
16677                 i += 1;
16678                 if((i%2) === 0){
16679                     m.dom.xmonth = 5 + Math.round(i * 0.5);
16680                 }else{
16681                     m.dom.xmonth = Math.round((i-1) * 0.5);
16682                 }
16683             });
16684         }
16685     },
16686
16687     
16688     showMonthPicker : function(){
16689         if(!this.disabled){
16690             this.createMonthPicker();
16691             var size = this.el.getSize();
16692             this.monthPicker.setSize(size);
16693             this.monthPicker.child('table').setSize(size);
16694
16695             this.mpSelMonth = (this.activeDate || this.value).getMonth();
16696             this.updateMPMonth(this.mpSelMonth);
16697             this.mpSelYear = (this.activeDate || this.value).getFullYear();
16698             this.updateMPYear(this.mpSelYear);
16699
16700             this.monthPicker.slideIn('t', {duration:0.2});
16701         }
16702     },
16703
16704     
16705     updateMPYear : function(y){
16706         this.mpyear = y;
16707         var ys = this.mpYears.elements;
16708         for(var i = 1; i <= 10; i++){
16709             var td = ys[i-1], y2;
16710             if((i%2) === 0){
16711                 y2 = y + Math.round(i * 0.5);
16712                 td.firstChild.innerHTML = y2;
16713                 td.xyear = y2;
16714             }else{
16715                 y2 = y - (5-Math.round(i * 0.5));
16716                 td.firstChild.innerHTML = y2;
16717                 td.xyear = y2;
16718             }
16719             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
16720         }
16721     },
16722
16723     
16724     updateMPMonth : function(sm){
16725         this.mpMonths.each(function(m, a, i){
16726             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
16727         });
16728     },
16729
16730     
16731     selectMPMonth : function(m){
16732
16733     },
16734
16735     
16736     onMonthClick : function(e, t){
16737         e.stopEvent();
16738         var el = new Ext.Element(t), pn;
16739         if(el.is('button.x-date-mp-cancel')){
16740             this.hideMonthPicker();
16741         }
16742         else if(el.is('button.x-date-mp-ok')){
16743             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
16744             if(d.getMonth() != this.mpSelMonth){
16745                 
16746                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
16747             }
16748             this.update(d);
16749             this.hideMonthPicker();
16750         }
16751         else if((pn = el.up('td.x-date-mp-month', 2))){
16752             this.mpMonths.removeClass('x-date-mp-sel');
16753             pn.addClass('x-date-mp-sel');
16754             this.mpSelMonth = pn.dom.xmonth;
16755         }
16756         else if((pn = el.up('td.x-date-mp-year', 2))){
16757             this.mpYears.removeClass('x-date-mp-sel');
16758             pn.addClass('x-date-mp-sel');
16759             this.mpSelYear = pn.dom.xyear;
16760         }
16761         else if(el.is('a.x-date-mp-prev')){
16762             this.updateMPYear(this.mpyear-10);
16763         }
16764         else if(el.is('a.x-date-mp-next')){
16765             this.updateMPYear(this.mpyear+10);
16766         }
16767     },
16768
16769     
16770     onMonthDblClick : function(e, t){
16771         e.stopEvent();
16772         var el = new Ext.Element(t), pn;
16773         if((pn = el.up('td.x-date-mp-month', 2))){
16774             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
16775             this.hideMonthPicker();
16776         }
16777         else if((pn = el.up('td.x-date-mp-year', 2))){
16778             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
16779             this.hideMonthPicker();
16780         }
16781     },
16782
16783     
16784     hideMonthPicker : function(disableAnim){
16785         if(this.monthPicker){
16786             if(disableAnim === true){
16787                 this.monthPicker.hide();
16788             }else{
16789                 this.monthPicker.slideOut('t', {duration:0.2});
16790             }
16791         }
16792     },
16793
16794     
16795     showPrevMonth : function(e){
16796         this.update(this.activeDate.add('mo', -1));
16797     },
16798
16799     
16800     showNextMonth : function(e){
16801         this.update(this.activeDate.add('mo', 1));
16802     },
16803
16804     
16805     showPrevYear : function(){
16806         this.update(this.activeDate.add('y', -1));
16807     },
16808
16809     
16810     showNextYear : function(){
16811         this.update(this.activeDate.add('y', 1));
16812     },
16813
16814     
16815     handleMouseWheel : function(e){
16816         e.stopEvent();
16817         if(!this.disabled){
16818             var delta = e.getWheelDelta();
16819             if(delta > 0){
16820                 this.showPrevMonth();
16821             } else if(delta < 0){
16822                 this.showNextMonth();
16823             }
16824         }
16825     },
16826
16827     
16828     handleDateClick : function(e, t){
16829         e.stopEvent();
16830         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
16831             this.cancelFocus = this.focusOnSelect === false;
16832             this.setValue(new Date(t.dateValue));
16833             delete this.cancelFocus;
16834             this.fireEvent('select', this, this.value);
16835         }
16836     },
16837
16838     
16839     selectToday : function(){
16840         if(this.todayBtn && !this.todayBtn.disabled){
16841             this.setValue(new Date().clearTime());
16842             this.fireEvent('select', this, this.value);
16843         }
16844     },
16845
16846     
16847     update : function(date, forceRefresh){
16848         if(this.rendered){
16849             var vd = this.activeDate, vis = this.isVisible();
16850             this.activeDate = date;
16851             if(!forceRefresh && vd && this.el){
16852                 var t = date.getTime();
16853                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
16854                     this.cells.removeClass('x-date-selected');
16855                     this.cells.each(function(c){
16856                        if(c.dom.firstChild.dateValue == t){
16857                            c.addClass('x-date-selected');
16858                            if(vis && !this.cancelFocus){
16859                                Ext.fly(c.dom.firstChild).focus(50);
16860                            }
16861                            return false;
16862                        }
16863                     }, this);
16864                     return;
16865                 }
16866             }
16867             var days = date.getDaysInMonth(),
16868                 firstOfMonth = date.getFirstDateOfMonth(),
16869                 startingPos = firstOfMonth.getDay()-this.startDay;
16870
16871             if(startingPos < 0){
16872                 startingPos += 7;
16873             }
16874             days += startingPos;
16875
16876             var pm = date.add('mo', -1),
16877                 prevStart = pm.getDaysInMonth()-startingPos,
16878                 cells = this.cells.elements,
16879                 textEls = this.textNodes,
16880                 
16881                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
16882                 today = new Date().clearTime().getTime(),
16883                 sel = date.clearTime(true).getTime(),
16884                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
16885                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
16886                 ddMatch = this.disabledDatesRE,
16887                 ddText = this.disabledDatesText,
16888                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
16889                 ddaysText = this.disabledDaysText,
16890                 format = this.format;
16891
16892             if(this.showToday){
16893                 var td = new Date().clearTime(),
16894                     disable = (td < min || td > max ||
16895                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
16896                     (ddays && ddays.indexOf(td.getDay()) != -1));
16897
16898                 if(!this.disabled){
16899                     this.todayBtn.setDisabled(disable);
16900                     this.todayKeyListener[disable ? 'disable' : 'enable']();
16901                 }
16902             }
16903
16904             var setCellClass = function(cal, cell){
16905                 cell.title = '';
16906                 var t = d.clearTime(true).getTime();
16907                 cell.firstChild.dateValue = t;
16908                 if(t == today){
16909                     cell.className += ' x-date-today';
16910                     cell.title = cal.todayText;
16911                 }
16912                 if(t == sel){
16913                     cell.className += ' x-date-selected';
16914                     if(vis){
16915                         Ext.fly(cell.firstChild).focus(50);
16916                     }
16917                 }
16918                 
16919                 if(t < min) {
16920                     cell.className = ' x-date-disabled';
16921                     cell.title = cal.minText;
16922                     return;
16923                 }
16924                 if(t > max) {
16925                     cell.className = ' x-date-disabled';
16926                     cell.title = cal.maxText;
16927                     return;
16928                 }
16929                 if(ddays){
16930                     if(ddays.indexOf(d.getDay()) != -1){
16931                         cell.title = ddaysText;
16932                         cell.className = ' x-date-disabled';
16933                     }
16934                 }
16935                 if(ddMatch && format){
16936                     var fvalue = d.dateFormat(format);
16937                     if(ddMatch.test(fvalue)){
16938                         cell.title = ddText.replace('%0', fvalue);
16939                         cell.className = ' x-date-disabled';
16940                     }
16941                 }
16942             };
16943
16944             var i = 0;
16945             for(; i < startingPos; i++) {
16946                 textEls[i].innerHTML = (++prevStart);
16947                 d.setDate(d.getDate()+1);
16948                 cells[i].className = 'x-date-prevday';
16949                 setCellClass(this, cells[i]);
16950             }
16951             for(; i < days; i++){
16952                 var intDay = i - startingPos + 1;
16953                 textEls[i].innerHTML = (intDay);
16954                 d.setDate(d.getDate()+1);
16955                 cells[i].className = 'x-date-active';
16956                 setCellClass(this, cells[i]);
16957             }
16958             var extraDays = 0;
16959             for(; i < 42; i++) {
16960                  textEls[i].innerHTML = (++extraDays);
16961                  d.setDate(d.getDate()+1);
16962                  cells[i].className = 'x-date-nextday';
16963                  setCellClass(this, cells[i]);
16964             }
16965
16966             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
16967
16968             if(!this.internalRender){
16969                 var main = this.el.dom.firstChild,
16970                     w = main.offsetWidth;
16971                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
16972                 Ext.fly(main).setWidth(w);
16973                 this.internalRender = true;
16974                 
16975                 
16976                 
16977                 if(Ext.isOpera && !this.secondPass){
16978                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
16979                     this.secondPass = true;
16980                     this.update.defer(10, this, [date]);
16981                 }
16982             }
16983         }
16984     },
16985
16986     
16987     beforeDestroy : function() {
16988         if(this.rendered){
16989             Ext.destroy(
16990                 this.keyNav,
16991                 this.monthPicker,
16992                 this.eventEl,
16993                 this.mbtn,
16994                 this.nextRepeater,
16995                 this.prevRepeater,
16996                 this.cells.el,
16997                 this.todayBtn
16998             );
16999             delete this.textNodes;
17000             delete this.cells.elements;
17001         }
17002     }
17003
17004     
17005 });
17006
17007 Ext.reg('datepicker', Ext.DatePicker);
17008
17009 Ext.LoadMask = function(el, config){
17010     this.el = Ext.get(el);
17011     Ext.apply(this, config);
17012     if(this.store){
17013         this.store.on({
17014             scope: this,
17015             beforeload: this.onBeforeLoad,
17016             load: this.onLoad,
17017             exception: this.onLoad
17018         });
17019         this.removeMask = Ext.value(this.removeMask, false);
17020     }else{
17021         var um = this.el.getUpdater();
17022         um.showLoadIndicator = false; 
17023         um.on({
17024             scope: this,
17025             beforeupdate: this.onBeforeLoad,
17026             update: this.onLoad,
17027             failure: this.onLoad
17028         });
17029         this.removeMask = Ext.value(this.removeMask, true);
17030     }
17031 };
17032
17033 Ext.LoadMask.prototype = {
17034     
17035     
17036     
17037     msg : 'Loading...',
17038     
17039     msgCls : 'x-mask-loading',
17040
17041     
17042     disabled: false,
17043
17044     
17045     disable : function(){
17046        this.disabled = true;
17047     },
17048
17049     
17050     enable : function(){
17051         this.disabled = false;
17052     },
17053
17054     
17055     onLoad : function(){
17056         this.el.unmask(this.removeMask);
17057     },
17058
17059     
17060     onBeforeLoad : function(){
17061         if(!this.disabled){
17062             this.el.mask(this.msg, this.msgCls);
17063         }
17064     },
17065
17066     
17067     show: function(){
17068         this.onBeforeLoad();
17069     },
17070
17071     
17072     hide: function(){
17073         this.onLoad();
17074     },
17075
17076     
17077     destroy : function(){
17078         if(this.store){
17079             this.store.un('beforeload', this.onBeforeLoad, this);
17080             this.store.un('load', this.onLoad, this);
17081             this.store.un('exception', this.onLoad, this);
17082         }else{
17083             var um = this.el.getUpdater();
17084             um.un('beforeupdate', this.onBeforeLoad, this);
17085             um.un('update', this.onLoad, this);
17086             um.un('failure', this.onLoad, this);
17087         }
17088     }
17089 };Ext.ns('Ext.slider');
17090
17091
17092 Ext.slider.Thumb = Ext.extend(Object, {
17093
17094     
17095     constructor: function(config) {
17096         
17097         Ext.apply(this, config || {}, {
17098             cls: 'x-slider-thumb',
17099
17100             
17101             constrain: false
17102         });
17103
17104         Ext.slider.Thumb.superclass.constructor.call(this, config);
17105
17106         if (this.slider.vertical) {
17107             Ext.apply(this, Ext.slider.Thumb.Vertical);
17108         }
17109     },
17110
17111     
17112     render: function() {
17113         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
17114
17115         this.initEvents();
17116     },
17117
17118     
17119     enable: function() {
17120         this.disabled = false;
17121         this.el.removeClass(this.slider.disabledClass);
17122     },
17123
17124     
17125     disable: function() {
17126         this.disabled = true;
17127         this.el.addClass(this.slider.disabledClass);
17128     },
17129
17130     
17131     initEvents: function() {
17132         var el = this.el;
17133
17134         el.addClassOnOver('x-slider-thumb-over');
17135
17136         this.tracker = new Ext.dd.DragTracker({
17137             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
17138             onStart      : this.onDragStart.createDelegate(this),
17139             onDrag       : this.onDrag.createDelegate(this),
17140             onEnd        : this.onDragEnd.createDelegate(this),
17141             tolerance    : 3,
17142             autoStart    : 300
17143         });
17144
17145         this.tracker.initEl(el);
17146     },
17147
17148     
17149     onBeforeDragStart : function(e) {
17150         if (this.disabled) {
17151             return false;
17152         } else {
17153             this.slider.promoteThumb(this);
17154             return true;
17155         }
17156     },
17157
17158     
17159     onDragStart: function(e){
17160         this.el.addClass('x-slider-thumb-drag');
17161         this.dragging = true;
17162         this.dragStartValue = this.value;
17163
17164         this.slider.fireEvent('dragstart', this.slider, e, this);
17165     },
17166
17167     
17168     onDrag: function(e) {
17169         var slider   = this.slider,
17170             index    = this.index,
17171             newValue = this.getNewValue();
17172
17173         if (this.constrain) {
17174             var above = slider.thumbs[index + 1],
17175                 below = slider.thumbs[index - 1];
17176
17177             if (below != undefined && newValue <= below.value) newValue = below.value;
17178             if (above != undefined && newValue >= above.value) newValue = above.value;
17179         }
17180
17181         slider.setValue(index, newValue, false);
17182         slider.fireEvent('drag', slider, e, this);
17183     },
17184
17185     getNewValue: function() {
17186         var slider   = this.slider,
17187             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
17188
17189         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
17190     },
17191
17192     
17193     onDragEnd: function(e) {
17194         var slider = this.slider,
17195             value  = this.value;
17196
17197         this.el.removeClass('x-slider-thumb-drag');
17198
17199         this.dragging = false;
17200         slider.fireEvent('dragend', slider, e);
17201
17202         if (this.dragStartValue != value) {
17203             slider.fireEvent('changecomplete', slider, value, this);
17204         }
17205     }
17206 });
17207
17208
17209 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
17210     
17211     
17212     vertical: false,
17213     
17214     minValue: 0,
17215     
17216     maxValue: 100,
17217     
17218     decimalPrecision: 0,
17219     
17220     keyIncrement: 1,
17221     
17222     increment: 0,
17223
17224     
17225     clickRange: [5,15],
17226
17227     
17228     clickToChange : true,
17229     
17230     animate: true,
17231
17232     
17233     dragging: false,
17234
17235     
17236     constrainThumbs: true,
17237
17238     
17239     topThumbZIndex: 10000,
17240
17241     
17242     initComponent : function(){
17243         if(!Ext.isDefined(this.value)){
17244             this.value = this.minValue;
17245         }
17246
17247         
17248         this.thumbs = [];
17249
17250         Ext.slider.MultiSlider.superclass.initComponent.call(this);
17251
17252         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
17253         this.addEvents(
17254             
17255             'beforechange',
17256
17257             
17258             'change',
17259
17260             
17261             'changecomplete',
17262
17263             
17264             'dragstart',
17265
17266             
17267             'drag',
17268
17269             
17270             'dragend'
17271         );
17272
17273         
17274         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
17275
17276         var values = this.values;
17277
17278         for (var i=0; i < values.length; i++) {
17279             this.addThumb(values[i]);
17280         }
17281
17282         if(this.vertical){
17283             Ext.apply(this, Ext.slider.Vertical);
17284         }
17285     },
17286
17287     
17288     addThumb: function(value) {
17289         var thumb = new Ext.slider.Thumb({
17290             value    : value,
17291             slider   : this,
17292             index    : this.thumbs.length,
17293             constrain: this.constrainThumbs
17294         });
17295         this.thumbs.push(thumb);
17296
17297         
17298         if (this.rendered) thumb.render();
17299     },
17300
17301     
17302     promoteThumb: function(topThumb) {
17303         var thumbs = this.thumbs,
17304             zIndex, thumb;
17305
17306         for (var i = 0, j = thumbs.length; i < j; i++) {
17307             thumb = thumbs[i];
17308
17309             if (thumb == topThumb) {
17310                 zIndex = this.topThumbZIndex;
17311             } else {
17312                 zIndex = '';
17313             }
17314
17315             thumb.el.setStyle('zIndex', zIndex);
17316         }
17317     },
17318
17319     
17320     onRender : function() {
17321         this.autoEl = {
17322             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
17323             cn : {
17324                 cls: 'x-slider-end',
17325                 cn : {
17326                     cls:'x-slider-inner',
17327                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
17328                 }
17329             }
17330         };
17331
17332         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
17333
17334         this.endEl   = this.el.first();
17335         this.innerEl = this.endEl.first();
17336         this.focusEl = this.innerEl.child('.x-slider-focus');
17337
17338         
17339         for (var i=0; i < this.thumbs.length; i++) {
17340             this.thumbs[i].render();
17341         }
17342
17343         
17344         var thumb      = this.innerEl.child('.x-slider-thumb');
17345         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
17346
17347         this.initEvents();
17348     },
17349
17350     
17351     initEvents : function(){
17352         this.mon(this.el, {
17353             scope    : this,
17354             mousedown: this.onMouseDown,
17355             keydown  : this.onKeyDown
17356         });
17357
17358         this.focusEl.swallowEvent("click", true);
17359     },
17360
17361     
17362     onMouseDown : function(e){
17363         if(this.disabled){
17364             return;
17365         }
17366
17367         
17368         var thumbClicked = false;
17369         for (var i=0; i < this.thumbs.length; i++) {
17370             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
17371         }
17372
17373         if (this.clickToChange && !thumbClicked) {
17374             var local = this.innerEl.translatePoints(e.getXY());
17375             this.onClickChange(local);
17376         }
17377         this.focus();
17378     },
17379
17380     
17381     onClickChange : function(local) {
17382         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
17383             
17384             var thumb = this.getNearest(local, 'left'),
17385                 index = thumb.index;
17386
17387             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
17388         }
17389     },
17390
17391     
17392     getNearest: function(local, prop) {
17393         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
17394             clickValue = this.reverseValue(localValue),
17395             nearestDistance = (this.maxValue - this.minValue) + 5, 
17396             index = 0,
17397             nearest = null;
17398
17399         for (var i=0; i < this.thumbs.length; i++) {
17400             var thumb = this.thumbs[i],
17401                 value = thumb.value,
17402                 dist  = Math.abs(value - clickValue);
17403
17404             if (Math.abs(dist <= nearestDistance)) {
17405                 nearest = thumb;
17406                 index = i;
17407                 nearestDistance = dist;
17408             }
17409         }
17410         return nearest;
17411     },
17412
17413     
17414     onKeyDown : function(e){
17415         
17416         if(this.disabled || this.thumbs.length !== 1){
17417             e.preventDefault();
17418             return;
17419         }
17420         var k = e.getKey(),
17421             val;
17422         switch(k){
17423             case e.UP:
17424             case e.RIGHT:
17425                 e.stopEvent();
17426                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
17427                 this.setValue(0, val, undefined, true);
17428             break;
17429             case e.DOWN:
17430             case e.LEFT:
17431                 e.stopEvent();
17432                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
17433                 this.setValue(0, val, undefined, true);
17434             break;
17435             default:
17436                 e.preventDefault();
17437         }
17438     },
17439
17440     
17441     doSnap : function(value){
17442         if (!(this.increment && value)) {
17443             return value;
17444         }
17445         var newValue = value,
17446             inc = this.increment,
17447             m = value % inc;
17448         if (m != 0) {
17449             newValue -= m;
17450             if (m * 2 >= inc) {
17451                 newValue += inc;
17452             } else if (m * 2 < -inc) {
17453                 newValue -= inc;
17454             }
17455         }
17456         return newValue.constrain(this.minValue,  this.maxValue);
17457     },
17458
17459     
17460     afterRender : function(){
17461         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
17462
17463         for (var i=0; i < this.thumbs.length; i++) {
17464             var thumb = this.thumbs[i];
17465
17466             if (thumb.value !== undefined) {
17467                 var v = this.normalizeValue(thumb.value);
17468
17469                 if (v !== thumb.value) {
17470                     
17471                     this.setValue(i, v, false);
17472                 } else {
17473                     this.moveThumb(i, this.translateValue(v), false);
17474                 }
17475             }
17476         };
17477     },
17478
17479     
17480     getRatio : function(){
17481         var w = this.innerEl.getWidth(),
17482             v = this.maxValue - this.minValue;
17483         return v == 0 ? w : (w/v);
17484     },
17485
17486     
17487     normalizeValue : function(v){
17488         v = this.doSnap(v);
17489         v = Ext.util.Format.round(v, this.decimalPrecision);
17490         v = v.constrain(this.minValue, this.maxValue);
17491         return v;
17492     },
17493
17494     
17495     setMinValue : function(val){
17496         this.minValue = val;
17497         var i = 0,
17498             thumbs = this.thumbs,
17499             len = thumbs.length,
17500             t;
17501             
17502         for(; i < len; ++i){
17503             t = thumbs[i];
17504             t.value = t.value < val ? val : t.value;
17505         }
17506         this.syncThumb();
17507     },
17508
17509     
17510     setMaxValue : function(val){
17511         this.maxValue = val;
17512         var i = 0,
17513             thumbs = this.thumbs,
17514             len = thumbs.length,
17515             t;
17516             
17517         for(; i < len; ++i){
17518             t = thumbs[i];
17519             t.value = t.value > val ? val : t.value;
17520         }
17521         this.syncThumb();
17522     },
17523
17524     
17525     setValue : function(index, v, animate, changeComplete) {
17526         var thumb = this.thumbs[index],
17527             el    = thumb.el;
17528
17529         v = this.normalizeValue(v);
17530
17531         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
17532             thumb.value = v;
17533             if(this.rendered){
17534                 this.moveThumb(index, this.translateValue(v), animate !== false);
17535                 this.fireEvent('change', this, v, thumb);
17536                 if(changeComplete){
17537                     this.fireEvent('changecomplete', this, v, thumb);
17538                 }
17539             }
17540         }
17541     },
17542
17543     
17544     translateValue : function(v) {
17545         var ratio = this.getRatio();
17546         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
17547     },
17548
17549     
17550     reverseValue : function(pos){
17551         var ratio = this.getRatio();
17552         return (pos + (this.minValue * ratio)) / ratio;
17553     },
17554
17555     
17556     moveThumb: function(index, v, animate){
17557         var thumb = this.thumbs[index].el;
17558
17559         if(!animate || this.animate === false){
17560             thumb.setLeft(v);
17561         }else{
17562             thumb.shift({left: v, stopFx: true, duration:.35});
17563         }
17564     },
17565
17566     
17567     focus : function(){
17568         this.focusEl.focus(10);
17569     },
17570
17571     
17572     onResize : function(w, h){
17573         var thumbs = this.thumbs,
17574             len = thumbs.length,
17575             i = 0;
17576             
17577         
17578         for(; i < len; ++i){
17579             thumbs[i].el.stopFx();    
17580         }
17581         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
17582         this.syncThumb();
17583         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
17584     },
17585
17586     
17587     onDisable: function(){
17588         Ext.slider.MultiSlider.superclass.onDisable.call(this);
17589
17590         for (var i=0; i < this.thumbs.length; i++) {
17591             var thumb = this.thumbs[i],
17592                 el    = thumb.el;
17593
17594             thumb.disable();
17595
17596             if(Ext.isIE){
17597                 
17598                 
17599                 var xy = el.getXY();
17600                 el.hide();
17601
17602                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
17603
17604                 if (!this.thumbHolder) {
17605                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
17606                 }
17607
17608                 this.thumbHolder.show().setXY(xy);
17609             }
17610         }
17611     },
17612
17613     
17614     onEnable: function(){
17615         Ext.slider.MultiSlider.superclass.onEnable.call(this);
17616
17617         for (var i=0; i < this.thumbs.length; i++) {
17618             var thumb = this.thumbs[i],
17619                 el    = thumb.el;
17620
17621             thumb.enable();
17622
17623             if (Ext.isIE) {
17624                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
17625
17626                 if (this.thumbHolder) this.thumbHolder.hide();
17627
17628                 el.show();
17629                 this.syncThumb();
17630             }
17631         }
17632     },
17633
17634     
17635     syncThumb : function() {
17636         if (this.rendered) {
17637             for (var i=0; i < this.thumbs.length; i++) {
17638                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
17639             }
17640         }
17641     },
17642
17643     
17644     getValue : function(index) {
17645         return this.thumbs[index].value;
17646     },
17647
17648     
17649     getValues: function() {
17650         var values = [];
17651
17652         for (var i=0; i < this.thumbs.length; i++) {
17653             values.push(this.thumbs[i].value);
17654         }
17655
17656         return values;
17657     },
17658
17659     
17660     beforeDestroy : function(){
17661         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
17662         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
17663     }
17664 });
17665
17666 Ext.reg('multislider', Ext.slider.MultiSlider);
17667
17668
17669 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
17670     constructor: function(config) {
17671       config = config || {};
17672
17673       Ext.applyIf(config, {
17674           values: [config.value || 0]
17675       });
17676
17677       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
17678     },
17679
17680     
17681     getValue: function() {
17682         
17683         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
17684     },
17685
17686     
17687     setValue: function(value, animate) {
17688         var args = Ext.toArray(arguments),
17689             len  = args.length;
17690
17691         
17692         
17693         
17694         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
17695             args.unshift(0);
17696         }
17697
17698         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
17699     },
17700
17701     
17702     syncThumb : function() {
17703         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
17704     },
17705     
17706     
17707     getNearest : function(){
17708         
17709         return this.thumbs[0];    
17710     }
17711 });
17712
17713
17714 Ext.Slider = Ext.slider.SingleSlider;
17715
17716 Ext.reg('slider', Ext.slider.SingleSlider);
17717
17718
17719 Ext.slider.Vertical = {
17720     onResize : function(w, h){
17721         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
17722         this.syncThumb();
17723     },
17724
17725     getRatio : function(){
17726         var h = this.innerEl.getHeight(),
17727             v = this.maxValue - this.minValue;
17728         return h/v;
17729     },
17730
17731     moveThumb: function(index, v, animate) {
17732         var thumb = this.thumbs[index],
17733             el    = thumb.el;
17734
17735         if (!animate || this.animate === false) {
17736             el.setBottom(v);
17737         } else {
17738             el.shift({bottom: v, stopFx: true, duration:.35});
17739         }
17740     },
17741
17742     onClickChange : function(local) {
17743         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
17744             var thumb = this.getNearest(local, 'top'),
17745                 index = thumb.index,
17746                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
17747
17748             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
17749         }
17750     }
17751 };
17752
17753
17754 Ext.slider.Thumb.Vertical = {
17755     getNewValue: function() {
17756         var slider   = this.slider,
17757             innerEl  = slider.innerEl,
17758             pos      = innerEl.translatePoints(this.tracker.getXY()),
17759             bottom   = innerEl.getHeight() - pos.top;
17760
17761         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
17762     }
17763 };
17764
17765 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
17766    
17767     baseCls : 'x-progress',
17768     
17769     
17770     animate : false,
17771
17772     
17773     waitTimer : null,
17774
17775     
17776     initComponent : function(){
17777         Ext.ProgressBar.superclass.initComponent.call(this);
17778         this.addEvents(
17779             
17780             "update"
17781         );
17782     },
17783
17784     
17785     onRender : function(ct, position){
17786         var tpl = new Ext.Template(
17787             '<div class="{cls}-wrap">',
17788                 '<div class="{cls}-inner">',
17789                     '<div class="{cls}-bar">',
17790                         '<div class="{cls}-text">',
17791                             '<div>&#160;</div>',
17792                         '</div>',
17793                     '</div>',
17794                     '<div class="{cls}-text {cls}-text-back">',
17795                         '<div>&#160;</div>',
17796                     '</div>',
17797                 '</div>',
17798             '</div>'
17799         );
17800
17801         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
17802             : tpl.append(ct, {cls: this.baseCls}, true);
17803                 
17804         if(this.id){
17805             this.el.dom.id = this.id;
17806         }
17807         var inner = this.el.dom.firstChild;
17808         this.progressBar = Ext.get(inner.firstChild);
17809
17810         if(this.textEl){
17811             
17812             this.textEl = Ext.get(this.textEl);
17813             delete this.textTopEl;
17814         }else{
17815             
17816             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
17817             var textBackEl = Ext.get(inner.childNodes[1]);
17818             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
17819             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
17820             this.textEl.setWidth(inner.offsetWidth);
17821         }
17822         this.progressBar.setHeight(inner.offsetHeight);
17823     },
17824     
17825     
17826     afterRender : function(){
17827         Ext.ProgressBar.superclass.afterRender.call(this);
17828         if(this.value){
17829             this.updateProgress(this.value, this.text);
17830         }else{
17831             this.updateText(this.text);
17832         }
17833     },
17834
17835     
17836     updateProgress : function(value, text, animate){
17837         this.value = value || 0;
17838         if(text){
17839             this.updateText(text);
17840         }
17841         if(this.rendered && !this.isDestroyed){
17842             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
17843             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
17844             if(this.textTopEl){
17845                 
17846                 this.textTopEl.removeClass('x-hidden').setWidth(w);
17847             }
17848         }
17849         this.fireEvent('update', this, value, text);
17850         return this;
17851     },
17852
17853     
17854     wait : function(o){
17855         if(!this.waitTimer){
17856             var scope = this;
17857             o = o || {};
17858             this.updateText(o.text);
17859             this.waitTimer = Ext.TaskMgr.start({
17860                 run: function(i){
17861                     var inc = o.increment || 10;
17862                     i -= 1;
17863                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
17864                 },
17865                 interval: o.interval || 1000,
17866                 duration: o.duration,
17867                 onStop: function(){
17868                     if(o.fn){
17869                         o.fn.apply(o.scope || this);
17870                     }
17871                     this.reset();
17872                 },
17873                 scope: scope
17874             });
17875         }
17876         return this;
17877     },
17878
17879     
17880     isWaiting : function(){
17881         return this.waitTimer !== null;
17882     },
17883
17884     
17885     updateText : function(text){
17886         this.text = text || '&#160;';
17887         if(this.rendered){
17888             this.textEl.update(this.text);
17889         }
17890         return this;
17891     },
17892     
17893     
17894     syncProgressBar : function(){
17895         if(this.value){
17896             this.updateProgress(this.value, this.text);
17897         }
17898         return this;
17899     },
17900
17901     
17902     setSize : function(w, h){
17903         Ext.ProgressBar.superclass.setSize.call(this, w, h);
17904         if(this.textTopEl){
17905             var inner = this.el.dom.firstChild;
17906             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
17907         }
17908         this.syncProgressBar();
17909         return this;
17910     },
17911
17912     
17913     reset : function(hide){
17914         this.updateProgress(0);
17915         if(this.textTopEl){
17916             this.textTopEl.addClass('x-hidden');
17917         }
17918         this.clearTimer();
17919         if(hide === true){
17920             this.hide();
17921         }
17922         return this;
17923     },
17924     
17925     
17926     clearTimer : function(){
17927         if(this.waitTimer){
17928             this.waitTimer.onStop = null; 
17929             Ext.TaskMgr.stop(this.waitTimer);
17930             this.waitTimer = null;
17931         }
17932     },
17933     
17934     onDestroy: function(){
17935         this.clearTimer();
17936         if(this.rendered){
17937             if(this.textEl.isComposite){
17938                 this.textEl.clear();
17939             }
17940             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
17941         }
17942         Ext.ProgressBar.superclass.onDestroy.call(this);
17943     }
17944 });
17945 Ext.reg('progress', Ext.ProgressBar);
17946
17947 (function() {
17948
17949 var Event=Ext.EventManager;
17950 var Dom=Ext.lib.Dom;
17951
17952
17953 Ext.dd.DragDrop = function(id, sGroup, config) {
17954     if(id) {
17955         this.init(id, sGroup, config);
17956     }
17957 };
17958
17959 Ext.dd.DragDrop.prototype = {
17960
17961     
17962
17963     
17964     id: null,
17965
17966     
17967     config: null,
17968
17969     
17970     dragElId: null,
17971
17972     
17973     handleElId: null,
17974
17975     
17976     invalidHandleTypes: null,
17977
17978     
17979     invalidHandleIds: null,
17980
17981     
17982     invalidHandleClasses: null,
17983
17984     
17985     startPageX: 0,
17986
17987     
17988     startPageY: 0,
17989
17990     
17991     groups: null,
17992
17993     
17994     locked: false,
17995
17996     
17997     lock: function() {
17998         this.locked = true;
17999     },
18000
18001     
18002     moveOnly: false,
18003
18004     
18005     unlock: function() {
18006         this.locked = false;
18007     },
18008
18009     
18010     isTarget: true,
18011
18012     
18013     padding: null,
18014
18015     
18016     _domRef: null,
18017
18018     
18019     __ygDragDrop: true,
18020
18021     
18022     constrainX: false,
18023
18024     
18025     constrainY: false,
18026
18027     
18028     minX: 0,
18029
18030     
18031     maxX: 0,
18032
18033     
18034     minY: 0,
18035
18036     
18037     maxY: 0,
18038
18039     
18040     maintainOffset: false,
18041
18042     
18043     xTicks: null,
18044
18045     
18046     yTicks: null,
18047
18048     
18049     primaryButtonOnly: true,
18050
18051     
18052     available: false,
18053
18054     
18055     hasOuterHandles: false,
18056
18057     
18058     b4StartDrag: function(x, y) { },
18059
18060     
18061     startDrag: function(x, y) {  },
18062
18063     
18064     b4Drag: function(e) { },
18065
18066     
18067     onDrag: function(e) {  },
18068
18069     
18070     onDragEnter: function(e, id) {  },
18071
18072     
18073     b4DragOver: function(e) { },
18074
18075     
18076     onDragOver: function(e, id) {  },
18077
18078     
18079     b4DragOut: function(e) { },
18080
18081     
18082     onDragOut: function(e, id) {  },
18083
18084     
18085     b4DragDrop: function(e) { },
18086
18087     
18088     onDragDrop: function(e, id) {  },
18089
18090     
18091     onInvalidDrop: function(e) {  },
18092
18093     
18094     b4EndDrag: function(e) { },
18095
18096     
18097     endDrag: function(e) {  },
18098
18099     
18100     b4MouseDown: function(e) {  },
18101
18102     
18103     onMouseDown: function(e) {  },
18104
18105     
18106     onMouseUp: function(e) {  },
18107
18108     
18109     onAvailable: function () {
18110     },
18111
18112     
18113     defaultPadding : {left:0, right:0, top:0, bottom:0},
18114
18115     
18116     constrainTo : function(constrainTo, pad, inContent){
18117         if(Ext.isNumber(pad)){
18118             pad = {left: pad, right:pad, top:pad, bottom:pad};
18119         }
18120         pad = pad || this.defaultPadding;
18121         var b = Ext.get(this.getEl()).getBox(),
18122             ce = Ext.get(constrainTo),
18123             s = ce.getScroll(),
18124             c, 
18125             cd = ce.dom;
18126         if(cd == document.body){
18127             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
18128         }else{
18129             var xy = ce.getXY();
18130             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
18131         }
18132
18133
18134         var topSpace = b.y - c.y,
18135             leftSpace = b.x - c.x;
18136
18137         this.resetConstraints();
18138         this.setXConstraint(leftSpace - (pad.left||0), 
18139                 c.width - leftSpace - b.width - (pad.right||0), 
18140                                 this.xTickSize
18141         );
18142         this.setYConstraint(topSpace - (pad.top||0), 
18143                 c.height - topSpace - b.height - (pad.bottom||0), 
18144                                 this.yTickSize
18145         );
18146     },
18147
18148     
18149     getEl: function() {
18150         if (!this._domRef) {
18151             this._domRef = Ext.getDom(this.id);
18152         }
18153
18154         return this._domRef;
18155     },
18156
18157     
18158     getDragEl: function() {
18159         return Ext.getDom(this.dragElId);
18160     },
18161
18162     
18163     init: function(id, sGroup, config) {
18164         this.initTarget(id, sGroup, config);
18165         Event.on(this.id, "mousedown", this.handleMouseDown, this);
18166         
18167     },
18168
18169     
18170     initTarget: function(id, sGroup, config) {
18171
18172         
18173         this.config = config || {};
18174
18175         
18176         this.DDM = Ext.dd.DDM;
18177         
18178         this.groups = {};
18179
18180         
18181         
18182         if (typeof id !== "string") {
18183             id = Ext.id(id);
18184         }
18185
18186         
18187         this.id = id;
18188
18189         
18190         this.addToGroup((sGroup) ? sGroup : "default");
18191
18192         
18193         
18194         this.handleElId = id;
18195
18196         
18197         this.setDragElId(id);
18198
18199         
18200         this.invalidHandleTypes = { A: "A" };
18201         this.invalidHandleIds = {};
18202         this.invalidHandleClasses = [];
18203
18204         this.applyConfig();
18205
18206         this.handleOnAvailable();
18207     },
18208
18209     
18210     applyConfig: function() {
18211
18212         
18213         
18214         this.padding           = this.config.padding || [0, 0, 0, 0];
18215         this.isTarget          = (this.config.isTarget !== false);
18216         this.maintainOffset    = (this.config.maintainOffset);
18217         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18218
18219     },
18220
18221     
18222     handleOnAvailable: function() {
18223         this.available = true;
18224         this.resetConstraints();
18225         this.onAvailable();
18226     },
18227
18228      
18229     setPadding: function(iTop, iRight, iBot, iLeft) {
18230         
18231         if (!iRight && 0 !== iRight) {
18232             this.padding = [iTop, iTop, iTop, iTop];
18233         } else if (!iBot && 0 !== iBot) {
18234             this.padding = [iTop, iRight, iTop, iRight];
18235         } else {
18236             this.padding = [iTop, iRight, iBot, iLeft];
18237         }
18238     },
18239
18240     
18241     setInitPosition: function(diffX, diffY) {
18242         var el = this.getEl();
18243
18244         if (!this.DDM.verifyEl(el)) {
18245             return;
18246         }
18247
18248         var dx = diffX || 0;
18249         var dy = diffY || 0;
18250
18251         var p = Dom.getXY( el );
18252
18253         this.initPageX = p[0] - dx;
18254         this.initPageY = p[1] - dy;
18255
18256         this.lastPageX = p[0];
18257         this.lastPageY = p[1];
18258
18259         this.setStartPosition(p);
18260     },
18261
18262     
18263     setStartPosition: function(pos) {
18264         var p = pos || Dom.getXY( this.getEl() );
18265         this.deltaSetXY = null;
18266
18267         this.startPageX = p[0];
18268         this.startPageY = p[1];
18269     },
18270
18271     
18272     addToGroup: function(sGroup) {
18273         this.groups[sGroup] = true;
18274         this.DDM.regDragDrop(this, sGroup);
18275     },
18276
18277     
18278     removeFromGroup: function(sGroup) {
18279         if (this.groups[sGroup]) {
18280             delete this.groups[sGroup];
18281         }
18282
18283         this.DDM.removeDDFromGroup(this, sGroup);
18284     },
18285
18286     
18287     setDragElId: function(id) {
18288         this.dragElId = id;
18289     },
18290
18291     
18292     setHandleElId: function(id) {
18293         if (typeof id !== "string") {
18294             id = Ext.id(id);
18295         }
18296         this.handleElId = id;
18297         this.DDM.regHandle(this.id, id);
18298     },
18299
18300     
18301     setOuterHandleElId: function(id) {
18302         if (typeof id !== "string") {
18303             id = Ext.id(id);
18304         }
18305         Event.on(id, "mousedown",
18306                 this.handleMouseDown, this);
18307         this.setHandleElId(id);
18308
18309         this.hasOuterHandles = true;
18310     },
18311
18312     
18313     unreg: function() {
18314         Event.un(this.id, "mousedown",
18315                 this.handleMouseDown);
18316         this._domRef = null;
18317         this.DDM._remove(this);
18318     },
18319
18320     destroy : function(){
18321         this.unreg();
18322     },
18323
18324     
18325     isLocked: function() {
18326         return (this.DDM.isLocked() || this.locked);
18327     },
18328
18329     
18330     handleMouseDown: function(e, oDD){
18331         if (this.primaryButtonOnly && e.button != 0) {
18332             return;
18333         }
18334
18335         if (this.isLocked()) {
18336             return;
18337         }
18338
18339         this.DDM.refreshCache(this.groups);
18340
18341         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
18342         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
18343         } else {
18344             if (this.clickValidator(e)) {
18345
18346                 
18347                 this.setStartPosition();
18348
18349                 this.b4MouseDown(e);
18350                 this.onMouseDown(e);
18351
18352                 this.DDM.handleMouseDown(e, this);
18353
18354                 this.DDM.stopEvent(e);
18355             } else {
18356
18357
18358             }
18359         }
18360     },
18361
18362     clickValidator: function(e) {
18363         var target = e.getTarget();
18364         return ( this.isValidHandleChild(target) &&
18365                     (this.id == this.handleElId ||
18366                         this.DDM.handleWasClicked(target, this.id)) );
18367     },
18368
18369     
18370     addInvalidHandleType: function(tagName) {
18371         var type = tagName.toUpperCase();
18372         this.invalidHandleTypes[type] = type;
18373     },
18374
18375     
18376     addInvalidHandleId: function(id) {
18377         if (typeof id !== "string") {
18378             id = Ext.id(id);
18379         }
18380         this.invalidHandleIds[id] = id;
18381     },
18382
18383     
18384     addInvalidHandleClass: function(cssClass) {
18385         this.invalidHandleClasses.push(cssClass);
18386     },
18387
18388     
18389     removeInvalidHandleType: function(tagName) {
18390         var type = tagName.toUpperCase();
18391         
18392         delete this.invalidHandleTypes[type];
18393     },
18394
18395     
18396     removeInvalidHandleId: function(id) {
18397         if (typeof id !== "string") {
18398             id = Ext.id(id);
18399         }
18400         delete this.invalidHandleIds[id];
18401     },
18402
18403     
18404     removeInvalidHandleClass: function(cssClass) {
18405         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18406             if (this.invalidHandleClasses[i] == cssClass) {
18407                 delete this.invalidHandleClasses[i];
18408             }
18409         }
18410     },
18411
18412     
18413     isValidHandleChild: function(node) {
18414
18415         var valid = true;
18416         
18417         var nodeName;
18418         try {
18419             nodeName = node.nodeName.toUpperCase();
18420         } catch(e) {
18421             nodeName = node.nodeName;
18422         }
18423         valid = valid && !this.invalidHandleTypes[nodeName];
18424         valid = valid && !this.invalidHandleIds[node.id];
18425
18426         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18427             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
18428         }
18429
18430
18431         return valid;
18432
18433     },
18434
18435     
18436     setXTicks: function(iStartX, iTickSize) {
18437         this.xTicks = [];
18438         this.xTickSize = iTickSize;
18439
18440         var tickMap = {};
18441
18442         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18443             if (!tickMap[i]) {
18444                 this.xTicks[this.xTicks.length] = i;
18445                 tickMap[i] = true;
18446             }
18447         }
18448
18449         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18450             if (!tickMap[i]) {
18451                 this.xTicks[this.xTicks.length] = i;
18452                 tickMap[i] = true;
18453             }
18454         }
18455
18456         this.xTicks.sort(this.DDM.numericSort) ;
18457     },
18458
18459     
18460     setYTicks: function(iStartY, iTickSize) {
18461         this.yTicks = [];
18462         this.yTickSize = iTickSize;
18463
18464         var tickMap = {};
18465
18466         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18467             if (!tickMap[i]) {
18468                 this.yTicks[this.yTicks.length] = i;
18469                 tickMap[i] = true;
18470             }
18471         }
18472
18473         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18474             if (!tickMap[i]) {
18475                 this.yTicks[this.yTicks.length] = i;
18476                 tickMap[i] = true;
18477             }
18478         }
18479
18480         this.yTicks.sort(this.DDM.numericSort) ;
18481     },
18482
18483     
18484     setXConstraint: function(iLeft, iRight, iTickSize) {
18485         this.leftConstraint = iLeft;
18486         this.rightConstraint = iRight;
18487
18488         this.minX = this.initPageX - iLeft;
18489         this.maxX = this.initPageX + iRight;
18490         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
18491
18492         this.constrainX = true;
18493     },
18494
18495     
18496     clearConstraints: function() {
18497         this.constrainX = false;
18498         this.constrainY = false;
18499         this.clearTicks();
18500     },
18501
18502     
18503     clearTicks: function() {
18504         this.xTicks = null;
18505         this.yTicks = null;
18506         this.xTickSize = 0;
18507         this.yTickSize = 0;
18508     },
18509
18510     
18511     setYConstraint: function(iUp, iDown, iTickSize) {
18512         this.topConstraint = iUp;
18513         this.bottomConstraint = iDown;
18514
18515         this.minY = this.initPageY - iUp;
18516         this.maxY = this.initPageY + iDown;
18517         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
18518
18519         this.constrainY = true;
18520
18521     },
18522
18523     
18524     resetConstraints: function() {
18525         
18526         if (this.initPageX || this.initPageX === 0) {
18527             
18528             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
18529             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
18530
18531             this.setInitPosition(dx, dy);
18532
18533         
18534         } else {
18535             this.setInitPosition();
18536         }
18537
18538         if (this.constrainX) {
18539             this.setXConstraint( this.leftConstraint,
18540                                  this.rightConstraint,
18541                                  this.xTickSize        );
18542         }
18543
18544         if (this.constrainY) {
18545             this.setYConstraint( this.topConstraint,
18546                                  this.bottomConstraint,
18547                                  this.yTickSize         );
18548         }
18549     },
18550
18551     
18552     getTick: function(val, tickArray) {
18553         if (!tickArray) {
18554             
18555             
18556             return val;
18557         } else if (tickArray[0] >= val) {
18558             
18559             
18560             return tickArray[0];
18561         } else {
18562             for (var i=0, len=tickArray.length; i<len; ++i) {
18563                 var next = i + 1;
18564                 if (tickArray[next] && tickArray[next] >= val) {
18565                     var diff1 = val - tickArray[i];
18566                     var diff2 = tickArray[next] - val;
18567                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
18568                 }
18569             }
18570
18571             
18572             
18573             return tickArray[tickArray.length - 1];
18574         }
18575     },
18576
18577     
18578     toString: function() {
18579         return ("DragDrop " + this.id);
18580     }
18581
18582 };
18583
18584 })();
18585
18586
18587
18588
18589 if (!Ext.dd.DragDropMgr) {
18590
18591
18592 Ext.dd.DragDropMgr = function() {
18593
18594     var Event = Ext.EventManager;
18595
18596     return {
18597
18598         
18599         ids: {},
18600
18601         
18602         handleIds: {},
18603
18604         
18605         dragCurrent: null,
18606
18607         
18608         dragOvers: {},
18609
18610         
18611         deltaX: 0,
18612
18613         
18614         deltaY: 0,
18615
18616         
18617         preventDefault: true,
18618
18619         
18620         stopPropagation: true,
18621
18622         
18623         initialized: false,
18624
18625         
18626         locked: false,
18627
18628         
18629         init: function() {
18630             this.initialized = true;
18631         },
18632
18633         
18634         POINT: 0,
18635
18636         
18637         INTERSECT: 1,
18638
18639         
18640         mode: 0,
18641
18642         
18643         _execOnAll: function(sMethod, args) {
18644             for (var i in this.ids) {
18645                 for (var j in this.ids[i]) {
18646                     var oDD = this.ids[i][j];
18647                     if (! this.isTypeOfDD(oDD)) {
18648                         continue;
18649                     }
18650                     oDD[sMethod].apply(oDD, args);
18651                 }
18652             }
18653         },
18654
18655         
18656         _onLoad: function() {
18657
18658             this.init();
18659
18660
18661             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
18662             Event.on(document, "mousemove", this.handleMouseMove, this, true);
18663             Event.on(window,   "unload",    this._onUnload, this, true);
18664             Event.on(window,   "resize",    this._onResize, this, true);
18665             
18666
18667         },
18668
18669         
18670         _onResize: function(e) {
18671             this._execOnAll("resetConstraints", []);
18672         },
18673
18674         
18675         lock: function() { this.locked = true; },
18676
18677         
18678         unlock: function() { this.locked = false; },
18679
18680         
18681         isLocked: function() { return this.locked; },
18682
18683         
18684         locationCache: {},
18685
18686         
18687         useCache: true,
18688
18689         
18690         clickPixelThresh: 3,
18691
18692         
18693         clickTimeThresh: 350,
18694
18695         
18696         dragThreshMet: false,
18697
18698         
18699         clickTimeout: null,
18700
18701         
18702         startX: 0,
18703
18704         
18705         startY: 0,
18706
18707         
18708         regDragDrop: function(oDD, sGroup) {
18709             if (!this.initialized) { this.init(); }
18710
18711             if (!this.ids[sGroup]) {
18712                 this.ids[sGroup] = {};
18713             }
18714             this.ids[sGroup][oDD.id] = oDD;
18715         },
18716
18717         
18718         removeDDFromGroup: function(oDD, sGroup) {
18719             if (!this.ids[sGroup]) {
18720                 this.ids[sGroup] = {};
18721             }
18722
18723             var obj = this.ids[sGroup];
18724             if (obj && obj[oDD.id]) {
18725                 delete obj[oDD.id];
18726             }
18727         },
18728
18729         
18730         _remove: function(oDD) {
18731             for (var g in oDD.groups) {
18732                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
18733                     delete this.ids[g][oDD.id];
18734                 }
18735             }
18736             delete this.handleIds[oDD.id];
18737         },
18738
18739         
18740         regHandle: function(sDDId, sHandleId) {
18741             if (!this.handleIds[sDDId]) {
18742                 this.handleIds[sDDId] = {};
18743             }
18744             this.handleIds[sDDId][sHandleId] = sHandleId;
18745         },
18746
18747         
18748         isDragDrop: function(id) {
18749             return ( this.getDDById(id) ) ? true : false;
18750         },
18751
18752         
18753         getRelated: function(p_oDD, bTargetsOnly) {
18754             var oDDs = [];
18755             for (var i in p_oDD.groups) {
18756                 for (var j in this.ids[i]) {
18757                     var dd = this.ids[i][j];
18758                     if (! this.isTypeOfDD(dd)) {
18759                         continue;
18760                     }
18761                     if (!bTargetsOnly || dd.isTarget) {
18762                         oDDs[oDDs.length] = dd;
18763                     }
18764                 }
18765             }
18766
18767             return oDDs;
18768         },
18769
18770         
18771         isLegalTarget: function (oDD, oTargetDD) {
18772             var targets = this.getRelated(oDD, true);
18773             for (var i=0, len=targets.length;i<len;++i) {
18774                 if (targets[i].id == oTargetDD.id) {
18775                     return true;
18776                 }
18777             }
18778
18779             return false;
18780         },
18781
18782         
18783         isTypeOfDD: function (oDD) {
18784             return (oDD && oDD.__ygDragDrop);
18785         },
18786
18787         
18788         isHandle: function(sDDId, sHandleId) {
18789             return ( this.handleIds[sDDId] &&
18790                             this.handleIds[sDDId][sHandleId] );
18791         },
18792
18793         
18794         getDDById: function(id) {
18795             for (var i in this.ids) {
18796                 if (this.ids[i][id]) {
18797                     return this.ids[i][id];
18798                 }
18799             }
18800             return null;
18801         },
18802
18803         
18804         handleMouseDown: function(e, oDD) {
18805             if(Ext.QuickTips){
18806                 Ext.QuickTips.disable();
18807             }
18808             if(this.dragCurrent){
18809                 
18810                 
18811                 this.handleMouseUp(e);
18812             }
18813             
18814             this.currentTarget = e.getTarget();
18815             this.dragCurrent = oDD;
18816
18817             var el = oDD.getEl();
18818
18819             
18820             this.startX = e.getPageX();
18821             this.startY = e.getPageY();
18822
18823             this.deltaX = this.startX - el.offsetLeft;
18824             this.deltaY = this.startY - el.offsetTop;
18825
18826             this.dragThreshMet = false;
18827
18828             this.clickTimeout = setTimeout(
18829                     function() {
18830                         var DDM = Ext.dd.DDM;
18831                         DDM.startDrag(DDM.startX, DDM.startY);
18832                     },
18833                     this.clickTimeThresh );
18834         },
18835
18836         
18837         startDrag: function(x, y) {
18838             clearTimeout(this.clickTimeout);
18839             if (this.dragCurrent) {
18840                 this.dragCurrent.b4StartDrag(x, y);
18841                 this.dragCurrent.startDrag(x, y);
18842             }
18843             this.dragThreshMet = true;
18844         },
18845
18846         
18847         handleMouseUp: function(e) {
18848
18849             if(Ext.QuickTips){
18850                 Ext.QuickTips.enable();
18851             }
18852             if (! this.dragCurrent) {
18853                 return;
18854             }
18855
18856             clearTimeout(this.clickTimeout);
18857
18858             if (this.dragThreshMet) {
18859                 this.fireEvents(e, true);
18860             } else {
18861             }
18862
18863             this.stopDrag(e);
18864
18865             this.stopEvent(e);
18866         },
18867
18868         
18869         stopEvent: function(e){
18870             if(this.stopPropagation) {
18871                 e.stopPropagation();
18872             }
18873
18874             if (this.preventDefault) {
18875                 e.preventDefault();
18876             }
18877         },
18878
18879         
18880         stopDrag: function(e) {
18881             
18882             if (this.dragCurrent) {
18883                 if (this.dragThreshMet) {
18884                     this.dragCurrent.b4EndDrag(e);
18885                     this.dragCurrent.endDrag(e);
18886                 }
18887
18888                 this.dragCurrent.onMouseUp(e);
18889             }
18890
18891             this.dragCurrent = null;
18892             this.dragOvers = {};
18893         },
18894
18895         
18896         handleMouseMove: function(e) {
18897             if (! this.dragCurrent) {
18898                 return true;
18899             }
18900             
18901
18902             
18903             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
18904                 this.stopEvent(e);
18905                 return this.handleMouseUp(e);
18906             }
18907
18908             if (!this.dragThreshMet) {
18909                 var diffX = Math.abs(this.startX - e.getPageX());
18910                 var diffY = Math.abs(this.startY - e.getPageY());
18911                 if (diffX > this.clickPixelThresh ||
18912                             diffY > this.clickPixelThresh) {
18913                     this.startDrag(this.startX, this.startY);
18914                 }
18915             }
18916
18917             if (this.dragThreshMet) {
18918                 this.dragCurrent.b4Drag(e);
18919                 this.dragCurrent.onDrag(e);
18920                 if(!this.dragCurrent.moveOnly){
18921                     this.fireEvents(e, false);
18922                 }
18923             }
18924
18925             this.stopEvent(e);
18926
18927             return true;
18928         },
18929
18930         
18931         fireEvents: function(e, isDrop) {
18932             var dc = this.dragCurrent;
18933
18934             
18935             
18936             if (!dc || dc.isLocked()) {
18937                 return;
18938             }
18939
18940             var pt = e.getPoint();
18941
18942             
18943             var oldOvers = [];
18944
18945             var outEvts   = [];
18946             var overEvts  = [];
18947             var dropEvts  = [];
18948             var enterEvts = [];
18949
18950             
18951             
18952             for (var i in this.dragOvers) {
18953
18954                 var ddo = this.dragOvers[i];
18955
18956                 if (! this.isTypeOfDD(ddo)) {
18957                     continue;
18958                 }
18959
18960                 if (! this.isOverTarget(pt, ddo, this.mode)) {
18961                     outEvts.push( ddo );
18962                 }
18963
18964                 oldOvers[i] = true;
18965                 delete this.dragOvers[i];
18966             }
18967
18968             for (var sGroup in dc.groups) {
18969
18970                 if ("string" != typeof sGroup) {
18971                     continue;
18972                 }
18973
18974                 for (i in this.ids[sGroup]) {
18975                     var oDD = this.ids[sGroup][i];
18976                     if (! this.isTypeOfDD(oDD)) {
18977                         continue;
18978                     }
18979
18980                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
18981                         if (this.isOverTarget(pt, oDD, this.mode)) {
18982                             
18983                             if (isDrop) {
18984                                 dropEvts.push( oDD );
18985                             
18986                             } else {
18987
18988                                 
18989                                 if (!oldOvers[oDD.id]) {
18990                                     enterEvts.push( oDD );
18991                                 
18992                                 } else {
18993                                     overEvts.push( oDD );
18994                                 }
18995
18996                                 this.dragOvers[oDD.id] = oDD;
18997                             }
18998                         }
18999                     }
19000                 }
19001             }
19002
19003             if (this.mode) {
19004                 if (outEvts.length) {
19005                     dc.b4DragOut(e, outEvts);
19006                     dc.onDragOut(e, outEvts);
19007                 }
19008
19009                 if (enterEvts.length) {
19010                     dc.onDragEnter(e, enterEvts);
19011                 }
19012
19013                 if (overEvts.length) {
19014                     dc.b4DragOver(e, overEvts);
19015                     dc.onDragOver(e, overEvts);
19016                 }
19017
19018                 if (dropEvts.length) {
19019                     dc.b4DragDrop(e, dropEvts);
19020                     dc.onDragDrop(e, dropEvts);
19021                 }
19022
19023             } else {
19024                 
19025                 var len = 0;
19026                 for (i=0, len=outEvts.length; i<len; ++i) {
19027                     dc.b4DragOut(e, outEvts[i].id);
19028                     dc.onDragOut(e, outEvts[i].id);
19029                 }
19030
19031                 
19032                 for (i=0,len=enterEvts.length; i<len; ++i) {
19033                     
19034                     dc.onDragEnter(e, enterEvts[i].id);
19035                 }
19036
19037                 
19038                 for (i=0,len=overEvts.length; i<len; ++i) {
19039                     dc.b4DragOver(e, overEvts[i].id);
19040                     dc.onDragOver(e, overEvts[i].id);
19041                 }
19042
19043                 
19044                 for (i=0, len=dropEvts.length; i<len; ++i) {
19045                     dc.b4DragDrop(e, dropEvts[i].id);
19046                     dc.onDragDrop(e, dropEvts[i].id);
19047                 }
19048
19049             }
19050
19051             
19052             if (isDrop && !dropEvts.length) {
19053                 dc.onInvalidDrop(e);
19054             }
19055
19056         },
19057
19058         
19059         getBestMatch: function(dds) {
19060             var winner = null;
19061             
19062             
19063                
19064             
19065             
19066
19067             var len = dds.length;
19068
19069             if (len == 1) {
19070                 winner = dds[0];
19071             } else {
19072                 
19073                 for (var i=0; i<len; ++i) {
19074                     var dd = dds[i];
19075                     
19076                     
19077                     
19078                     if (dd.cursorIsOver) {
19079                         winner = dd;
19080                         break;
19081                     
19082                     } else {
19083                         if (!winner ||
19084                             winner.overlap.getArea() < dd.overlap.getArea()) {
19085                             winner = dd;
19086                         }
19087                     }
19088                 }
19089             }
19090
19091             return winner;
19092         },
19093
19094         
19095         refreshCache: function(groups) {
19096             for (var sGroup in groups) {
19097                 if ("string" != typeof sGroup) {
19098                     continue;
19099                 }
19100                 for (var i in this.ids[sGroup]) {
19101                     var oDD = this.ids[sGroup][i];
19102
19103                     if (this.isTypeOfDD(oDD)) {
19104                     
19105                         var loc = this.getLocation(oDD);
19106                         if (loc) {
19107                             this.locationCache[oDD.id] = loc;
19108                         } else {
19109                             delete this.locationCache[oDD.id];
19110                             
19111                             
19112                             
19113                         }
19114                     }
19115                 }
19116             }
19117         },
19118
19119         
19120         verifyEl: function(el) {
19121             if (el) {
19122                 var parent;
19123                 if(Ext.isIE){
19124                     try{
19125                         parent = el.offsetParent;
19126                     }catch(e){}
19127                 }else{
19128                     parent = el.offsetParent;
19129                 }
19130                 if (parent) {
19131                     return true;
19132                 }
19133             }
19134
19135             return false;
19136         },
19137
19138         
19139         getLocation: function(oDD) {
19140             if (! this.isTypeOfDD(oDD)) {
19141                 return null;
19142             }
19143
19144             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
19145
19146             try {
19147                 pos= Ext.lib.Dom.getXY(el);
19148             } catch (e) { }
19149
19150             if (!pos) {
19151                 return null;
19152             }
19153
19154             x1 = pos[0];
19155             x2 = x1 + el.offsetWidth;
19156             y1 = pos[1];
19157             y2 = y1 + el.offsetHeight;
19158
19159             t = y1 - oDD.padding[0];
19160             r = x2 + oDD.padding[1];
19161             b = y2 + oDD.padding[2];
19162             l = x1 - oDD.padding[3];
19163
19164             return new Ext.lib.Region( t, r, b, l );
19165         },
19166
19167         
19168         isOverTarget: function(pt, oTarget, intersect) {
19169             
19170             var loc = this.locationCache[oTarget.id];
19171             if (!loc || !this.useCache) {
19172                 loc = this.getLocation(oTarget);
19173                 this.locationCache[oTarget.id] = loc;
19174
19175             }
19176
19177             if (!loc) {
19178                 return false;
19179             }
19180
19181             oTarget.cursorIsOver = loc.contains( pt );
19182
19183             
19184             
19185             
19186             
19187             
19188             var dc = this.dragCurrent;
19189             if (!dc || !dc.getTargetCoord ||
19190                     (!intersect && !dc.constrainX && !dc.constrainY)) {
19191                 return oTarget.cursorIsOver;
19192             }
19193
19194             oTarget.overlap = null;
19195
19196             
19197             
19198             
19199             
19200             var pos = dc.getTargetCoord(pt.x, pt.y);
19201
19202             var el = dc.getDragEl();
19203             var curRegion = new Ext.lib.Region( pos.y,
19204                                                    pos.x + el.offsetWidth,
19205                                                    pos.y + el.offsetHeight,
19206                                                    pos.x );
19207
19208             var overlap = curRegion.intersect(loc);
19209
19210             if (overlap) {
19211                 oTarget.overlap = overlap;
19212                 return (intersect) ? true : oTarget.cursorIsOver;
19213             } else {
19214                 return false;
19215             }
19216         },
19217
19218         
19219         _onUnload: function(e, me) {
19220             Ext.dd.DragDropMgr.unregAll();
19221         },
19222
19223         
19224         unregAll: function() {
19225
19226             if (this.dragCurrent) {
19227                 this.stopDrag();
19228                 this.dragCurrent = null;
19229             }
19230
19231             this._execOnAll("unreg", []);
19232
19233             for (var i in this.elementCache) {
19234                 delete this.elementCache[i];
19235             }
19236
19237             this.elementCache = {};
19238             this.ids = {};
19239         },
19240
19241         
19242         elementCache: {},
19243
19244         
19245         getElWrapper: function(id) {
19246             var oWrapper = this.elementCache[id];
19247             if (!oWrapper || !oWrapper.el) {
19248                 oWrapper = this.elementCache[id] =
19249                     new this.ElementWrapper(Ext.getDom(id));
19250             }
19251             return oWrapper;
19252         },
19253
19254         
19255         getElement: function(id) {
19256             return Ext.getDom(id);
19257         },
19258
19259         
19260         getCss: function(id) {
19261             var el = Ext.getDom(id);
19262             return (el) ? el.style : null;
19263         },
19264
19265         
19266         ElementWrapper: function(el) {
19267                 
19268                 this.el = el || null;
19269                 
19270                 this.id = this.el && el.id;
19271                 
19272                 this.css = this.el && el.style;
19273             },
19274
19275         
19276         getPosX: function(el) {
19277             return Ext.lib.Dom.getX(el);
19278         },
19279
19280         
19281         getPosY: function(el) {
19282             return Ext.lib.Dom.getY(el);
19283         },
19284
19285         
19286         swapNode: function(n1, n2) {
19287             if (n1.swapNode) {
19288                 n1.swapNode(n2);
19289             } else {
19290                 var p = n2.parentNode;
19291                 var s = n2.nextSibling;
19292
19293                 if (s == n1) {
19294                     p.insertBefore(n1, n2);
19295                 } else if (n2 == n1.nextSibling) {
19296                     p.insertBefore(n2, n1);
19297                 } else {
19298                     n1.parentNode.replaceChild(n2, n1);
19299                     p.insertBefore(n1, s);
19300                 }
19301             }
19302         },
19303
19304         
19305         getScroll: function () {
19306             var t, l, dde=document.documentElement, db=document.body;
19307             if (dde && (dde.scrollTop || dde.scrollLeft)) {
19308                 t = dde.scrollTop;
19309                 l = dde.scrollLeft;
19310             } else if (db) {
19311                 t = db.scrollTop;
19312                 l = db.scrollLeft;
19313             } else {
19314
19315             }
19316             return { top: t, left: l };
19317         },
19318
19319         
19320         getStyle: function(el, styleProp) {
19321             return Ext.fly(el).getStyle(styleProp);
19322         },
19323
19324         
19325         getScrollTop: function () {
19326             return this.getScroll().top;
19327         },
19328
19329         
19330         getScrollLeft: function () {
19331             return this.getScroll().left;
19332         },
19333
19334         
19335         moveToEl: function (moveEl, targetEl) {
19336             var aCoord = Ext.lib.Dom.getXY(targetEl);
19337             Ext.lib.Dom.setXY(moveEl, aCoord);
19338         },
19339
19340         
19341         numericSort: function(a, b) {
19342             return (a - b);
19343         },
19344
19345         
19346         _timeoutCount: 0,
19347
19348         
19349         _addListeners: function() {
19350             var DDM = Ext.dd.DDM;
19351             if ( Ext.lib.Event && document ) {
19352                 DDM._onLoad();
19353             } else {
19354                 if (DDM._timeoutCount > 2000) {
19355                 } else {
19356                     setTimeout(DDM._addListeners, 10);
19357                     if (document && document.body) {
19358                         DDM._timeoutCount += 1;
19359                     }
19360                 }
19361             }
19362         },
19363
19364         
19365         handleWasClicked: function(node, id) {
19366             if (this.isHandle(id, node.id)) {
19367                 return true;
19368             } else {
19369                 
19370                 var p = node.parentNode;
19371
19372                 while (p) {
19373                     if (this.isHandle(id, p.id)) {
19374                         return true;
19375                     } else {
19376                         p = p.parentNode;
19377                     }
19378                 }
19379             }
19380
19381             return false;
19382         }
19383
19384     };
19385
19386 }();
19387
19388
19389 Ext.dd.DDM = Ext.dd.DragDropMgr;
19390 Ext.dd.DDM._addListeners();
19391
19392 }
19393
19394
19395 Ext.dd.DD = function(id, sGroup, config) {
19396     if (id) {
19397         this.init(id, sGroup, config);
19398     }
19399 };
19400
19401 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
19402
19403     
19404     scroll: true,
19405
19406     
19407     autoOffset: function(iPageX, iPageY) {
19408         var x = iPageX - this.startPageX;
19409         var y = iPageY - this.startPageY;
19410         this.setDelta(x, y);
19411     },
19412
19413     
19414     setDelta: function(iDeltaX, iDeltaY) {
19415         this.deltaX = iDeltaX;
19416         this.deltaY = iDeltaY;
19417     },
19418
19419     
19420     setDragElPos: function(iPageX, iPageY) {
19421         
19422         
19423
19424         var el = this.getDragEl();
19425         this.alignElWithMouse(el, iPageX, iPageY);
19426     },
19427
19428     
19429     alignElWithMouse: function(el, iPageX, iPageY) {
19430         var oCoord = this.getTargetCoord(iPageX, iPageY);
19431         var fly = el.dom ? el : Ext.fly(el, '_dd');
19432         if (!this.deltaSetXY) {
19433             var aCoord = [oCoord.x, oCoord.y];
19434             fly.setXY(aCoord);
19435             var newLeft = fly.getLeft(true);
19436             var newTop  = fly.getTop(true);
19437             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
19438         } else {
19439             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
19440         }
19441
19442         this.cachePosition(oCoord.x, oCoord.y);
19443         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
19444         return oCoord;
19445     },
19446
19447     
19448     cachePosition: function(iPageX, iPageY) {
19449         if (iPageX) {
19450             this.lastPageX = iPageX;
19451             this.lastPageY = iPageY;
19452         } else {
19453             var aCoord = Ext.lib.Dom.getXY(this.getEl());
19454             this.lastPageX = aCoord[0];
19455             this.lastPageY = aCoord[1];
19456         }
19457     },
19458
19459     
19460     autoScroll: function(x, y, h, w) {
19461
19462         if (this.scroll) {
19463             
19464             var clientH = Ext.lib.Dom.getViewHeight();
19465
19466             
19467             var clientW = Ext.lib.Dom.getViewWidth();
19468
19469             
19470             var st = this.DDM.getScrollTop();
19471
19472             
19473             var sl = this.DDM.getScrollLeft();
19474
19475             
19476             var bot = h + y;
19477
19478             
19479             var right = w + x;
19480
19481             
19482             
19483             
19484             var toBot = (clientH + st - y - this.deltaY);
19485
19486             
19487             var toRight = (clientW + sl - x - this.deltaX);
19488
19489
19490             
19491             
19492             var thresh = 40;
19493
19494             
19495             
19496             
19497             var scrAmt = (document.all) ? 80 : 30;
19498
19499             
19500             
19501             if ( bot > clientH && toBot < thresh ) {
19502                 window.scrollTo(sl, st + scrAmt);
19503             }
19504
19505             
19506             
19507             if ( y < st && st > 0 && y - st < thresh ) {
19508                 window.scrollTo(sl, st - scrAmt);
19509             }
19510
19511             
19512             
19513             if ( right > clientW && toRight < thresh ) {
19514                 window.scrollTo(sl + scrAmt, st);
19515             }
19516
19517             
19518             
19519             if ( x < sl && sl > 0 && x - sl < thresh ) {
19520                 window.scrollTo(sl - scrAmt, st);
19521             }
19522         }
19523     },
19524
19525     
19526     getTargetCoord: function(iPageX, iPageY) {
19527         var x = iPageX - this.deltaX;
19528         var y = iPageY - this.deltaY;
19529
19530         if (this.constrainX) {
19531             if (x < this.minX) { x = this.minX; }
19532             if (x > this.maxX) { x = this.maxX; }
19533         }
19534
19535         if (this.constrainY) {
19536             if (y < this.minY) { y = this.minY; }
19537             if (y > this.maxY) { y = this.maxY; }
19538         }
19539
19540         x = this.getTick(x, this.xTicks);
19541         y = this.getTick(y, this.yTicks);
19542
19543
19544         return {x:x, y:y};
19545     },
19546
19547     
19548     applyConfig: function() {
19549         Ext.dd.DD.superclass.applyConfig.call(this);
19550         this.scroll = (this.config.scroll !== false);
19551     },
19552
19553     
19554     b4MouseDown: function(e) {
19555         
19556         this.autoOffset(e.getPageX(),
19557                             e.getPageY());
19558     },
19559
19560     
19561     b4Drag: function(e) {
19562         this.setDragElPos(e.getPageX(),
19563                             e.getPageY());
19564     },
19565
19566     toString: function() {
19567         return ("DD " + this.id);
19568     }
19569
19570     
19571     
19572     
19573     
19574
19575 });
19576
19577 Ext.dd.DDProxy = function(id, sGroup, config) {
19578     if (id) {
19579         this.init(id, sGroup, config);
19580         this.initFrame();
19581     }
19582 };
19583
19584
19585 Ext.dd.DDProxy.dragElId = "ygddfdiv";
19586
19587 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
19588
19589     
19590     resizeFrame: true,
19591
19592     
19593     centerFrame: false,
19594
19595     
19596     createFrame: function() {
19597         var self = this;
19598         var body = document.body;
19599
19600         if (!body || !body.firstChild) {
19601             setTimeout( function() { self.createFrame(); }, 50 );
19602             return;
19603         }
19604
19605         var div = this.getDragEl();
19606
19607         if (!div) {
19608             div    = document.createElement("div");
19609             div.id = this.dragElId;
19610             var s  = div.style;
19611
19612             s.position   = "absolute";
19613             s.visibility = "hidden";
19614             s.cursor     = "move";
19615             s.border     = "2px solid #aaa";
19616             s.zIndex     = 999;
19617
19618             
19619             
19620             
19621             body.insertBefore(div, body.firstChild);
19622         }
19623     },
19624
19625     
19626     initFrame: function() {
19627         this.createFrame();
19628     },
19629
19630     applyConfig: function() {
19631         Ext.dd.DDProxy.superclass.applyConfig.call(this);
19632
19633         this.resizeFrame = (this.config.resizeFrame !== false);
19634         this.centerFrame = (this.config.centerFrame);
19635         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
19636     },
19637
19638     
19639     showFrame: function(iPageX, iPageY) {
19640         var el = this.getEl();
19641         var dragEl = this.getDragEl();
19642         var s = dragEl.style;
19643
19644         this._resizeProxy();
19645
19646         if (this.centerFrame) {
19647             this.setDelta( Math.round(parseInt(s.width,  10)/2),
19648                            Math.round(parseInt(s.height, 10)/2) );
19649         }
19650
19651         this.setDragElPos(iPageX, iPageY);
19652
19653         Ext.fly(dragEl).show();
19654     },
19655
19656     
19657     _resizeProxy: function() {
19658         if (this.resizeFrame) {
19659             var el = this.getEl();
19660             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
19661         }
19662     },
19663
19664     
19665     b4MouseDown: function(e) {
19666         var x = e.getPageX();
19667         var y = e.getPageY();
19668         this.autoOffset(x, y);
19669         this.setDragElPos(x, y);
19670     },
19671
19672     
19673     b4StartDrag: function(x, y) {
19674         
19675         this.showFrame(x, y);
19676     },
19677
19678     
19679     b4EndDrag: function(e) {
19680         Ext.fly(this.getDragEl()).hide();
19681     },
19682
19683     
19684     
19685     
19686     endDrag: function(e) {
19687
19688         var lel = this.getEl();
19689         var del = this.getDragEl();
19690
19691         
19692         del.style.visibility = "";
19693
19694         this.beforeMove();
19695         
19696         
19697         lel.style.visibility = "hidden";
19698         Ext.dd.DDM.moveToEl(lel, del);
19699         del.style.visibility = "hidden";
19700         lel.style.visibility = "";
19701
19702         this.afterDrag();
19703     },
19704
19705     beforeMove : function(){
19706
19707     },
19708
19709     afterDrag : function(){
19710
19711     },
19712
19713     toString: function() {
19714         return ("DDProxy " + this.id);
19715     }
19716
19717 });
19718
19719 Ext.dd.DDTarget = function(id, sGroup, config) {
19720     if (id) {
19721         this.initTarget(id, sGroup, config);
19722     }
19723 };
19724
19725
19726 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
19727     
19728     getDragEl: Ext.emptyFn,
19729     
19730     isValidHandleChild: Ext.emptyFn,
19731     
19732     startDrag: Ext.emptyFn,
19733     
19734     endDrag: Ext.emptyFn,
19735     
19736     onDrag: Ext.emptyFn,
19737     
19738     onDragDrop: Ext.emptyFn,
19739     
19740     onDragEnter: Ext.emptyFn,
19741     
19742     onDragOut: Ext.emptyFn,
19743     
19744     onDragOver: Ext.emptyFn,
19745     
19746     onInvalidDrop: Ext.emptyFn,
19747     
19748     onMouseDown: Ext.emptyFn,
19749     
19750     onMouseUp: Ext.emptyFn,
19751     
19752     setXConstraint: Ext.emptyFn,
19753     
19754     setYConstraint: Ext.emptyFn,
19755     
19756     resetConstraints: Ext.emptyFn,
19757     
19758     clearConstraints: Ext.emptyFn,
19759     
19760     clearTicks: Ext.emptyFn,
19761     
19762     setInitPosition: Ext.emptyFn,
19763     
19764     setDragElId: Ext.emptyFn,
19765     
19766     setHandleElId: Ext.emptyFn,
19767     
19768     setOuterHandleElId: Ext.emptyFn,
19769     
19770     addInvalidHandleClass: Ext.emptyFn,
19771     
19772     addInvalidHandleId: Ext.emptyFn,
19773     
19774     addInvalidHandleType: Ext.emptyFn,
19775     
19776     removeInvalidHandleClass: Ext.emptyFn,
19777     
19778     removeInvalidHandleId: Ext.emptyFn,
19779     
19780     removeInvalidHandleType: Ext.emptyFn,
19781
19782     toString: function() {
19783         return ("DDTarget " + this.id);
19784     }
19785 });
19786 Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
19787         
19788     active: false,
19789         
19790     tolerance: 5,
19791         
19792     autoStart: false,
19793     
19794     constructor : function(config){
19795         Ext.apply(this, config);
19796             this.addEvents(
19797                 
19798                 'mousedown',
19799                 
19800                 'mouseup',
19801                 
19802                 'mousemove',
19803                 
19804                 'dragstart',
19805                 
19806                 'dragend',
19807                 
19808                 'drag'
19809             );
19810         
19811             this.dragRegion = new Ext.lib.Region(0,0,0,0);
19812         
19813             if(this.el){
19814                 this.initEl(this.el);
19815             }
19816         Ext.dd.DragTracker.superclass.constructor.call(this, config);
19817     },
19818
19819     initEl: function(el){
19820         this.el = Ext.get(el);
19821         el.on('mousedown', this.onMouseDown, this,
19822                 this.delegate ? {delegate: this.delegate} : undefined);
19823     },
19824
19825     destroy : function(){
19826         this.el.un('mousedown', this.onMouseDown, this);
19827     },
19828
19829     onMouseDown: function(e, target){
19830         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
19831             this.startXY = this.lastXY = e.getXY();
19832             this.dragTarget = this.delegate ? target : this.el.dom;
19833             if(this.preventDefault !== false){
19834                 e.preventDefault();
19835             }
19836             var doc = Ext.getDoc();
19837             doc.on('mouseup', this.onMouseUp, this);
19838             doc.on('mousemove', this.onMouseMove, this);
19839             doc.on('selectstart', this.stopSelect, this);
19840             if(this.autoStart){
19841                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
19842             }
19843         }
19844     },
19845
19846     onMouseMove: function(e, target){
19847         
19848         if(this.active && Ext.isIE && !e.browserEvent.button){
19849             e.preventDefault();
19850             this.onMouseUp(e);
19851             return;
19852         }
19853
19854         e.preventDefault();
19855         var xy = e.getXY(), s = this.startXY;
19856         this.lastXY = xy;
19857         if(!this.active){
19858             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
19859                 this.triggerStart();
19860             }else{
19861                 return;
19862             }
19863         }
19864         this.fireEvent('mousemove', this, e);
19865         this.onDrag(e);
19866         this.fireEvent('drag', this, e);
19867     },
19868
19869     onMouseUp: function(e) {
19870         var doc = Ext.getDoc();
19871         doc.un('mousemove', this.onMouseMove, this);
19872         doc.un('mouseup', this.onMouseUp, this);
19873         doc.un('selectstart', this.stopSelect, this);
19874         e.preventDefault();
19875         this.clearStart();
19876         var wasActive = this.active;
19877         this.active = false;
19878         delete this.elRegion;
19879         this.fireEvent('mouseup', this, e);
19880         if(wasActive){
19881             this.onEnd(e);
19882             this.fireEvent('dragend', this, e);
19883         }
19884     },
19885
19886     triggerStart: function(isTimer) {
19887         this.clearStart();
19888         this.active = true;
19889         this.onStart(this.startXY);
19890         this.fireEvent('dragstart', this, this.startXY);
19891     },
19892
19893     clearStart : function() {
19894         if(this.timer){
19895             clearTimeout(this.timer);
19896             delete this.timer;
19897         }
19898     },
19899
19900     stopSelect : function(e) {
19901         e.stopEvent();
19902         return false;
19903     },
19904     
19905     
19906     onBeforeStart : function(e) {
19907
19908     },
19909
19910     
19911     onStart : function(xy) {
19912
19913     },
19914
19915     
19916     onDrag : function(e) {
19917
19918     },
19919
19920     
19921     onEnd : function(e) {
19922
19923     },
19924
19925     
19926     getDragTarget : function(){
19927         return this.dragTarget;
19928     },
19929
19930     getDragCt : function(){
19931         return this.el;
19932     },
19933
19934     getXY : function(constrain){
19935         return constrain ?
19936                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
19937     },
19938
19939     getOffset : function(constrain){
19940         var xy = this.getXY(constrain);
19941         var s = this.startXY;
19942         return [s[0]-xy[0], s[1]-xy[1]];
19943     },
19944
19945     constrainModes: {
19946         'point' : function(xy){
19947
19948             if(!this.elRegion){
19949                 this.elRegion = this.getDragCt().getRegion();
19950             }
19951
19952             var dr = this.dragRegion;
19953
19954             dr.left = xy[0];
19955             dr.top = xy[1];
19956             dr.right = xy[0];
19957             dr.bottom = xy[1];
19958
19959             dr.constrainTo(this.elRegion);
19960
19961             return [dr.left, dr.top];
19962         }
19963     }
19964 });
19965 Ext.dd.ScrollManager = function(){
19966     var ddm = Ext.dd.DragDropMgr;
19967     var els = {};
19968     var dragEl = null;
19969     var proc = {};
19970     
19971     var onStop = function(e){
19972         dragEl = null;
19973         clearProc();
19974     };
19975     
19976     var triggerRefresh = function(){
19977         if(ddm.dragCurrent){
19978              ddm.refreshCache(ddm.dragCurrent.groups);
19979         }
19980     };
19981     
19982     var doScroll = function(){
19983         if(ddm.dragCurrent){
19984             var dds = Ext.dd.ScrollManager;
19985             var inc = proc.el.ddScrollConfig ?
19986                       proc.el.ddScrollConfig.increment : dds.increment;
19987             if(!dds.animate){
19988                 if(proc.el.scroll(proc.dir, inc)){
19989                     triggerRefresh();
19990                 }
19991             }else{
19992                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
19993             }
19994         }
19995     };
19996     
19997     var clearProc = function(){
19998         if(proc.id){
19999             clearInterval(proc.id);
20000         }
20001         proc.id = 0;
20002         proc.el = null;
20003         proc.dir = "";
20004     };
20005     
20006     var startProc = function(el, dir){
20007         clearProc();
20008         proc.el = el;
20009         proc.dir = dir;
20010         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
20011                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
20012         proc.id = setInterval(doScroll, freq);
20013     };
20014     
20015     var onFire = function(e, isDrop){
20016         if(isDrop || !ddm.dragCurrent){ return; }
20017         var dds = Ext.dd.ScrollManager;
20018         if(!dragEl || dragEl != ddm.dragCurrent){
20019             dragEl = ddm.dragCurrent;
20020             
20021             dds.refreshCache();
20022         }
20023         
20024         var xy = Ext.lib.Event.getXY(e);
20025         var pt = new Ext.lib.Point(xy[0], xy[1]);
20026         for(var id in els){
20027             var el = els[id], r = el._region;
20028             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
20029             if(r && r.contains(pt) && el.isScrollable()){
20030                 if(r.bottom - pt.y <= c.vthresh){
20031                     if(proc.el != el){
20032                         startProc(el, "down");
20033                     }
20034                     return;
20035                 }else if(r.right - pt.x <= c.hthresh){
20036                     if(proc.el != el){
20037                         startProc(el, "left");
20038                     }
20039                     return;
20040                 }else if(pt.y - r.top <= c.vthresh){
20041                     if(proc.el != el){
20042                         startProc(el, "up");
20043                     }
20044                     return;
20045                 }else if(pt.x - r.left <= c.hthresh){
20046                     if(proc.el != el){
20047                         startProc(el, "right");
20048                     }
20049                     return;
20050                 }
20051             }
20052         }
20053         clearProc();
20054     };
20055     
20056     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
20057     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
20058     
20059     return {
20060         
20061         register : function(el){
20062             if(Ext.isArray(el)){
20063                 for(var i = 0, len = el.length; i < len; i++) {
20064                         this.register(el[i]);
20065                 }
20066             }else{
20067                 el = Ext.get(el);
20068                 els[el.id] = el;
20069             }
20070         },
20071         
20072         
20073         unregister : function(el){
20074             if(Ext.isArray(el)){
20075                 for(var i = 0, len = el.length; i < len; i++) {
20076                         this.unregister(el[i]);
20077                 }
20078             }else{
20079                 el = Ext.get(el);
20080                 delete els[el.id];
20081             }
20082         },
20083         
20084         
20085         vthresh : 25,
20086         
20087         hthresh : 25,
20088
20089         
20090         increment : 100,
20091         
20092         
20093         frequency : 500,
20094         
20095         
20096         animate: true,
20097         
20098         
20099         animDuration: .4,
20100         
20101         
20102         refreshCache : function(){
20103             for(var id in els){
20104                 if(typeof els[id] == 'object'){ 
20105                     els[id]._region = els[id].getRegion();
20106                 }
20107             }
20108         }
20109     };
20110 }();
20111 Ext.dd.Registry = function(){
20112     var elements = {}; 
20113     var handles = {}; 
20114     var autoIdSeed = 0;
20115
20116     var getId = function(el, autogen){
20117         if(typeof el == "string"){
20118             return el;
20119         }
20120         var id = el.id;
20121         if(!id && autogen !== false){
20122             id = "extdd-" + (++autoIdSeed);
20123             el.id = id;
20124         }
20125         return id;
20126     };
20127     
20128     return {
20129     
20130         register : function(el, data){
20131             data = data || {};
20132             if(typeof el == "string"){
20133                 el = document.getElementById(el);
20134             }
20135             data.ddel = el;
20136             elements[getId(el)] = data;
20137             if(data.isHandle !== false){
20138                 handles[data.ddel.id] = data;
20139             }
20140             if(data.handles){
20141                 var hs = data.handles;
20142                 for(var i = 0, len = hs.length; i < len; i++){
20143                         handles[getId(hs[i])] = data;
20144                 }
20145             }
20146         },
20147
20148     
20149         unregister : function(el){
20150             var id = getId(el, false);
20151             var data = elements[id];
20152             if(data){
20153                 delete elements[id];
20154                 if(data.handles){
20155                     var hs = data.handles;
20156                     for(var i = 0, len = hs.length; i < len; i++){
20157                         delete handles[getId(hs[i], false)];
20158                     }
20159                 }
20160             }
20161         },
20162
20163     
20164         getHandle : function(id){
20165             if(typeof id != "string"){ 
20166                 id = id.id;
20167             }
20168             return handles[id];
20169         },
20170
20171     
20172         getHandleFromEvent : function(e){
20173             var t = Ext.lib.Event.getTarget(e);
20174             return t ? handles[t.id] : null;
20175         },
20176
20177     
20178         getTarget : function(id){
20179             if(typeof id != "string"){ 
20180                 id = id.id;
20181             }
20182             return elements[id];
20183         },
20184
20185     
20186         getTargetFromEvent : function(e){
20187             var t = Ext.lib.Event.getTarget(e);
20188             return t ? elements[t.id] || handles[t.id] : null;
20189         }
20190     };
20191 }();
20192 Ext.dd.StatusProxy = function(config){
20193     Ext.apply(this, config);
20194     this.id = this.id || Ext.id();
20195     this.el = new Ext.Layer({
20196         dh: {
20197             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
20198                 {tag: "div", cls: "x-dd-drop-icon"},
20199                 {tag: "div", cls: "x-dd-drag-ghost"}
20200             ]
20201         }, 
20202         shadow: !config || config.shadow !== false
20203     });
20204     this.ghost = Ext.get(this.el.dom.childNodes[1]);
20205     this.dropStatus = this.dropNotAllowed;
20206 };
20207
20208 Ext.dd.StatusProxy.prototype = {
20209     
20210     dropAllowed : "x-dd-drop-ok",
20211     
20212     dropNotAllowed : "x-dd-drop-nodrop",
20213
20214     
20215     setStatus : function(cssClass){
20216         cssClass = cssClass || this.dropNotAllowed;
20217         if(this.dropStatus != cssClass){
20218             this.el.replaceClass(this.dropStatus, cssClass);
20219             this.dropStatus = cssClass;
20220         }
20221     },
20222
20223     
20224     reset : function(clearGhost){
20225         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
20226         this.dropStatus = this.dropNotAllowed;
20227         if(clearGhost){
20228             this.ghost.update("");
20229         }
20230     },
20231
20232     
20233     update : function(html){
20234         if(typeof html == "string"){
20235             this.ghost.update(html);
20236         }else{
20237             this.ghost.update("");
20238             html.style.margin = "0";
20239             this.ghost.dom.appendChild(html);
20240         }
20241         var el = this.ghost.dom.firstChild; 
20242         if(el){
20243             Ext.fly(el).setStyle('float', 'none');
20244         }
20245     },
20246
20247     
20248     getEl : function(){
20249         return this.el;
20250     },
20251
20252     
20253     getGhost : function(){
20254         return this.ghost;
20255     },
20256
20257     
20258     hide : function(clear){
20259         this.el.hide();
20260         if(clear){
20261             this.reset(true);
20262         }
20263     },
20264
20265     
20266     stop : function(){
20267         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
20268             this.anim.stop();
20269         }
20270     },
20271
20272     
20273     show : function(){
20274         this.el.show();
20275     },
20276
20277     
20278     sync : function(){
20279         this.el.sync();
20280     },
20281
20282     
20283     repair : function(xy, callback, scope){
20284         this.callback = callback;
20285         this.scope = scope;
20286         if(xy && this.animRepair !== false){
20287             this.el.addClass("x-dd-drag-repair");
20288             this.el.hideUnders(true);
20289             this.anim = this.el.shift({
20290                 duration: this.repairDuration || .5,
20291                 easing: 'easeOut',
20292                 xy: xy,
20293                 stopFx: true,
20294                 callback: this.afterRepair,
20295                 scope: this
20296             });
20297         }else{
20298             this.afterRepair();
20299         }
20300     },
20301
20302     
20303     afterRepair : function(){
20304         this.hide(true);
20305         if(typeof this.callback == "function"){
20306             this.callback.call(this.scope || this);
20307         }
20308         this.callback = null;
20309         this.scope = null;
20310     },
20311     
20312     destroy: function(){
20313         Ext.destroy(this.ghost, this.el);    
20314     }
20315 };
20316 Ext.dd.DragSource = function(el, config){
20317     this.el = Ext.get(el);
20318     if(!this.dragData){
20319         this.dragData = {};
20320     }
20321     
20322     Ext.apply(this, config);
20323     
20324     if(!this.proxy){
20325         this.proxy = new Ext.dd.StatusProxy();
20326     }
20327     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
20328           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
20329     
20330     this.dragging = false;
20331 };
20332
20333 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
20334     
20335     
20336     dropAllowed : "x-dd-drop-ok",
20337     
20338     dropNotAllowed : "x-dd-drop-nodrop",
20339
20340     
20341     getDragData : function(e){
20342         return this.dragData;
20343     },
20344
20345     
20346     onDragEnter : function(e, id){
20347         var target = Ext.dd.DragDropMgr.getDDById(id);
20348         this.cachedTarget = target;
20349         if(this.beforeDragEnter(target, e, id) !== false){
20350             if(target.isNotifyTarget){
20351                 var status = target.notifyEnter(this, e, this.dragData);
20352                 this.proxy.setStatus(status);
20353             }else{
20354                 this.proxy.setStatus(this.dropAllowed);
20355             }
20356             
20357             if(this.afterDragEnter){
20358                 
20359                 this.afterDragEnter(target, e, id);
20360             }
20361         }
20362     },
20363
20364     
20365     beforeDragEnter : function(target, e, id){
20366         return true;
20367     },
20368
20369     
20370     alignElWithMouse: function() {
20371         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
20372         this.proxy.sync();
20373     },
20374
20375     
20376     onDragOver : function(e, id){
20377         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20378         if(this.beforeDragOver(target, e, id) !== false){
20379             if(target.isNotifyTarget){
20380                 var status = target.notifyOver(this, e, this.dragData);
20381                 this.proxy.setStatus(status);
20382             }
20383
20384             if(this.afterDragOver){
20385                 
20386                 this.afterDragOver(target, e, id);
20387             }
20388         }
20389     },
20390
20391     
20392     beforeDragOver : function(target, e, id){
20393         return true;
20394     },
20395
20396     
20397     onDragOut : function(e, id){
20398         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20399         if(this.beforeDragOut(target, e, id) !== false){
20400             if(target.isNotifyTarget){
20401                 target.notifyOut(this, e, this.dragData);
20402             }
20403             this.proxy.reset();
20404             if(this.afterDragOut){
20405                 
20406                 this.afterDragOut(target, e, id);
20407             }
20408         }
20409         this.cachedTarget = null;
20410     },
20411
20412     
20413     beforeDragOut : function(target, e, id){
20414         return true;
20415     },
20416     
20417     
20418     onDragDrop : function(e, id){
20419         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20420         if(this.beforeDragDrop(target, e, id) !== false){
20421             if(target.isNotifyTarget){
20422                 if(target.notifyDrop(this, e, this.dragData)){ 
20423                     this.onValidDrop(target, e, id);
20424                 }else{
20425                     this.onInvalidDrop(target, e, id);
20426                 }
20427             }else{
20428                 this.onValidDrop(target, e, id);
20429             }
20430             
20431             if(this.afterDragDrop){
20432                 
20433                 this.afterDragDrop(target, e, id);
20434             }
20435         }
20436         delete this.cachedTarget;
20437     },
20438
20439     
20440     beforeDragDrop : function(target, e, id){
20441         return true;
20442     },
20443
20444     
20445     onValidDrop : function(target, e, id){
20446         this.hideProxy();
20447         if(this.afterValidDrop){
20448             
20449             this.afterValidDrop(target, e, id);
20450         }
20451     },
20452
20453     
20454     getRepairXY : function(e, data){
20455         return this.el.getXY();  
20456     },
20457
20458     
20459     onInvalidDrop : function(target, e, id){
20460         this.beforeInvalidDrop(target, e, id);
20461         if(this.cachedTarget){
20462             if(this.cachedTarget.isNotifyTarget){
20463                 this.cachedTarget.notifyOut(this, e, this.dragData);
20464             }
20465             this.cacheTarget = null;
20466         }
20467         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
20468
20469         if(this.afterInvalidDrop){
20470             
20471             this.afterInvalidDrop(e, id);
20472         }
20473     },
20474
20475     
20476     afterRepair : function(){
20477         if(Ext.enableFx){
20478             this.el.highlight(this.hlColor || "c3daf9");
20479         }
20480         this.dragging = false;
20481     },
20482
20483     
20484     beforeInvalidDrop : function(target, e, id){
20485         return true;
20486     },
20487
20488     
20489     handleMouseDown : function(e){
20490         if(this.dragging) {
20491             return;
20492         }
20493         var data = this.getDragData(e);
20494         if(data && this.onBeforeDrag(data, e) !== false){
20495             this.dragData = data;
20496             this.proxy.stop();
20497             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
20498         } 
20499     },
20500
20501     
20502     onBeforeDrag : function(data, e){
20503         return true;
20504     },
20505
20506     
20507     onStartDrag : Ext.emptyFn,
20508
20509     
20510     startDrag : function(x, y){
20511         this.proxy.reset();
20512         this.dragging = true;
20513         this.proxy.update("");
20514         this.onInitDrag(x, y);
20515         this.proxy.show();
20516     },
20517
20518     
20519     onInitDrag : function(x, y){
20520         var clone = this.el.dom.cloneNode(true);
20521         clone.id = Ext.id(); 
20522         this.proxy.update(clone);
20523         this.onStartDrag(x, y);
20524         return true;
20525     },
20526
20527     
20528     getProxy : function(){
20529         return this.proxy;  
20530     },
20531
20532     
20533     hideProxy : function(){
20534         this.proxy.hide();  
20535         this.proxy.reset(true);
20536         this.dragging = false;
20537     },
20538
20539     
20540     triggerCacheRefresh : function(){
20541         Ext.dd.DDM.refreshCache(this.groups);
20542     },
20543
20544     
20545     b4EndDrag: function(e) {
20546     },
20547
20548     
20549     endDrag : function(e){
20550         this.onEndDrag(this.dragData, e);
20551     },
20552
20553     
20554     onEndDrag : function(data, e){
20555     },
20556     
20557     
20558     autoOffset : function(x, y) {
20559         this.setDelta(-12, -20);
20560     },
20561     
20562     destroy: function(){
20563         Ext.dd.DragSource.superclass.destroy.call(this);
20564         Ext.destroy(this.proxy);
20565     }
20566 });
20567 Ext.dd.DropTarget = function(el, config){
20568     this.el = Ext.get(el);
20569     
20570     Ext.apply(this, config);
20571     
20572     if(this.containerScroll){
20573         Ext.dd.ScrollManager.register(this.el);
20574     }
20575     
20576     Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
20577           {isTarget: true});
20578
20579 };
20580
20581 Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
20582     
20583     
20584     
20585     dropAllowed : "x-dd-drop-ok",
20586     
20587     dropNotAllowed : "x-dd-drop-nodrop",
20588
20589     
20590     isTarget : true,
20591
20592     
20593     isNotifyTarget : true,
20594
20595     
20596     notifyEnter : function(dd, e, data){
20597         if(this.overClass){
20598             this.el.addClass(this.overClass);
20599         }
20600         return this.dropAllowed;
20601     },
20602
20603     
20604     notifyOver : function(dd, e, data){
20605         return this.dropAllowed;
20606     },
20607
20608     
20609     notifyOut : function(dd, e, data){
20610         if(this.overClass){
20611             this.el.removeClass(this.overClass);
20612         }
20613     },
20614
20615     
20616     notifyDrop : function(dd, e, data){
20617         return false;
20618     }
20619 });
20620 Ext.dd.DragZone = function(el, config){
20621     Ext.dd.DragZone.superclass.constructor.call(this, el, config);
20622     if(this.containerScroll){
20623         Ext.dd.ScrollManager.register(this.el);
20624     }
20625 };
20626
20627 Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
20628     
20629     
20630     
20631
20632     
20633     getDragData : function(e){
20634         return Ext.dd.Registry.getHandleFromEvent(e);
20635     },
20636     
20637     
20638     onInitDrag : function(x, y){
20639         this.proxy.update(this.dragData.ddel.cloneNode(true));
20640         this.onStartDrag(x, y);
20641         return true;
20642     },
20643     
20644     
20645     afterRepair : function(){
20646         if(Ext.enableFx){
20647             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
20648         }
20649         this.dragging = false;
20650     },
20651
20652     
20653     getRepairXY : function(e){
20654         return Ext.Element.fly(this.dragData.ddel).getXY();  
20655     }
20656 });
20657 Ext.dd.DropZone = function(el, config){
20658     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
20659 };
20660
20661 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
20662     
20663     getTargetFromEvent : function(e){
20664         return Ext.dd.Registry.getTargetFromEvent(e);
20665     },
20666
20667     
20668     onNodeEnter : function(n, dd, e, data){
20669         
20670     },
20671
20672     
20673     onNodeOver : function(n, dd, e, data){
20674         return this.dropAllowed;
20675     },
20676
20677     
20678     onNodeOut : function(n, dd, e, data){
20679         
20680     },
20681
20682     
20683     onNodeDrop : function(n, dd, e, data){
20684         return false;
20685     },
20686
20687     
20688     onContainerOver : function(dd, e, data){
20689         return this.dropNotAllowed;
20690     },
20691
20692     
20693     onContainerDrop : function(dd, e, data){
20694         return false;
20695     },
20696
20697     
20698     notifyEnter : function(dd, e, data){
20699         return this.dropNotAllowed;
20700     },
20701
20702     
20703     notifyOver : function(dd, e, data){
20704         var n = this.getTargetFromEvent(e);
20705         if(!n){ 
20706             if(this.lastOverNode){
20707                 this.onNodeOut(this.lastOverNode, dd, e, data);
20708                 this.lastOverNode = null;
20709             }
20710             return this.onContainerOver(dd, e, data);
20711         }
20712         if(this.lastOverNode != n){
20713             if(this.lastOverNode){
20714                 this.onNodeOut(this.lastOverNode, dd, e, data);
20715             }
20716             this.onNodeEnter(n, dd, e, data);
20717             this.lastOverNode = n;
20718         }
20719         return this.onNodeOver(n, dd, e, data);
20720     },
20721
20722     
20723     notifyOut : function(dd, e, data){
20724         if(this.lastOverNode){
20725             this.onNodeOut(this.lastOverNode, dd, e, data);
20726             this.lastOverNode = null;
20727         }
20728     },
20729
20730     
20731     notifyDrop : function(dd, e, data){
20732         if(this.lastOverNode){
20733             this.onNodeOut(this.lastOverNode, dd, e, data);
20734             this.lastOverNode = null;
20735         }
20736         var n = this.getTargetFromEvent(e);
20737         return n ?
20738             this.onNodeDrop(n, dd, e, data) :
20739             this.onContainerDrop(dd, e, data);
20740     },
20741
20742     
20743     triggerCacheRefresh : function(){
20744         Ext.dd.DDM.refreshCache(this.groups);
20745     }  
20746 });
20747 Ext.Element.addMethods({
20748     
20749     initDD : function(group, config, overrides){
20750         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
20751         return Ext.apply(dd, overrides);
20752     },
20753
20754     
20755     initDDProxy : function(group, config, overrides){
20756         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
20757         return Ext.apply(dd, overrides);
20758     },
20759
20760     
20761     initDDTarget : function(group, config, overrides){
20762         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
20763         return Ext.apply(dd, overrides);
20764     }
20765 });
20766
20767 Ext.data.Api = (function() {
20768
20769     
20770     
20771     
20772     
20773     var validActions = {};
20774
20775     return {
20776         
20777         actions : {
20778             create  : 'create',
20779             read    : 'read',
20780             update  : 'update',
20781             destroy : 'destroy'
20782         },
20783
20784         
20785         restActions : {
20786             create  : 'POST',
20787             read    : 'GET',
20788             update  : 'PUT',
20789             destroy : 'DELETE'
20790         },
20791
20792         
20793         isAction : function(action) {
20794             return (Ext.data.Api.actions[action]) ? true : false;
20795         },
20796
20797         
20798         getVerb : function(name) {
20799             if (validActions[name]) {
20800                 return validActions[name];  
20801             }
20802             for (var verb in this.actions) {
20803                 if (this.actions[verb] === name) {
20804                     validActions[name] = verb;
20805                     break;
20806                 }
20807             }
20808             return (validActions[name] !== undefined) ? validActions[name] : null;
20809         },
20810
20811         
20812         isValid : function(api){
20813             var invalid = [];
20814             var crud = this.actions; 
20815             for (var action in api) {
20816                 if (!(action in crud)) {
20817                     invalid.push(action);
20818                 }
20819             }
20820             return (!invalid.length) ? true : invalid;
20821         },
20822
20823         
20824         hasUniqueUrl : function(proxy, verb) {
20825             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
20826             var unique = true;
20827             for (var action in proxy.api) {
20828                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
20829                     break;
20830                 }
20831             }
20832             return unique;
20833         },
20834
20835         
20836         prepare : function(proxy) {
20837             if (!proxy.api) {
20838                 proxy.api = {}; 
20839             }
20840             for (var verb in this.actions) {
20841                 var action = this.actions[verb];
20842                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
20843                 if (typeof(proxy.api[action]) == 'string') {
20844                     proxy.api[action] = {
20845                         url: proxy.api[action],
20846                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
20847                     };
20848                 }
20849             }
20850         },
20851
20852         
20853         restify : function(proxy) {
20854             proxy.restful = true;
20855             for (var verb in this.restActions) {
20856                 proxy.api[this.actions[verb]].method ||
20857                     (proxy.api[this.actions[verb]].method = this.restActions[verb]);
20858             }
20859             
20860             
20861             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
20862                 var reader = o.reader;
20863                 var res = new Ext.data.Response({
20864                     action: action,
20865                     raw: response
20866                 });
20867
20868                 switch (response.status) {
20869                     case 200:   
20870                         return true;
20871                         break;
20872                     case 201:   
20873                         if (Ext.isEmpty(res.raw.responseText)) {
20874                           res.success = true;
20875                         } else {
20876                           
20877                           return true;
20878                         }
20879                         break;
20880                     case 204:  
20881                         res.success = true;
20882                         res.data = null;
20883                         break;
20884                     default:
20885                         return true;
20886                         break;
20887                 }
20888                 if (res.success === true) {
20889                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
20890                 } else {
20891                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
20892                 }
20893                 o.request.callback.call(o.request.scope, res.data, res, res.success);
20894
20895                 return false;   
20896             }, proxy);
20897         }
20898     };
20899 })();
20900
20901
20902 Ext.data.Response = function(params, response) {
20903     Ext.apply(this, params, {
20904         raw: response
20905     });
20906 };
20907 Ext.data.Response.prototype = {
20908     message : null,
20909     success : false,
20910     status : null,
20911     root : null,
20912     raw : null,
20913
20914     getMessage : function() {
20915         return this.message;
20916     },
20917     getSuccess : function() {
20918         return this.success;
20919     },
20920     getStatus : function() {
20921         return this.status;
20922     },
20923     getRoot : function() {
20924         return this.root;
20925     },
20926     getRawResponse : function() {
20927         return this.raw;
20928     }
20929 };
20930
20931
20932 Ext.data.Api.Error = Ext.extend(Ext.Error, {
20933     constructor : function(message, arg) {
20934         this.arg = arg;
20935         Ext.Error.call(this, message);
20936     },
20937     name: 'Ext.data.Api'
20938 });
20939 Ext.apply(Ext.data.Api.Error.prototype, {
20940     lang: {
20941         'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
20942         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
20943         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
20944         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
20945     }
20946 });
20947
20948
20949
20950
20951 Ext.data.SortTypes = {
20952     
20953     none : function(s){
20954         return s;
20955     },
20956     
20957     
20958     stripTagsRE : /<\/?[^>]+>/gi,
20959     
20960     
20961     asText : function(s){
20962         return String(s).replace(this.stripTagsRE, "");
20963     },
20964     
20965     
20966     asUCText : function(s){
20967         return String(s).toUpperCase().replace(this.stripTagsRE, "");
20968     },
20969     
20970     
20971     asUCString : function(s) {
20972         return String(s).toUpperCase();
20973     },
20974     
20975     
20976     asDate : function(s) {
20977         if(!s){
20978             return 0;
20979         }
20980         if(Ext.isDate(s)){
20981             return s.getTime();
20982         }
20983         return Date.parse(String(s));
20984     },
20985     
20986     
20987     asFloat : function(s) {
20988         var val = parseFloat(String(s).replace(/,/g, ""));
20989         return isNaN(val) ? 0 : val;
20990     },
20991     
20992     
20993     asInt : function(s) {
20994         var val = parseInt(String(s).replace(/,/g, ""), 10);
20995         return isNaN(val) ? 0 : val;
20996     }
20997 };
20998 Ext.data.Record = function(data, id){
20999     
21000     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
21001     this.data = data || {};
21002 };
21003
21004
21005 Ext.data.Record.create = function(o){
21006     var f = Ext.extend(Ext.data.Record, {});
21007     var p = f.prototype;
21008     p.fields = new Ext.util.MixedCollection(false, function(field){
21009         return field.name;
21010     });
21011     for(var i = 0, len = o.length; i < len; i++){
21012         p.fields.add(new Ext.data.Field(o[i]));
21013     }
21014     f.getField = function(name){
21015         return p.fields.get(name);
21016     };
21017     return f;
21018 };
21019
21020 Ext.data.Record.PREFIX = 'ext-record';
21021 Ext.data.Record.AUTO_ID = 1;
21022 Ext.data.Record.EDIT = 'edit';
21023 Ext.data.Record.REJECT = 'reject';
21024 Ext.data.Record.COMMIT = 'commit';
21025
21026
21027
21028 Ext.data.Record.id = function(rec) {
21029     rec.phantom = true;
21030     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
21031 };
21032
21033 Ext.data.Record.prototype = {
21034     
21035     
21036     
21037     
21038     
21039     
21040     dirty : false,
21041     editing : false,
21042     error : null,
21043     
21044     modified : null,
21045     
21046     phantom : false,
21047
21048     
21049     join : function(store){
21050         
21051         this.store = store;
21052     },
21053
21054     
21055     set : function(name, value){
21056         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
21057         if(encode(this.data[name]) == encode(value)) {
21058             return;
21059         }        
21060         this.dirty = true;
21061         if(!this.modified){
21062             this.modified = {};
21063         }
21064         if(this.modified[name] === undefined){
21065             this.modified[name] = this.data[name];
21066         }
21067         this.data[name] = value;
21068         if(!this.editing){
21069             this.afterEdit();
21070         }
21071     },
21072
21073     
21074     afterEdit : function(){
21075         if (this.store != undefined && typeof this.store.afterEdit == "function") {
21076             this.store.afterEdit(this);
21077         }
21078     },
21079
21080     
21081     afterReject : function(){
21082         if(this.store){
21083             this.store.afterReject(this);
21084         }
21085     },
21086
21087     
21088     afterCommit : function(){
21089         if(this.store){
21090             this.store.afterCommit(this);
21091         }
21092     },
21093
21094     
21095     get : function(name){
21096         return this.data[name];
21097     },
21098
21099     
21100     beginEdit : function(){
21101         this.editing = true;
21102         this.modified = this.modified || {};
21103     },
21104
21105     
21106     cancelEdit : function(){
21107         this.editing = false;
21108         delete this.modified;
21109     },
21110
21111     
21112     endEdit : function(){
21113         this.editing = false;
21114         if(this.dirty){
21115             this.afterEdit();
21116         }
21117     },
21118
21119     
21120     reject : function(silent){
21121         var m = this.modified;
21122         for(var n in m){
21123             if(typeof m[n] != "function"){
21124                 this.data[n] = m[n];
21125             }
21126         }
21127         this.dirty = false;
21128         delete this.modified;
21129         this.editing = false;
21130         if(silent !== true){
21131             this.afterReject();
21132         }
21133     },
21134
21135     
21136     commit : function(silent){
21137         this.dirty = false;
21138         delete this.modified;
21139         this.editing = false;
21140         if(silent !== true){
21141             this.afterCommit();
21142         }
21143     },
21144
21145     
21146     getChanges : function(){
21147         var m = this.modified, cs = {};
21148         for(var n in m){
21149             if(m.hasOwnProperty(n)){
21150                 cs[n] = this.data[n];
21151             }
21152         }
21153         return cs;
21154     },
21155
21156     
21157     hasError : function(){
21158         return this.error !== null;
21159     },
21160
21161     
21162     clearError : function(){
21163         this.error = null;
21164     },
21165
21166     
21167     copy : function(newId) {
21168         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
21169     },
21170
21171     
21172     isModified : function(fieldName){
21173         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
21174     },
21175
21176     
21177     isValid : function() {
21178         return this.fields.find(function(f) {
21179             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
21180         },this) ? false : true;
21181     },
21182
21183     
21184     markDirty : function(){
21185         this.dirty = true;
21186         if(!this.modified){
21187             this.modified = {};
21188         }
21189         this.fields.each(function(f) {
21190             this.modified[f.name] = this.data[f.name];
21191         },this);
21192     }
21193 };
21194
21195 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
21196     
21197
21198     
21199     register : function(){
21200         for(var i = 0, s; (s = arguments[i]); i++){
21201             this.add(s);
21202         }
21203     },
21204
21205     
21206     unregister : function(){
21207         for(var i = 0, s; (s = arguments[i]); i++){
21208             this.remove(this.lookup(s));
21209         }
21210     },
21211
21212     
21213     lookup : function(id){
21214         if(Ext.isArray(id)){
21215             var fields = ['field1'], expand = !Ext.isArray(id[0]);
21216             if(!expand){
21217                 for(var i = 2, len = id[0].length; i <= len; ++i){
21218                     fields.push('field' + i);
21219                 }
21220             }
21221             return new Ext.data.ArrayStore({
21222                 fields: fields,
21223                 data: id,
21224                 expandData: expand,
21225                 autoDestroy: true,
21226                 autoCreated: true
21227
21228             });
21229         }
21230         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
21231     },
21232
21233     
21234     getKey : function(o){
21235          return o.storeId;
21236     }
21237 });
21238 Ext.data.Store = Ext.extend(Ext.util.Observable, {
21239     
21240     
21241     
21242     
21243     
21244     
21245     
21246     writer : undefined,
21247     
21248     
21249     
21250     remoteSort : false,
21251
21252     
21253     autoDestroy : false,
21254
21255     
21256     pruneModifiedRecords : false,
21257
21258     
21259     lastOptions : null,
21260
21261     
21262     autoSave : true,
21263
21264     
21265     batch : true,
21266
21267     
21268     restful: false,
21269
21270     
21271     paramNames : undefined,
21272
21273     
21274     defaultParamNames : {
21275         start : 'start',
21276         limit : 'limit',
21277         sort : 'sort',
21278         dir : 'dir'
21279     },
21280
21281     
21282     isDestroyed: false,
21283
21284     
21285     hasMultiSort: false,
21286
21287     
21288     batchKey : '_ext_batch_',
21289
21290     constructor : function(config){
21291         this.data = new Ext.util.MixedCollection(false);
21292         this.data.getKey = function(o){
21293             return o.id;
21294         };
21295
21296
21297         
21298         this.removed = [];
21299
21300         if(config && config.data){
21301             this.inlineData = config.data;
21302             delete config.data;
21303         }
21304
21305         Ext.apply(this, config);
21306
21307         
21308         this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
21309
21310         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
21311
21312         if((this.url || this.api) && !this.proxy){
21313             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
21314         }
21315         
21316         if (this.restful === true && this.proxy) {
21317             
21318             
21319             this.batch = false;
21320             Ext.data.Api.restify(this.proxy);
21321         }
21322
21323         if(this.reader){ 
21324             if(!this.recordType){
21325                 this.recordType = this.reader.recordType;
21326             }
21327             if(this.reader.onMetaChange){
21328                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
21329             }
21330             if (this.writer) { 
21331                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
21332                     this.writer = this.buildWriter(this.writer);
21333                 }
21334                 this.writer.meta = this.reader.meta;
21335                 this.pruneModifiedRecords = true;
21336             }
21337         }
21338
21339         
21340
21341         if(this.recordType){
21342             
21343             this.fields = this.recordType.prototype.fields;
21344         }
21345         this.modified = [];
21346
21347         this.addEvents(
21348             
21349             'datachanged',
21350             
21351             'metachange',
21352             
21353             'add',
21354             
21355             'remove',
21356             
21357             'update',
21358             
21359             'clear',
21360             
21361             'exception',
21362             
21363             'beforeload',
21364             
21365             'load',
21366             
21367             'loadexception',
21368             
21369             'beforewrite',
21370             
21371             'write',
21372             
21373             'beforesave',
21374             
21375             'save'
21376
21377         );
21378
21379         if(this.proxy){
21380             
21381             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
21382         }
21383         
21384         if (this.writer) {
21385             this.on({
21386                 scope: this,
21387                 add: this.createRecords,
21388                 remove: this.destroyRecord,
21389                 update: this.updateRecord,
21390                 clear: this.onClear
21391             });
21392         }
21393
21394         this.sortToggle = {};
21395         if(this.sortField){
21396             this.setDefaultSort(this.sortField, this.sortDir);
21397         }else if(this.sortInfo){
21398             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
21399         }
21400
21401         Ext.data.Store.superclass.constructor.call(this);
21402
21403         if(this.id){
21404             this.storeId = this.id;
21405             delete this.id;
21406         }
21407         if(this.storeId){
21408             Ext.StoreMgr.register(this);
21409         }
21410         if(this.inlineData){
21411             this.loadData(this.inlineData);
21412             delete this.inlineData;
21413         }else if(this.autoLoad){
21414             this.load.defer(10, this, [
21415                 typeof this.autoLoad == 'object' ?
21416                     this.autoLoad : undefined]);
21417         }
21418         
21419         this.batchCounter = 0;
21420         this.batches = {};
21421     },
21422
21423     
21424     buildWriter : function(config) {
21425         var klass = undefined,
21426             type = (config.format || 'json').toLowerCase();
21427         switch (type) {
21428             case 'json':
21429                 klass = Ext.data.JsonWriter;
21430                 break;
21431             case 'xml':
21432                 klass = Ext.data.XmlWriter;
21433                 break;
21434             default:
21435                 klass = Ext.data.JsonWriter;
21436         }
21437         return new klass(config);
21438     },
21439
21440     
21441     destroy : function(){
21442         if(!this.isDestroyed){
21443             if(this.storeId){
21444                 Ext.StoreMgr.unregister(this);
21445             }
21446             this.clearData();
21447             this.data = null;
21448             Ext.destroy(this.proxy);
21449             this.reader = this.writer = null;
21450             this.purgeListeners();
21451             this.isDestroyed = true;
21452         }
21453     },
21454
21455     
21456     add : function(records){
21457         records = [].concat(records);
21458         if(records.length < 1){
21459             return;
21460         }
21461         for(var i = 0, len = records.length; i < len; i++){
21462             records[i].join(this);
21463         }
21464         var index = this.data.length;
21465         this.data.addAll(records);
21466         if(this.snapshot){
21467             this.snapshot.addAll(records);
21468         }
21469         this.fireEvent('add', this, records, index);
21470     },
21471
21472     
21473     addSorted : function(record){
21474         var index = this.findInsertIndex(record);
21475         this.insert(index, record);
21476     },
21477
21478     
21479     remove : function(record){
21480         if(Ext.isArray(record)){
21481             Ext.each(record, function(r){
21482                 this.remove(r);
21483             }, this);
21484             return;
21485         }
21486         var index = this.data.indexOf(record);
21487         if(index > -1){
21488             record.join(null);
21489             this.data.removeAt(index);
21490         }
21491         if(this.pruneModifiedRecords){
21492             this.modified.remove(record);
21493         }
21494         if(this.snapshot){
21495             this.snapshot.remove(record);
21496         }
21497         if(index > -1){
21498             this.fireEvent('remove', this, record, index);
21499         }
21500     },
21501
21502     
21503     removeAt : function(index){
21504         this.remove(this.getAt(index));
21505     },
21506
21507     
21508     removeAll : function(silent){
21509         var items = [];
21510         this.each(function(rec){
21511             items.push(rec);
21512         });
21513         this.clearData();
21514         if(this.snapshot){
21515             this.snapshot.clear();
21516         }
21517         if(this.pruneModifiedRecords){
21518             this.modified = [];
21519         }
21520         if (silent !== true) {  
21521             this.fireEvent('clear', this, items);
21522         }
21523     },
21524
21525     
21526     onClear: function(store, records){
21527         Ext.each(records, function(rec, index){
21528             this.destroyRecord(this, rec, index);
21529         }, this);
21530     },
21531
21532     
21533     insert : function(index, records){
21534         records = [].concat(records);
21535         for(var i = 0, len = records.length; i < len; i++){
21536             this.data.insert(index, records[i]);
21537             records[i].join(this);
21538         }
21539         if(this.snapshot){
21540             this.snapshot.addAll(records);
21541         }
21542         this.fireEvent('add', this, records, index);
21543     },
21544
21545     
21546     indexOf : function(record){
21547         return this.data.indexOf(record);
21548     },
21549
21550     
21551     indexOfId : function(id){
21552         return this.data.indexOfKey(id);
21553     },
21554
21555     
21556     getById : function(id){
21557         return (this.snapshot || this.data).key(id);
21558     },
21559
21560     
21561     getAt : function(index){
21562         return this.data.itemAt(index);
21563     },
21564
21565     
21566     getRange : function(start, end){
21567         return this.data.getRange(start, end);
21568     },
21569
21570     
21571     storeOptions : function(o){
21572         o = Ext.apply({}, o);
21573         delete o.callback;
21574         delete o.scope;
21575         this.lastOptions = o;
21576     },
21577
21578     
21579     clearData: function(){
21580         this.data.each(function(rec) {
21581             rec.join(null);
21582         });
21583         this.data.clear();
21584     },
21585
21586     
21587     load : function(options) {
21588         options = Ext.apply({}, options);
21589         this.storeOptions(options);
21590         if(this.sortInfo && this.remoteSort){
21591             var pn = this.paramNames;
21592             options.params = Ext.apply({}, options.params);
21593             options.params[pn.sort] = this.sortInfo.field;
21594             options.params[pn.dir] = this.sortInfo.direction;
21595         }
21596         try {
21597             return this.execute('read', null, options); 
21598         } catch(e) {
21599             this.handleException(e);
21600             return false;
21601         }
21602     },
21603
21604     
21605     updateRecord : function(store, record, action) {
21606         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
21607             this.save();
21608         }
21609     },
21610
21611     
21612     createRecords : function(store, rs, index) {
21613         for (var i = 0, len = rs.length; i < len; i++) {
21614             if (rs[i].phantom && rs[i].isValid()) {
21615                 rs[i].markDirty();  
21616                 this.modified.push(rs[i]);  
21617             }
21618         }
21619         if (this.autoSave === true) {
21620             this.save();
21621         }
21622     },
21623
21624     
21625     destroyRecord : function(store, record, index) {
21626         if (this.modified.indexOf(record) != -1) {  
21627             this.modified.remove(record);
21628         }
21629         if (!record.phantom) {
21630             this.removed.push(record);
21631
21632             
21633             
21634             
21635             record.lastIndex = index;
21636
21637             if (this.autoSave === true) {
21638                 this.save();
21639             }
21640         }
21641     },
21642
21643     
21644     execute : function(action, rs, options,  batch) {
21645         
21646         if (!Ext.data.Api.isAction(action)) {
21647             throw new Ext.data.Api.Error('execute', action);
21648         }
21649         
21650         options = Ext.applyIf(options||{}, {
21651             params: {}
21652         });
21653         if(batch !== undefined){
21654             this.addToBatch(batch);
21655         }
21656         
21657         
21658         var doRequest = true;
21659
21660         if (action === 'read') {
21661             doRequest = this.fireEvent('beforeload', this, options);
21662             Ext.applyIf(options.params, this.baseParams);
21663         }
21664         else {
21665             
21666             
21667             if (this.writer.listful === true && this.restful !== true) {
21668                 rs = (Ext.isArray(rs)) ? rs : [rs];
21669             }
21670             
21671             else if (Ext.isArray(rs) && rs.length == 1) {
21672                 rs = rs.shift();
21673             }
21674             
21675             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
21676                 this.writer.apply(options.params, this.baseParams, action, rs);
21677             }
21678         }
21679         if (doRequest !== false) {
21680             
21681             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
21682                 options.params.xaction = action;    
21683             }
21684             
21685             
21686             
21687             
21688             
21689             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
21690         }
21691         return doRequest;
21692     },
21693
21694     
21695     save : function() {
21696         if (!this.writer) {
21697             throw new Ext.data.Store.Error('writer-undefined');
21698         }
21699
21700         var queue = [],
21701             len,
21702             trans,
21703             batch,
21704             data = {};
21705         
21706         if(this.removed.length){
21707             queue.push(['destroy', this.removed]);
21708         }
21709
21710         
21711         var rs = [].concat(this.getModifiedRecords());
21712         if(rs.length){
21713             
21714             var phantoms = [];
21715             for(var i = rs.length-1; i >= 0; i--){
21716                 if(rs[i].phantom === true){
21717                     var rec = rs.splice(i, 1).shift();
21718                     if(rec.isValid()){
21719                         phantoms.push(rec);
21720                     }
21721                 }else if(!rs[i].isValid()){ 
21722                     rs.splice(i,1);
21723                 }
21724             }
21725             
21726             if(phantoms.length){
21727                 queue.push(['create', phantoms]);
21728             }
21729
21730             
21731             if(rs.length){
21732                 queue.push(['update', rs]);
21733             }
21734         }
21735         len = queue.length;
21736         if(len){
21737             batch = ++this.batchCounter;
21738             for(var i = 0; i < len; ++i){
21739                 trans = queue[i];
21740                 data[trans[0]] = trans[1];
21741             }
21742             if(this.fireEvent('beforesave', this, data) !== false){
21743                 for(var i = 0; i < len; ++i){
21744                     trans = queue[i];
21745                     this.doTransaction(trans[0], trans[1], batch);
21746                 }
21747                 return batch;
21748             }
21749         }
21750         return -1;
21751     },
21752
21753     
21754     doTransaction : function(action, rs, batch) {
21755         function transaction(records) {
21756             try{
21757                 this.execute(action, records, undefined, batch);
21758             }catch (e){
21759                 this.handleException(e);
21760             }
21761         }
21762         if(this.batch === false){
21763             for(var i = 0, len = rs.length; i < len; i++){
21764                 transaction.call(this, rs[i]);
21765             }
21766         }else{
21767             transaction.call(this, rs);
21768         }
21769     },
21770
21771     
21772     addToBatch : function(batch){
21773         var b = this.batches,
21774             key = this.batchKey + batch,
21775             o = b[key];
21776
21777         if(!o){
21778             b[key] = o = {
21779                 id: batch,
21780                 count: 0,
21781                 data: {}
21782             };
21783         }
21784         ++o.count;
21785     },
21786
21787     removeFromBatch : function(batch, action, data){
21788         var b = this.batches,
21789             key = this.batchKey + batch,
21790             o = b[key],
21791             data,
21792             arr;
21793
21794
21795         if(o){
21796             arr = o.data[action] || [];
21797             o.data[action] = arr.concat(data);
21798             if(o.count === 1){
21799                 data = o.data;
21800                 delete b[key];
21801                 this.fireEvent('save', this, batch, data);
21802             }else{
21803                 --o.count;
21804             }
21805         }
21806     },
21807
21808     
21809     
21810     createCallback : function(action, rs, batch) {
21811         var actions = Ext.data.Api.actions;
21812         return (action == 'read') ? this.loadRecords : function(data, response, success) {
21813             
21814             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
21815             
21816             if (success === true) {
21817                 this.fireEvent('write', this, action, data, response, rs);
21818             }
21819             this.removeFromBatch(batch, action, data);
21820         };
21821     },
21822
21823     
21824     
21825     
21826     clearModified : function(rs) {
21827         if (Ext.isArray(rs)) {
21828             for (var n=rs.length-1;n>=0;n--) {
21829                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
21830             }
21831         } else {
21832             this.modified.splice(this.modified.indexOf(rs), 1);
21833         }
21834     },
21835
21836     
21837     reMap : function(record) {
21838         if (Ext.isArray(record)) {
21839             for (var i = 0, len = record.length; i < len; i++) {
21840                 this.reMap(record[i]);
21841             }
21842         } else {
21843             delete this.data.map[record._phid];
21844             this.data.map[record.id] = record;
21845             var index = this.data.keys.indexOf(record._phid);
21846             this.data.keys.splice(index, 1, record.id);
21847             delete record._phid;
21848         }
21849     },
21850
21851     
21852     onCreateRecords : function(success, rs, data) {
21853         if (success === true) {
21854             try {
21855                 this.reader.realize(rs, data);
21856                 this.reMap(rs);
21857             }
21858             catch (e) {
21859                 this.handleException(e);
21860                 if (Ext.isArray(rs)) {
21861                     
21862                     this.onCreateRecords(success, rs, data);
21863                 }
21864             }
21865         }
21866     },
21867
21868     
21869     onUpdateRecords : function(success, rs, data) {
21870         if (success === true) {
21871             try {
21872                 this.reader.update(rs, data);
21873             } catch (e) {
21874                 this.handleException(e);
21875                 if (Ext.isArray(rs)) {
21876                     
21877                     this.onUpdateRecords(success, rs, data);
21878                 }
21879             }
21880         }
21881     },
21882
21883     
21884     onDestroyRecords : function(success, rs, data) {
21885         
21886         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
21887         for (var i=0,len=rs.length;i<len;i++) {
21888             this.removed.splice(this.removed.indexOf(rs[i]), 1);
21889         }
21890         if (success === false) {
21891             
21892             
21893             for (i=rs.length-1;i>=0;i--) {
21894                 this.insert(rs[i].lastIndex, rs[i]);    
21895             }
21896         }
21897     },
21898
21899     
21900     handleException : function(e) {
21901         
21902         Ext.handleError(e);
21903     },
21904
21905     
21906     reload : function(options){
21907         this.load(Ext.applyIf(options||{}, this.lastOptions));
21908     },
21909
21910     
21911     
21912     loadRecords : function(o, options, success){
21913         if (this.isDestroyed === true) {
21914             return;
21915         }
21916         if(!o || success === false){
21917             if(success !== false){
21918                 this.fireEvent('load', this, [], options);
21919             }
21920             if(options.callback){
21921                 options.callback.call(options.scope || this, [], options, false, o);
21922             }
21923             return;
21924         }
21925         var r = o.records, t = o.totalRecords || r.length;
21926         if(!options || options.add !== true){
21927             if(this.pruneModifiedRecords){
21928                 this.modified = [];
21929             }
21930             for(var i = 0, len = r.length; i < len; i++){
21931                 r[i].join(this);
21932             }
21933             if(this.snapshot){
21934                 this.data = this.snapshot;
21935                 delete this.snapshot;
21936             }
21937             this.clearData();
21938             this.data.addAll(r);
21939             this.totalLength = t;
21940             this.applySort();
21941             this.fireEvent('datachanged', this);
21942         }else{
21943             this.totalLength = Math.max(t, this.data.length+r.length);
21944             this.add(r);
21945         }
21946         this.fireEvent('load', this, r, options);
21947         if(options.callback){
21948             options.callback.call(options.scope || this, r, options, true);
21949         }
21950     },
21951
21952     
21953     loadData : function(o, append){
21954         var r = this.reader.readRecords(o);
21955         this.loadRecords(r, {add: append}, true);
21956     },
21957
21958     
21959     getCount : function(){
21960         return this.data.length || 0;
21961     },
21962
21963     
21964     getTotalCount : function(){
21965         return this.totalLength || 0;
21966     },
21967
21968     
21969     getSortState : function(){
21970         return this.sortInfo;
21971     },
21972
21973     
21974     applySort : function(){
21975         if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
21976             this.sortData();
21977         }
21978     },
21979
21980     
21981     sortData : function() {
21982         var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
21983             direction = sortInfo.direction || "ASC",
21984             sorters   = sortInfo.sorters,
21985             sortFns   = [];
21986
21987         
21988         if (!this.hasMultiSort) {
21989             sorters = [{direction: direction, field: sortInfo.field}];
21990         }
21991
21992         
21993         for (var i=0, j = sorters.length; i < j; i++) {
21994             sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
21995         }
21996         
21997         if (sortFns.length == 0) {
21998             return;
21999         }
22000
22001         
22002         
22003         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
22004
22005         
22006         var fn = function(r1, r2) {
22007           var result = sortFns[0].call(this, r1, r2);
22008
22009           
22010           if (sortFns.length > 1) {
22011               for (var i=1, j = sortFns.length; i < j; i++) {
22012                   result = result || sortFns[i].call(this, r1, r2);
22013               }
22014           }
22015
22016           return directionModifier * result;
22017         };
22018
22019         
22020         this.data.sort(direction, fn);
22021         if (this.snapshot && this.snapshot != this.data) {
22022             this.snapshot.sort(direction, fn);
22023         }
22024     },
22025
22026     
22027     createSortFunction: function(field, direction) {
22028         direction = direction || "ASC";
22029         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
22030
22031         var sortType = this.fields.get(field).sortType;
22032
22033         
22034         
22035         return function(r1, r2) {
22036             var v1 = sortType(r1.data[field]),
22037                 v2 = sortType(r2.data[field]);
22038
22039             return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
22040         };
22041     },
22042
22043     
22044     setDefaultSort : function(field, dir) {
22045         dir = dir ? dir.toUpperCase() : 'ASC';
22046         this.sortInfo = {field: field, direction: dir};
22047         this.sortToggle[field] = dir;
22048     },
22049
22050     
22051     sort : function(fieldName, dir) {
22052         if (Ext.isArray(arguments[0])) {
22053             return this.multiSort.call(this, fieldName, dir);
22054         } else {
22055             return this.singleSort(fieldName, dir);
22056         }
22057     },
22058
22059     
22060     singleSort: function(fieldName, dir) {
22061         var field = this.fields.get(fieldName);
22062         if (!field) return false;
22063
22064         var name       = field.name,
22065             sortInfo   = this.sortInfo || null,
22066             sortToggle = this.sortToggle ? this.sortToggle[name] : null;
22067
22068         if (!dir) {
22069             if (sortInfo && sortInfo.field == name) { 
22070                 dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
22071             } else {
22072                 dir = field.sortDir;
22073             }
22074         }
22075
22076         this.sortToggle[name] = dir;
22077         this.sortInfo = {field: name, direction: dir};
22078         this.hasMultiSort = false;
22079
22080         if (this.remoteSort) {
22081             if (!this.load(this.lastOptions)) {
22082                 if (sortToggle) {
22083                     this.sortToggle[name] = sortToggle;
22084                 }
22085                 if (sortInfo) {
22086                     this.sortInfo = sortInfo;
22087                 }
22088             }
22089         } else {
22090             this.applySort();
22091             this.fireEvent('datachanged', this);
22092         }
22093     },
22094
22095     
22096     multiSort: function(sorters, direction) {
22097         this.hasMultiSort = true;
22098         direction = direction || "ASC";
22099
22100         
22101         if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
22102             direction = direction.toggle("ASC", "DESC");
22103         }
22104
22105         
22106         this.multiSortInfo = {
22107             sorters  : sorters,
22108             direction: direction
22109         };
22110         
22111         if (this.remoteSort) {
22112             this.singleSort(sorters[0].field, sorters[0].direction);
22113
22114         } else {
22115             this.applySort();
22116             this.fireEvent('datachanged', this);
22117         }
22118     },
22119
22120     
22121     each : function(fn, scope){
22122         this.data.each(fn, scope);
22123     },
22124
22125     
22126     getModifiedRecords : function(){
22127         return this.modified;
22128     },
22129
22130     
22131     sum : function(property, start, end){
22132         var rs = this.data.items, v = 0;
22133         start = start || 0;
22134         end = (end || end === 0) ? end : rs.length-1;
22135
22136         for(var i = start; i <= end; i++){
22137             v += (rs[i].data[property] || 0);
22138         }
22139         return v;
22140     },
22141
22142     
22143     createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
22144         if(Ext.isEmpty(value, false)){
22145             return false;
22146         }
22147         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
22148         return function(r) {
22149             return value.test(r.data[property]);
22150         };
22151     },
22152
22153     
22154     createMultipleFilterFn: function(filters) {
22155         return function(record) {
22156             var isMatch = true;
22157
22158             for (var i=0, j = filters.length; i < j; i++) {
22159                 var filter = filters[i],
22160                     fn     = filter.fn,
22161                     scope  = filter.scope;
22162
22163                 isMatch = isMatch && fn.call(scope, record);
22164             }
22165
22166             return isMatch;
22167         };
22168     },
22169
22170     
22171     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
22172         
22173         if (Ext.isObject(property)) {
22174             property = [property];
22175         }
22176
22177         if (Ext.isArray(property)) {
22178             var filters = [];
22179
22180             
22181             for (var i=0, j = property.length; i < j; i++) {
22182                 var filter = property[i],
22183                     func   = filter.fn,
22184                     scope  = filter.scope || this;
22185
22186                 
22187                 if (!Ext.isFunction(func)) {
22188                     func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
22189                 }
22190
22191                 filters.push({fn: func, scope: scope});
22192             }
22193
22194             var fn = this.createMultipleFilterFn(filters);
22195         } else {
22196             
22197             var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
22198         }
22199
22200         return fn ? this.filterBy(fn) : this.clearFilter();
22201     },
22202
22203     
22204     filterBy : function(fn, scope){
22205         this.snapshot = this.snapshot || this.data;
22206         this.data = this.queryBy(fn, scope||this);
22207         this.fireEvent('datachanged', this);
22208     },
22209
22210     
22211     clearFilter : function(suppressEvent){
22212         if(this.isFiltered()){
22213             this.data = this.snapshot;
22214             delete this.snapshot;
22215             if(suppressEvent !== true){
22216                 this.fireEvent('datachanged', this);
22217             }
22218         }
22219     },
22220
22221     
22222     isFiltered : function(){
22223         return !!this.snapshot && this.snapshot != this.data;
22224     },
22225
22226     
22227     query : function(property, value, anyMatch, caseSensitive){
22228         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
22229         return fn ? this.queryBy(fn) : this.data.clone();
22230     },
22231
22232     
22233     queryBy : function(fn, scope){
22234         var data = this.snapshot || this.data;
22235         return data.filterBy(fn, scope||this);
22236     },
22237
22238     
22239     find : function(property, value, start, anyMatch, caseSensitive){
22240         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
22241         return fn ? this.data.findIndexBy(fn, null, start) : -1;
22242     },
22243
22244     
22245     findExact: function(property, value, start){
22246         return this.data.findIndexBy(function(rec){
22247             return rec.get(property) === value;
22248         }, this, start);
22249     },
22250
22251     
22252     findBy : function(fn, scope, start){
22253         return this.data.findIndexBy(fn, scope, start);
22254     },
22255
22256     
22257     collect : function(dataIndex, allowNull, bypassFilter){
22258         var d = (bypassFilter === true && this.snapshot) ?
22259                 this.snapshot.items : this.data.items;
22260         var v, sv, r = [], l = {};
22261         for(var i = 0, len = d.length; i < len; i++){
22262             v = d[i].data[dataIndex];
22263             sv = String(v);
22264             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
22265                 l[sv] = true;
22266                 r[r.length] = v;
22267             }
22268         }
22269         return r;
22270     },
22271
22272     
22273     afterEdit : function(record){
22274         if(this.modified.indexOf(record) == -1){
22275             this.modified.push(record);
22276         }
22277         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
22278     },
22279
22280     
22281     afterReject : function(record){
22282         this.modified.remove(record);
22283         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
22284     },
22285
22286     
22287     afterCommit : function(record){
22288         this.modified.remove(record);
22289         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
22290     },
22291
22292     
22293     commitChanges : function(){
22294         var m = this.modified.slice(0);
22295         this.modified = [];
22296         for(var i = 0, len = m.length; i < len; i++){
22297             m[i].commit();
22298         }
22299     },
22300
22301     
22302     rejectChanges : function(){
22303         var m = this.modified.slice(0);
22304         this.modified = [];
22305         for(var i = 0, len = m.length; i < len; i++){
22306             m[i].reject();
22307         }
22308         var m = this.removed.slice(0).reverse();
22309         this.removed = [];
22310         for(var i = 0, len = m.length; i < len; i++){
22311             this.insert(m[i].lastIndex||0, m[i]);
22312             m[i].reject();
22313         }
22314     },
22315
22316     
22317     onMetaChange : function(meta){
22318         this.recordType = this.reader.recordType;
22319         this.fields = this.recordType.prototype.fields;
22320         delete this.snapshot;
22321         if(this.reader.meta.sortInfo){
22322             this.sortInfo = this.reader.meta.sortInfo;
22323         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
22324             delete this.sortInfo;
22325         }
22326         if(this.writer){
22327             this.writer.meta = this.reader.meta;
22328         }
22329         this.modified = [];
22330         this.fireEvent('metachange', this, this.reader.meta);
22331     },
22332
22333     
22334     findInsertIndex : function(record){
22335         this.suspendEvents();
22336         var data = this.data.clone();
22337         this.data.add(record);
22338         this.applySort();
22339         var index = this.data.indexOf(record);
22340         this.data = data;
22341         this.resumeEvents();
22342         return index;
22343     },
22344
22345     
22346     setBaseParam : function (name, value){
22347         this.baseParams = this.baseParams || {};
22348         this.baseParams[name] = value;
22349     }
22350 });
22351
22352 Ext.reg('store', Ext.data.Store);
22353
22354
22355 Ext.data.Store.Error = Ext.extend(Ext.Error, {
22356     name: 'Ext.data.Store'
22357 });
22358 Ext.apply(Ext.data.Store.Error.prototype, {
22359     lang: {
22360         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
22361     }
22362 });
22363
22364 Ext.data.Field = Ext.extend(Object, {
22365     
22366     constructor : function(config){
22367         if(Ext.isString(config)){
22368             config = {name: config};
22369         }
22370         Ext.apply(this, config);
22371         
22372         var types = Ext.data.Types,
22373             st = this.sortType,
22374             t;
22375
22376         if(this.type){
22377             if(Ext.isString(this.type)){
22378                 this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
22379             }
22380         }else{
22381             this.type = types.AUTO;
22382         }
22383
22384         
22385         if(Ext.isString(st)){
22386             this.sortType = Ext.data.SortTypes[st];
22387         }else if(Ext.isEmpty(st)){
22388             this.sortType = this.type.sortType;
22389         }
22390
22391         if(!this.convert){
22392             this.convert = this.type.convert;
22393         }
22394     },
22395     
22396     
22397     
22398     
22399     
22400     dateFormat: null,
22401     
22402     defaultValue: "",
22403     
22404     mapping: null,
22405     
22406     sortType : null,
22407     
22408     sortDir : "ASC",
22409     
22410     allowBlank : true
22411 });
22412
22413 Ext.data.DataReader = function(meta, recordType){
22414     
22415     this.meta = meta;
22416     
22417     this.recordType = Ext.isArray(recordType) ?
22418         Ext.data.Record.create(recordType) : recordType;
22419
22420     
22421     if (this.recordType){
22422         this.buildExtractors();
22423     }
22424 };
22425
22426 Ext.data.DataReader.prototype = {
22427     
22428     
22429     getTotal: Ext.emptyFn,
22430     
22431     getRoot: Ext.emptyFn,
22432     
22433     getMessage: Ext.emptyFn,
22434     
22435     getSuccess: Ext.emptyFn,
22436     
22437     getId: Ext.emptyFn,
22438     
22439     buildExtractors : Ext.emptyFn,
22440     
22441     extractValues : Ext.emptyFn,
22442
22443     
22444     realize: function(rs, data){
22445         if (Ext.isArray(rs)) {
22446             for (var i = rs.length - 1; i >= 0; i--) {
22447                 
22448                 if (Ext.isArray(data)) {
22449                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
22450                 }
22451                 else {
22452                     
22453                     
22454                     this.realize(rs.splice(i,1).shift(), data);
22455                 }
22456             }
22457         }
22458         else {
22459             
22460             if (Ext.isArray(data) && data.length == 1) {
22461                 data = data.shift();
22462             }
22463             if (!this.isData(data)) {
22464                 
22465                 
22466                 throw new Ext.data.DataReader.Error('realize', rs);
22467             }
22468             rs.phantom = false; 
22469             rs._phid = rs.id;  
22470             rs.id = this.getId(data);
22471             rs.data = data;
22472
22473             rs.commit();
22474         }
22475     },
22476
22477     
22478     update : function(rs, data) {
22479         if (Ext.isArray(rs)) {
22480             for (var i=rs.length-1; i >= 0; i--) {
22481                 if (Ext.isArray(data)) {
22482                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
22483                 }
22484                 else {
22485                     
22486                     
22487                     this.update(rs.splice(i,1).shift(), data);
22488                 }
22489             }
22490         }
22491         else {
22492             
22493             if (Ext.isArray(data) && data.length == 1) {
22494                 data = data.shift();
22495             }
22496             if (this.isData(data)) {
22497                 rs.data = Ext.apply(rs.data, data);
22498             }
22499             rs.commit();
22500         }
22501     },
22502
22503     
22504     extractData : function(root, returnRecords) {
22505         
22506         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
22507
22508         var rs = [];
22509
22510         
22511         
22512         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
22513             root = [root];
22514         }
22515         var f       = this.recordType.prototype.fields,
22516             fi      = f.items,
22517             fl      = f.length,
22518             rs      = [];
22519         if (returnRecords === true) {
22520             var Record = this.recordType;
22521             for (var i = 0; i < root.length; i++) {
22522                 var n = root[i];
22523                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
22524                 record[rawName] = n;    
22525                 rs.push(record);
22526             }
22527         }
22528         else {
22529             for (var i = 0; i < root.length; i++) {
22530                 var data = this.extractValues(root[i], fi, fl);
22531                 data[this.meta.idProperty] = this.getId(root[i]);
22532                 rs.push(data);
22533             }
22534         }
22535         return rs;
22536     },
22537
22538     
22539     isData : function(data) {
22540         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
22541     },
22542
22543     
22544     onMetaChange : function(meta){
22545         delete this.ef;
22546         this.meta = meta;
22547         this.recordType = Ext.data.Record.create(meta.fields);
22548         this.buildExtractors();
22549     }
22550 };
22551
22552
22553 Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
22554     constructor : function(message, arg) {
22555         this.arg = arg;
22556         Ext.Error.call(this, message);
22557     },
22558     name: 'Ext.data.DataReader'
22559 });
22560 Ext.apply(Ext.data.DataReader.Error.prototype, {
22561     lang : {
22562         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
22563         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
22564         'invalid-response': "#readResponse received an invalid response from the server."
22565     }
22566 });
22567
22568 Ext.data.DataWriter = function(config){
22569     Ext.apply(this, config);
22570 };
22571 Ext.data.DataWriter.prototype = {
22572
22573     
22574     writeAllFields : false,
22575     
22576     listful : false,    
22577
22578     
22579     apply : function(params, baseParams, action, rs) {
22580         var data    = [],
22581         renderer    = action + 'Record';
22582         
22583         if (Ext.isArray(rs)) {
22584             Ext.each(rs, function(rec){
22585                 data.push(this[renderer](rec));
22586             }, this);
22587         }
22588         else if (rs instanceof Ext.data.Record) {
22589             data = this[renderer](rs);
22590         }
22591         this.render(params, baseParams, data);
22592     },
22593
22594     
22595     render : Ext.emptyFn,
22596
22597     
22598     updateRecord : Ext.emptyFn,
22599
22600     
22601     createRecord : Ext.emptyFn,
22602
22603     
22604     destroyRecord : Ext.emptyFn,
22605
22606     
22607     toHash : function(rec, config) {
22608         var map = rec.fields.map,
22609             data = {},
22610             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
22611             m;
22612         Ext.iterate(raw, function(prop, value){
22613             if((m = map[prop])){
22614                 data[m.mapping ? m.mapping : m.name] = value;
22615             }
22616         });
22617         
22618         
22619         
22620         if (rec.phantom) {
22621             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
22622                 delete data[this.meta.idProperty];
22623             }
22624         } else {
22625             data[this.meta.idProperty] = rec.id
22626         }
22627         return data;
22628     },
22629
22630     
22631     toArray : function(data) {
22632         var fields = [];
22633         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
22634         return fields;
22635     }
22636 };
22637 Ext.data.DataProxy = function(conn){
22638     
22639     
22640     conn = conn || {};
22641
22642     
22643     
22644     
22645
22646     this.api     = conn.api;
22647     this.url     = conn.url;
22648     this.restful = conn.restful;
22649     this.listeners = conn.listeners;
22650
22651     
22652     this.prettyUrls = conn.prettyUrls;
22653
22654     
22655
22656     this.addEvents(
22657         
22658         'exception',
22659         
22660         'beforeload',
22661         
22662         'load',
22663         
22664         'loadexception',
22665         
22666         'beforewrite',
22667         
22668         'write'
22669     );
22670     Ext.data.DataProxy.superclass.constructor.call(this);
22671
22672     
22673     try {
22674         Ext.data.Api.prepare(this);
22675     } catch (e) {
22676         if (e instanceof Ext.data.Api.Error) {
22677             e.toConsole();
22678         }
22679     }
22680     
22681     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
22682 };
22683
22684 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
22685     
22686     restful: false,
22687
22688     
22689     setApi : function() {
22690         if (arguments.length == 1) {
22691             var valid = Ext.data.Api.isValid(arguments[0]);
22692             if (valid === true) {
22693                 this.api = arguments[0];
22694             }
22695             else {
22696                 throw new Ext.data.Api.Error('invalid', valid);
22697             }
22698         }
22699         else if (arguments.length == 2) {
22700             if (!Ext.data.Api.isAction(arguments[0])) {
22701                 throw new Ext.data.Api.Error('invalid', arguments[0]);
22702             }
22703             this.api[arguments[0]] = arguments[1];
22704         }
22705         Ext.data.Api.prepare(this);
22706     },
22707
22708     
22709     isApiAction : function(action) {
22710         return (this.api[action]) ? true : false;
22711     },
22712
22713     
22714     request : function(action, rs, params, reader, callback, scope, options) {
22715         if (!this.api[action] && !this.load) {
22716             throw new Ext.data.DataProxy.Error('action-undefined', action);
22717         }
22718         params = params || {};
22719         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
22720             this.doRequest.apply(this, arguments);
22721         }
22722         else {
22723             callback.call(scope || this, null, options, false);
22724         }
22725     },
22726
22727
22728     
22729     load : null,
22730
22731     
22732     doRequest : function(action, rs, params, reader, callback, scope, options) {
22733         
22734         
22735         
22736         this.load(params, reader, callback, scope, options);
22737     },
22738
22739     
22740     onRead : Ext.emptyFn,
22741     
22742     onWrite : Ext.emptyFn,
22743     
22744     buildUrl : function(action, record) {
22745         record = record || null;
22746
22747         
22748         
22749         
22750         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
22751         if (!url) {
22752             throw new Ext.data.Api.Error('invalid-url', action);
22753         }
22754
22755         
22756         
22757         
22758         
22759         
22760         
22761         var provides = null;
22762         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
22763         if (m) {
22764             provides = m[2];    
22765             url      = m[1];    
22766         }
22767         
22768         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
22769             url += '/' + record.id;
22770         }
22771         return (provides === null) ? url : url + provides;
22772     },
22773
22774     
22775     destroy: function(){
22776         this.purgeListeners();
22777     }
22778 });
22779
22780
22781
22782 Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
22783 Ext.util.Observable.call(Ext.data.DataProxy);
22784
22785
22786 Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
22787     constructor : function(message, arg) {
22788         this.arg = arg;
22789         Ext.Error.call(this, message);
22790     },
22791     name: 'Ext.data.DataProxy'
22792 });
22793 Ext.apply(Ext.data.DataProxy.Error.prototype, {
22794     lang: {
22795         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
22796         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
22797     }
22798 });
22799
22800
22801
22802 Ext.data.Request = function(params) {
22803     Ext.apply(this, params);
22804 };
22805 Ext.data.Request.prototype = {
22806     
22807     action : undefined,
22808     
22809     rs : undefined,
22810     
22811     params: undefined,
22812     
22813     callback : Ext.emptyFn,
22814     
22815     scope : undefined,
22816     
22817     reader : undefined
22818 };
22819
22820 Ext.data.Response = function(params) {
22821     Ext.apply(this, params);
22822 };
22823 Ext.data.Response.prototype = {
22824     
22825     action: undefined,
22826     
22827     success : undefined,
22828     
22829     message : undefined,
22830     
22831     data: undefined,
22832     
22833     raw: undefined,
22834     
22835     records: undefined
22836 };
22837
22838 Ext.data.ScriptTagProxy = function(config){
22839     Ext.apply(this, config);
22840
22841     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
22842
22843     this.head = document.getElementsByTagName("head")[0];
22844
22845     
22846 };
22847
22848 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
22849
22850 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
22851     
22852     
22853     timeout : 30000,
22854     
22855     callbackParam : "callback",
22856     
22857     nocache : true,
22858
22859     
22860     doRequest : function(action, rs, params, reader, callback, scope, arg) {
22861         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
22862
22863         var url = this.buildUrl(action, rs);
22864         if (!url) {
22865             throw new Ext.data.Api.Error('invalid-url', url);
22866         }
22867         url = Ext.urlAppend(url, p);
22868
22869         if(this.nocache){
22870             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
22871         }
22872         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
22873         var trans = {
22874             id : transId,
22875             action: action,
22876             cb : "stcCallback"+transId,
22877             scriptId : "stcScript"+transId,
22878             params : params,
22879             arg : arg,
22880             url : url,
22881             callback : callback,
22882             scope : scope,
22883             reader : reader
22884         };
22885         window[trans.cb] = this.createCallback(action, rs, trans);
22886         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
22887         if(this.autoAbort !== false){
22888             this.abort();
22889         }
22890
22891         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
22892
22893         var script = document.createElement("script");
22894         script.setAttribute("src", url);
22895         script.setAttribute("type", "text/javascript");
22896         script.setAttribute("id", trans.scriptId);
22897         this.head.appendChild(script);
22898
22899         this.trans = trans;
22900     },
22901
22902     
22903     createCallback : function(action, rs, trans) {
22904         var self = this;
22905         return function(res) {
22906             self.trans = false;
22907             self.destroyTrans(trans, true);
22908             if (action === Ext.data.Api.actions.read) {
22909                 self.onRead.call(self, action, trans, res);
22910             } else {
22911                 self.onWrite.call(self, action, trans, res, rs);
22912             }
22913         };
22914     },
22915     
22916     onRead : function(action, trans, res) {
22917         var result;
22918         try {
22919             result = trans.reader.readRecords(res);
22920         }catch(e){
22921             
22922             this.fireEvent("loadexception", this, trans, res, e);
22923
22924             this.fireEvent('exception', this, 'response', action, trans, res, e);
22925             trans.callback.call(trans.scope||window, null, trans.arg, false);
22926             return;
22927         }
22928         if (result.success === false) {
22929             
22930             this.fireEvent('loadexception', this, trans, res);
22931
22932             this.fireEvent('exception', this, 'remote', action, trans, res, null);
22933         } else {
22934             this.fireEvent("load", this, res, trans.arg);
22935         }
22936         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
22937     },
22938     
22939     onWrite : function(action, trans, response, rs) {
22940         var reader = trans.reader;
22941         try {
22942             
22943             var res = reader.readResponse(action, response);
22944         } catch (e) {
22945             this.fireEvent('exception', this, 'response', action, trans, res, e);
22946             trans.callback.call(trans.scope||window, null, res, false);
22947             return;
22948         }
22949         if(!res.success === true){
22950             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
22951             trans.callback.call(trans.scope||window, null, res, false);
22952             return;
22953         }
22954         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
22955         trans.callback.call(trans.scope||window, res.data, res, true);
22956     },
22957
22958     
22959     isLoading : function(){
22960         return this.trans ? true : false;
22961     },
22962
22963     
22964     abort : function(){
22965         if(this.isLoading()){
22966             this.destroyTrans(this.trans);
22967         }
22968     },
22969
22970     
22971     destroyTrans : function(trans, isLoaded){
22972         this.head.removeChild(document.getElementById(trans.scriptId));
22973         clearTimeout(trans.timeoutId);
22974         if(isLoaded){
22975             window[trans.cb] = undefined;
22976             try{
22977                 delete window[trans.cb];
22978             }catch(e){}
22979         }else{
22980             
22981             window[trans.cb] = function(){
22982                 window[trans.cb] = undefined;
22983                 try{
22984                     delete window[trans.cb];
22985                 }catch(e){}
22986             };
22987         }
22988     },
22989
22990     
22991     handleFailure : function(trans){
22992         this.trans = false;
22993         this.destroyTrans(trans, false);
22994         if (trans.action === Ext.data.Api.actions.read) {
22995             
22996             this.fireEvent("loadexception", this, null, trans.arg);
22997         }
22998
22999         this.fireEvent('exception', this, 'response', trans.action, {
23000             response: null,
23001             options: trans.arg
23002         });
23003         trans.callback.call(trans.scope||window, null, trans.arg, false);
23004     },
23005
23006     
23007     destroy: function(){
23008         this.abort();
23009         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
23010     }
23011 });
23012 Ext.data.HttpProxy = function(conn){
23013     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
23014
23015     
23016     this.conn = conn;
23017
23018     
23019     
23020     
23021     
23022     this.conn.url = null;
23023
23024     this.useAjax = !conn || !conn.events;
23025
23026     
23027     var actions = Ext.data.Api.actions;
23028     this.activeRequest = {};
23029     for (var verb in actions) {
23030         this.activeRequest[actions[verb]] = undefined;
23031     }
23032 };
23033
23034 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
23035     
23036     getConnection : function() {
23037         return this.useAjax ? Ext.Ajax : this.conn;
23038     },
23039
23040     
23041     setUrl : function(url, makePermanent) {
23042         this.conn.url = url;
23043         if (makePermanent === true) {
23044             this.url = url;
23045             this.api = null;
23046             Ext.data.Api.prepare(this);
23047         }
23048     },
23049
23050     
23051     doRequest : function(action, rs, params, reader, cb, scope, arg) {
23052         var  o = {
23053             method: (this.api[action]) ? this.api[action]['method'] : undefined,
23054             request: {
23055                 callback : cb,
23056                 scope : scope,
23057                 arg : arg
23058             },
23059             reader: reader,
23060             callback : this.createCallback(action, rs),
23061             scope: this
23062         };
23063
23064         
23065         
23066         if (params.jsonData) {
23067             o.jsonData = params.jsonData;
23068         } else if (params.xmlData) {
23069             o.xmlData = params.xmlData;
23070         } else {
23071             o.params = params || {};
23072         }
23073         
23074         
23075         
23076         this.conn.url = this.buildUrl(action, rs);
23077
23078         if(this.useAjax){
23079
23080             Ext.applyIf(o, this.conn);
23081
23082             
23083             if (this.activeRequest[action]) {
23084                 
23085                 
23086                 
23087                 
23088                 
23089             }
23090             this.activeRequest[action] = Ext.Ajax.request(o);
23091         }else{
23092             this.conn.request(o);
23093         }
23094         
23095         this.conn.url = null;
23096     },
23097
23098     
23099     createCallback : function(action, rs) {
23100         return function(o, success, response) {
23101             this.activeRequest[action] = undefined;
23102             if (!success) {
23103                 if (action === Ext.data.Api.actions.read) {
23104                     
23105                     
23106                     this.fireEvent('loadexception', this, o, response);
23107                 }
23108                 this.fireEvent('exception', this, 'response', action, o, response);
23109                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
23110                 return;
23111             }
23112             if (action === Ext.data.Api.actions.read) {
23113                 this.onRead(action, o, response);
23114             } else {
23115                 this.onWrite(action, o, response, rs);
23116             }
23117         };
23118     },
23119
23120     
23121     onRead : function(action, o, response) {
23122         var result;
23123         try {
23124             result = o.reader.read(response);
23125         }catch(e){
23126             
23127             
23128             this.fireEvent('loadexception', this, o, response, e);
23129
23130             this.fireEvent('exception', this, 'response', action, o, response, e);
23131             o.request.callback.call(o.request.scope, null, o.request.arg, false);
23132             return;
23133         }
23134         if (result.success === false) {
23135             
23136             
23137             this.fireEvent('loadexception', this, o, response);
23138
23139             
23140             var res = o.reader.readResponse(action, response);
23141             this.fireEvent('exception', this, 'remote', action, o, res, null);
23142         }
23143         else {
23144             this.fireEvent('load', this, o, o.request.arg);
23145         }
23146         
23147         
23148         
23149         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
23150     },
23151     
23152     onWrite : function(action, o, response, rs) {
23153         var reader = o.reader;
23154         var res;
23155         try {
23156             res = reader.readResponse(action, response);
23157         } catch (e) {
23158             this.fireEvent('exception', this, 'response', action, o, response, e);
23159             o.request.callback.call(o.request.scope, null, o.request.arg, false);
23160             return;
23161         }
23162         if (res.success === true) {
23163             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
23164         } else {
23165             this.fireEvent('exception', this, 'remote', action, o, res, rs);
23166         }
23167         
23168         
23169         
23170         o.request.callback.call(o.request.scope, res.data, res, res.success);
23171     },
23172
23173     
23174     destroy: function(){
23175         if(!this.useAjax){
23176             this.conn.abort();
23177         }else if(this.activeRequest){
23178             var actions = Ext.data.Api.actions;
23179             for (var verb in actions) {
23180                 if(this.activeRequest[actions[verb]]){
23181                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
23182                 }
23183             }
23184         }
23185         Ext.data.HttpProxy.superclass.destroy.call(this);
23186     }
23187 });
23188 Ext.data.MemoryProxy = function(data){
23189     
23190     var api = {};
23191     api[Ext.data.Api.actions.read] = true;
23192     Ext.data.MemoryProxy.superclass.constructor.call(this, {
23193         api: api
23194     });
23195     this.data = data;
23196 };
23197
23198 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
23199     
23200
23201        
23202     doRequest : function(action, rs, params, reader, callback, scope, arg) {
23203         
23204         params = params || {};
23205         var result;
23206         try {
23207             result = reader.readRecords(this.data);
23208         }catch(e){
23209             
23210             this.fireEvent("loadexception", this, null, arg, e);
23211
23212             this.fireEvent('exception', this, 'response', action, arg, null, e);
23213             callback.call(scope, null, arg, false);
23214             return;
23215         }
23216         callback.call(scope, result, arg, true);
23217     }
23218 });
23219 Ext.data.Types = new function(){
23220     var st = Ext.data.SortTypes;
23221     Ext.apply(this, {
23222         
23223         stripRe: /[\$,%]/g,
23224         
23225         
23226         AUTO: {
23227             convert: function(v){ return v; },
23228             sortType: st.none,
23229             type: 'auto'
23230         },
23231
23232         
23233         STRING: {
23234             convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
23235             sortType: st.asUCString,
23236             type: 'string'
23237         },
23238
23239         
23240         INT: {
23241             convert: function(v){
23242                 return v !== undefined && v !== null && v !== '' ?
23243                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
23244             },
23245             sortType: st.none,
23246             type: 'int'
23247         },
23248         
23249         
23250         FLOAT: {
23251             convert: function(v){
23252                 return v !== undefined && v !== null && v !== '' ?
23253                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
23254             },
23255             sortType: st.none,
23256             type: 'float'
23257         },
23258         
23259         
23260         BOOL: {
23261             convert: function(v){ return v === true || v === 'true' || v == 1; },
23262             sortType: st.none,
23263             type: 'bool'
23264         },
23265         
23266         
23267         DATE: {
23268             convert: function(v){
23269                 var df = this.dateFormat;
23270                 if(!v){
23271                     return null;
23272                 }
23273                 if(Ext.isDate(v)){
23274                     return v;
23275                 }
23276                 if(df){
23277                     if(df == 'timestamp'){
23278                         return new Date(v*1000);
23279                     }
23280                     if(df == 'time'){
23281                         return new Date(parseInt(v, 10));
23282                     }
23283                     return Date.parseDate(v, df);
23284                 }
23285                 var parsed = Date.parse(v);
23286                 return parsed ? new Date(parsed) : null;
23287             },
23288             sortType: st.asDate,
23289             type: 'date'
23290         }
23291     });
23292     
23293     Ext.apply(this, {
23294         
23295         BOOLEAN: this.BOOL,
23296         
23297         INTEGER: this.INT,
23298         
23299         NUMBER: this.FLOAT    
23300     });
23301 };
23302 Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
23303     
23304     encode : true,
23305     
23306     encodeDelete: false,
23307     
23308     constructor : function(config){
23309         Ext.data.JsonWriter.superclass.constructor.call(this, config);    
23310     },
23311
23312     
23313     render : function(params, baseParams, data) {
23314         if (this.encode === true) {
23315             
23316             Ext.apply(params, baseParams);
23317             params[this.meta.root] = Ext.encode(data);
23318         } else {
23319             
23320             var jdata = Ext.apply({}, baseParams);
23321             jdata[this.meta.root] = data;
23322             params.jsonData = jdata;
23323         }
23324     },
23325     
23326     createRecord : function(rec) {
23327        return this.toHash(rec);
23328     },
23329     
23330     updateRecord : function(rec) {
23331         return this.toHash(rec);
23332
23333     },
23334     
23335     destroyRecord : function(rec){
23336         if(this.encodeDelete){
23337             var data = {};
23338             data[this.meta.idProperty] = rec.id;
23339             return data;
23340         }else{
23341             return rec.id;
23342         }
23343     }
23344 });
23345 Ext.data.JsonReader = function(meta, recordType){
23346     meta = meta || {};
23347     
23348     
23349     
23350     
23351     Ext.applyIf(meta, {
23352         idProperty: 'id',
23353         successProperty: 'success',
23354         totalProperty: 'total'
23355     });
23356
23357     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
23358 };
23359 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
23360     
23361     
23362     read : function(response){
23363         var json = response.responseText;
23364         var o = Ext.decode(json);
23365         if(!o) {
23366             throw {message: 'JsonReader.read: Json object not found'};
23367         }
23368         return this.readRecords(o);
23369     },
23370
23371     
23372     
23373     readResponse : function(action, response) {
23374         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
23375         if(!o) {
23376             throw new Ext.data.JsonReader.Error('response');
23377         }
23378
23379         var root = this.getRoot(o);
23380         if (action === Ext.data.Api.actions.create) {
23381             var def = Ext.isDefined(root);
23382             if (def && Ext.isEmpty(root)) {
23383                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
23384             }
23385             else if (!def) {
23386                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
23387             }
23388         }
23389
23390         
23391         var res = new Ext.data.Response({
23392             action: action,
23393             success: this.getSuccess(o),
23394             data: (root) ? this.extractData(root, false) : [],
23395             message: this.getMessage(o),
23396             raw: o
23397         });
23398
23399         
23400         if (Ext.isEmpty(res.success)) {
23401             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
23402         }
23403         return res;
23404     },
23405
23406     
23407     readRecords : function(o){
23408         
23409         this.jsonData = o;
23410         if(o.metaData){
23411             this.onMetaChange(o.metaData);
23412         }
23413         var s = this.meta, Record = this.recordType,
23414             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
23415
23416         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
23417         if(s.totalProperty){
23418             v = parseInt(this.getTotal(o), 10);
23419             if(!isNaN(v)){
23420                 totalRecords = v;
23421             }
23422         }
23423         if(s.successProperty){
23424             v = this.getSuccess(o);
23425             if(v === false || v === 'false'){
23426                 success = false;
23427             }
23428         }
23429
23430         
23431         return {
23432             success : success,
23433             records : this.extractData(root, true), 
23434             totalRecords : totalRecords
23435         };
23436     },
23437
23438     
23439     buildExtractors : function() {
23440         if(this.ef){
23441             return;
23442         }
23443         var s = this.meta, Record = this.recordType,
23444             f = Record.prototype.fields, fi = f.items, fl = f.length;
23445
23446         if(s.totalProperty) {
23447             this.getTotal = this.createAccessor(s.totalProperty);
23448         }
23449         if(s.successProperty) {
23450             this.getSuccess = this.createAccessor(s.successProperty);
23451         }
23452         if (s.messageProperty) {
23453             this.getMessage = this.createAccessor(s.messageProperty);
23454         }
23455         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
23456         if (s.id || s.idProperty) {
23457             var g = this.createAccessor(s.id || s.idProperty);
23458             this.getId = function(rec) {
23459                 var r = g(rec);
23460                 return (r === undefined || r === '') ? null : r;
23461             };
23462         } else {
23463             this.getId = function(){return null;};
23464         }
23465         var ef = [];
23466         for(var i = 0; i < fl; i++){
23467             f = fi[i];
23468             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
23469             ef.push(this.createAccessor(map));
23470         }
23471         this.ef = ef;
23472     },
23473
23474     
23475     simpleAccess : function(obj, subsc) {
23476         return obj[subsc];
23477     },
23478
23479     
23480     createAccessor : function(){
23481         var re = /[\[\.]/;
23482         return function(expr) {
23483             if(Ext.isEmpty(expr)){
23484                 return Ext.emptyFn;
23485             }
23486             if(Ext.isFunction(expr)){
23487                 return expr;
23488             }
23489             var i = String(expr).search(re);
23490             if(i >= 0){
23491                 return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
23492             }
23493             return function(obj){
23494                 return obj[expr];
23495             };
23496
23497         };
23498     }(),
23499
23500     
23501     extractValues : function(data, items, len) {
23502         var f, values = {};
23503         for(var j = 0; j < len; j++){
23504             f = items[j];
23505             var v = this.ef[j](data);
23506             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
23507         }
23508         return values;
23509     }
23510 });
23511
23512
23513 Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
23514     constructor : function(message, arg) {
23515         this.arg = arg;
23516         Ext.Error.call(this, message);
23517     },
23518     name : 'Ext.data.JsonReader'
23519 });
23520 Ext.apply(Ext.data.JsonReader.Error.prototype, {
23521     lang: {
23522         'response': 'An error occurred while json-decoding your server response',
23523         'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
23524         'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
23525         'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
23526         'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
23527     }
23528 });
23529
23530 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
23531     
23532     
23533     
23534     
23535     readRecords : function(o){
23536         this.arrayData = o;
23537         var s = this.meta,
23538             sid = s ? Ext.num(s.idIndex, s.id) : null,
23539             recordType = this.recordType,
23540             fields = recordType.prototype.fields,
23541             records = [],
23542             success = true,
23543             v;
23544
23545         var root = this.getRoot(o);
23546
23547         for(var i = 0, len = root.length; i < len; i++) {
23548             var n = root[i],
23549                 values = {},
23550                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
23551             for(var j = 0, jlen = fields.length; j < jlen; j++) {
23552                 var f = fields.items[j],
23553                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
23554                 v = n[k] !== undefined ? n[k] : f.defaultValue;
23555                 v = f.convert(v, n);
23556                 values[f.name] = v;
23557             }
23558             var record = new recordType(values, id);
23559             record.json = n;
23560             records[records.length] = record;
23561         }
23562
23563         var totalRecords = records.length;
23564
23565         if(s.totalProperty) {
23566             v = parseInt(this.getTotal(o), 10);
23567             if(!isNaN(v)) {
23568                 totalRecords = v;
23569             }
23570         }
23571         if(s.successProperty){
23572             v = this.getSuccess(o);
23573             if(v === false || v === 'false'){
23574                 success = false;
23575             }
23576         }
23577
23578         return {
23579             success : success,
23580             records : records,
23581             totalRecords : totalRecords
23582         };
23583     }
23584 });
23585 Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
23586     
23587     constructor: function(config){
23588         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
23589             reader: new Ext.data.ArrayReader(config)
23590         }));
23591     },
23592
23593     loadData : function(data, append){
23594         if(this.expandData === true){
23595             var r = [];
23596             for(var i = 0, len = data.length; i < len; i++){
23597                 r[r.length] = [data[i]];
23598             }
23599             data = r;
23600         }
23601         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
23602     }
23603 });
23604 Ext.reg('arraystore', Ext.data.ArrayStore);
23605
23606
23607 Ext.data.SimpleStore = Ext.data.ArrayStore;
23608 Ext.reg('simplestore', Ext.data.SimpleStore);
23609 Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
23610     
23611     constructor: function(config){
23612         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
23613             reader: new Ext.data.JsonReader(config)
23614         }));
23615     }
23616 });
23617 Ext.reg('jsonstore', Ext.data.JsonStore);
23618 Ext.data.XmlWriter = function(params) {
23619     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
23620     
23621     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
23622 };
23623 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
23624     
23625     documentRoot: 'xrequest',
23626     
23627     forceDocumentRoot: false,
23628     
23629     root: 'records',
23630     
23631     xmlVersion : '1.0',
23632     
23633     xmlEncoding: 'ISO-8859-15',
23634     
23635     
23636     tpl: '<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}</tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
23637
23638
23639     
23640     render : function(params, baseParams, data) {
23641         baseParams = this.toArray(baseParams);
23642         params.xmlData = this.tpl.applyTemplate({
23643             version: this.xmlVersion,
23644             encoding: this.xmlEncoding,
23645             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
23646             record: this.meta.record,
23647             root: this.root,
23648             baseParams: baseParams,
23649             records: (Ext.isArray(data[0])) ? data : [data]
23650         });
23651     },
23652
23653     
23654     createRecord : function(rec) {
23655         return this.toArray(this.toHash(rec));
23656     },
23657
23658     
23659     updateRecord : function(rec) {
23660         return this.toArray(this.toHash(rec));
23661
23662     },
23663     
23664     destroyRecord : function(rec) {
23665         var data = {};
23666         data[this.meta.idProperty] = rec.id;
23667         return this.toArray(data);
23668     }
23669 });
23670
23671 Ext.data.XmlReader = function(meta, recordType){
23672     meta = meta || {};
23673
23674     
23675     Ext.applyIf(meta, {
23676         idProperty: meta.idProperty || meta.idPath || meta.id,
23677         successProperty: meta.successProperty || meta.success
23678     });
23679
23680     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
23681 };
23682 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
23683     
23684     read : function(response){
23685         var doc = response.responseXML;
23686         if(!doc) {
23687             throw {message: "XmlReader.read: XML Document not available"};
23688         }
23689         return this.readRecords(doc);
23690     },
23691
23692     
23693     readRecords : function(doc){
23694         
23695         this.xmlData = doc;
23696
23697         var root    = doc.documentElement || doc,
23698             q       = Ext.DomQuery,
23699             totalRecords = 0,
23700             success = true;
23701
23702         if(this.meta.totalProperty){
23703             totalRecords = this.getTotal(root, 0);
23704         }
23705         if(this.meta.successProperty){
23706             success = this.getSuccess(root);
23707         }
23708
23709         var records = this.extractData(q.select(this.meta.record, root), true); 
23710
23711         
23712         return {
23713             success : success,
23714             records : records,
23715             totalRecords : totalRecords || records.length
23716         };
23717     },
23718
23719     
23720     readResponse : function(action, response) {
23721         var q   = Ext.DomQuery,
23722         doc     = response.responseXML;
23723
23724         
23725         var res = new Ext.data.Response({
23726             action: action,
23727             success : this.getSuccess(doc),
23728             message: this.getMessage(doc),
23729             data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc), false),
23730             raw: doc
23731         });
23732
23733         if (Ext.isEmpty(res.success)) {
23734             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
23735         }
23736
23737         
23738         if (action === Ext.data.Api.actions.create) {
23739             var def = Ext.isDefined(res.data);
23740             if (def && Ext.isEmpty(res.data)) {
23741                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
23742             }
23743             else if (!def) {
23744                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
23745             }
23746         }
23747         return res;
23748     },
23749
23750     getSuccess : function() {
23751         return true;
23752     },
23753
23754     
23755     buildExtractors : function() {
23756         if(this.ef){
23757             return;
23758         }
23759         var s       = this.meta,
23760             Record  = this.recordType,
23761             f       = Record.prototype.fields,
23762             fi      = f.items,
23763             fl      = f.length;
23764
23765         if(s.totalProperty) {
23766             this.getTotal = this.createAccessor(s.totalProperty);
23767         }
23768         if(s.successProperty) {
23769             this.getSuccess = this.createAccessor(s.successProperty);
23770         }
23771         if (s.messageProperty) {
23772             this.getMessage = this.createAccessor(s.messageProperty);
23773         }
23774         this.getRoot = function(res) {
23775             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
23776         };
23777         if (s.idPath || s.idProperty) {
23778             var g = this.createAccessor(s.idPath || s.idProperty);
23779             this.getId = function(rec) {
23780                 var id = g(rec) || rec.id;
23781                 return (id === undefined || id === '') ? null : id;
23782             };
23783         } else {
23784             this.getId = function(){return null;};
23785         }
23786         var ef = [];
23787         for(var i = 0; i < fl; i++){
23788             f = fi[i];
23789             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
23790             ef.push(this.createAccessor(map));
23791         }
23792         this.ef = ef;
23793     },
23794
23795     
23796     createAccessor : function(){
23797         var q = Ext.DomQuery;
23798         return function(key) {
23799             switch(key) {
23800                 case this.meta.totalProperty:
23801                     return function(root, def){
23802                         return q.selectNumber(key, root, def);
23803                     };
23804                     break;
23805                 case this.meta.successProperty:
23806                     return function(root, def) {
23807                         var sv = q.selectValue(key, root, true);
23808                         var success = sv !== false && sv !== 'false';
23809                         return success;
23810                     };
23811                     break;
23812                 default:
23813                     return function(root, def) {
23814                         return q.selectValue(key, root, def);
23815                     };
23816                     break;
23817             }
23818         };
23819     }(),
23820
23821     
23822     extractValues : function(data, items, len) {
23823         var f, values = {};
23824         for(var j = 0; j < len; j++){
23825             f = items[j];
23826             var v = this.ef[j](data);
23827             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
23828         }
23829         return values;
23830     }
23831 });
23832 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
23833     
23834     constructor: function(config){
23835         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
23836             reader: new Ext.data.XmlReader(config)
23837         }));
23838     }
23839 });
23840 Ext.reg('xmlstore', Ext.data.XmlStore);
23841 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
23842
23843     
23844     constructor: function(config) {
23845         config = config || {};
23846
23847         
23848         
23849         
23850         
23851         this.hasMultiSort  = true;
23852         this.multiSortInfo = this.multiSortInfo || {sorters: []};
23853
23854         var sorters    = this.multiSortInfo.sorters,
23855             groupField = config.groupField || this.groupField,
23856             sortInfo   = config.sortInfo || this.sortInfo,
23857             groupDir   = config.groupDir || this.groupDir;
23858
23859         
23860         if(groupField){
23861             sorters.push({
23862                 field    : groupField,
23863                 direction: groupDir
23864             });
23865         }
23866
23867         
23868         if (sortInfo) {
23869             sorters.push(sortInfo);
23870         }
23871
23872         Ext.data.GroupingStore.superclass.constructor.call(this, config);
23873
23874         this.addEvents(
23875           
23876           'groupchange'
23877         );
23878
23879         this.applyGroupField();
23880     },
23881
23882     
23883     
23884     remoteGroup : false,
23885     
23886     groupOnSort:false,
23887
23888     groupDir : 'ASC',
23889
23890     
23891     clearGrouping : function(){
23892         this.groupField = false;
23893
23894         if(this.remoteGroup){
23895             if(this.baseParams){
23896                 delete this.baseParams.groupBy;
23897                 delete this.baseParams.groupDir;
23898             }
23899             var lo = this.lastOptions;
23900             if(lo && lo.params){
23901                 delete lo.params.groupBy;
23902                 delete lo.params.groupDir;
23903             }
23904
23905             this.reload();
23906         }else{
23907             this.sort();
23908             this.fireEvent('datachanged', this);
23909         }
23910     },
23911
23912     
23913     groupBy : function(field, forceRegroup, direction) {
23914         direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
23915
23916         if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
23917             return; 
23918         }
23919
23920         
23921         
23922         sorters = this.multiSortInfo.sorters;
23923         if (sorters.length > 0 && sorters[0].field == this.groupField) {
23924             sorters.shift();
23925         }
23926
23927         this.groupField = field;
23928         this.groupDir = direction;
23929         this.applyGroupField();
23930
23931         var fireGroupEvent = function() {
23932             this.fireEvent('groupchange', this, this.getGroupState());
23933         };
23934
23935         if (this.groupOnSort) {
23936             this.sort(field, direction);
23937             fireGroupEvent.call(this);
23938             return;
23939         }
23940
23941         if (this.remoteGroup) {
23942             this.on('load', fireGroupEvent, this, {single: true});
23943             this.reload();
23944         } else {
23945             this.sort(sorters);
23946             fireGroupEvent.call(this);
23947         }
23948     },
23949
23950     
23951     
23952     sort : function(fieldName, dir) {
23953         if (this.remoteSort) {
23954             return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
23955         }
23956
23957         var sorters = [];
23958
23959         
23960         if (Ext.isArray(arguments[0])) {
23961             sorters = arguments[0];
23962         } else if (fieldName == undefined) {
23963             
23964             
23965             sorters = this.sortInfo ? [this.sortInfo] : [];
23966         } else {
23967             
23968             
23969             var field = this.fields.get(fieldName);
23970             if (!field) return false;
23971
23972             var name       = field.name,
23973                 sortInfo   = this.sortInfo || null,
23974                 sortToggle = this.sortToggle ? this.sortToggle[name] : null;
23975
23976             if (!dir) {
23977                 if (sortInfo && sortInfo.field == name) { 
23978                     dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
23979                 } else {
23980                     dir = field.sortDir;
23981                 }
23982             }
23983
23984             this.sortToggle[name] = dir;
23985             this.sortInfo = {field: name, direction: dir};
23986
23987             sorters = [this.sortInfo];
23988         }
23989
23990         
23991         if (this.groupField) {
23992             sorters.unshift({direction: this.groupDir, field: this.groupField});
23993         }
23994
23995         return this.multiSort.call(this, sorters, dir);
23996     },
23997
23998     
23999     applyGroupField: function(){
24000         if (this.remoteGroup) {
24001             if(!this.baseParams){
24002                 this.baseParams = {};
24003             }
24004
24005             Ext.apply(this.baseParams, {
24006                 groupBy : this.groupField,
24007                 groupDir: this.groupDir
24008             });
24009
24010             var lo = this.lastOptions;
24011             if (lo && lo.params) {
24012                 lo.params.groupDir = this.groupDir;
24013
24014                 
24015                 delete lo.params.groupBy;
24016             }
24017         }
24018     },
24019
24020     
24021     applyGrouping : function(alwaysFireChange){
24022         if(this.groupField !== false){
24023             this.groupBy(this.groupField, true, this.groupDir);
24024             return true;
24025         }else{
24026             if(alwaysFireChange === true){
24027                 this.fireEvent('datachanged', this);
24028             }
24029             return false;
24030         }
24031     },
24032
24033     
24034     getGroupState : function(){
24035         return this.groupOnSort && this.groupField !== false ?
24036                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
24037     }
24038 });
24039 Ext.reg('groupingstore', Ext.data.GroupingStore);
24040
24041 Ext.data.DirectProxy = function(config){
24042     Ext.apply(this, config);
24043     if(typeof this.paramOrder == 'string'){
24044         this.paramOrder = this.paramOrder.split(/[\s,|]/);
24045     }
24046     Ext.data.DirectProxy.superclass.constructor.call(this, config);
24047 };
24048
24049 Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
24050     
24051     paramOrder: undefined,
24052
24053     
24054     paramsAsHash: true,
24055
24056     
24057     directFn : undefined,
24058
24059     
24060     doRequest : function(action, rs, params, reader, callback, scope, options) {
24061         var args = [],
24062             directFn = this.api[action] || this.directFn;
24063
24064         switch (action) {
24065             case Ext.data.Api.actions.create:
24066                 args.push(params.jsonData);             
24067                 break;
24068             case Ext.data.Api.actions.read:
24069                 
24070                 if(directFn.directCfg.method.len > 0){
24071                     if(this.paramOrder){
24072                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
24073                             args.push(params[this.paramOrder[i]]);
24074                         }
24075                     }else if(this.paramsAsHash){
24076                         args.push(params);
24077                     }
24078                 }
24079                 break;
24080             case Ext.data.Api.actions.update:
24081                 args.push(params.jsonData);        
24082                 break;
24083             case Ext.data.Api.actions.destroy:
24084                 args.push(params.jsonData);        
24085                 break;
24086         }
24087
24088         var trans = {
24089             params : params || {},
24090             request: {
24091                 callback : callback,
24092                 scope : scope,
24093                 arg : options
24094             },
24095             reader: reader
24096         };
24097
24098         args.push(this.createCallback(action, rs, trans), this);
24099         directFn.apply(window, args);
24100     },
24101
24102     
24103     createCallback : function(action, rs, trans) {
24104         var me = this;
24105         return function(result, res) {
24106             if (!res.status) {
24107                 
24108                 if (action === Ext.data.Api.actions.read) {
24109                     me.fireEvent("loadexception", me, trans, res, null);
24110                 }
24111                 me.fireEvent('exception', me, 'remote', action, trans, res, null);
24112                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
24113                 return;
24114             }
24115             if (action === Ext.data.Api.actions.read) {
24116                 me.onRead(action, trans, result, res);
24117             } else {
24118                 me.onWrite(action, trans, result, res, rs);
24119             }
24120         };
24121     },
24122
24123     
24124     onRead : function(action, trans, result, res) {
24125         var records;
24126         try {
24127             records = trans.reader.readRecords(result);
24128         }
24129         catch (ex) {
24130             
24131             this.fireEvent("loadexception", this, trans, res, ex);
24132
24133             this.fireEvent('exception', this, 'response', action, trans, res, ex);
24134             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
24135             return;
24136         }
24137         this.fireEvent("load", this, res, trans.request.arg);
24138         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
24139     },
24140     
24141     onWrite : function(action, trans, result, res, rs) {
24142         var data = trans.reader.extractData(trans.reader.getRoot(result), false);
24143         var success = trans.reader.getSuccess(result);
24144         success = (success !== false);
24145         if (success){
24146             this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
24147         }else{
24148             this.fireEvent('exception', this, 'remote', action, trans, result, rs);
24149         }
24150         trans.request.callback.call(trans.request.scope, data, res, success);
24151     }
24152 });
24153
24154 Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
24155     constructor : function(config){
24156         
24157         var c = Ext.apply({}, {
24158             batchTransactions: false
24159         }, config);
24160         Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
24161             proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
24162             reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
24163         }));
24164     }
24165 });
24166 Ext.reg('directstore', Ext.data.DirectStore);
24167
24168 Ext.Direct = Ext.extend(Ext.util.Observable, {
24169     
24170
24171     
24172     exceptions: {
24173         TRANSPORT: 'xhr',
24174         PARSE: 'parse',
24175         LOGIN: 'login',
24176         SERVER: 'exception'
24177     },
24178
24179     
24180     constructor: function(){
24181         this.addEvents(
24182             
24183             'event',
24184             
24185             'exception'
24186         );
24187         this.transactions = {};
24188         this.providers = {};
24189     },
24190
24191     
24192     addProvider : function(provider){
24193         var a = arguments;
24194         if(a.length > 1){
24195             for(var i = 0, len = a.length; i < len; i++){
24196                 this.addProvider(a[i]);
24197             }
24198             return;
24199         }
24200
24201         
24202         if(!provider.events){
24203             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
24204         }
24205         provider.id = provider.id || Ext.id();
24206         this.providers[provider.id] = provider;
24207
24208         provider.on('data', this.onProviderData, this);
24209         provider.on('exception', this.onProviderException, this);
24210
24211
24212         if(!provider.isConnected()){
24213             provider.connect();
24214         }
24215
24216         return provider;
24217     },
24218
24219     
24220     getProvider : function(id){
24221         return this.providers[id];
24222     },
24223
24224     removeProvider : function(id){
24225         var provider = id.id ? id : this.providers[id];
24226         provider.un('data', this.onProviderData, this);
24227         provider.un('exception', this.onProviderException, this);
24228         delete this.providers[provider.id];
24229         return provider;
24230     },
24231
24232     addTransaction: function(t){
24233         this.transactions[t.tid] = t;
24234         return t;
24235     },
24236
24237     removeTransaction: function(t){
24238         delete this.transactions[t.tid || t];
24239         return t;
24240     },
24241
24242     getTransaction: function(tid){
24243         return this.transactions[tid.tid || tid];
24244     },
24245
24246     onProviderData : function(provider, e){
24247         if(Ext.isArray(e)){
24248             for(var i = 0, len = e.length; i < len; i++){
24249                 this.onProviderData(provider, e[i]);
24250             }
24251             return;
24252         }
24253         if(e.name && e.name != 'event' && e.name != 'exception'){
24254             this.fireEvent(e.name, e);
24255         }else if(e.type == 'exception'){
24256             this.fireEvent('exception', e);
24257         }
24258         this.fireEvent('event', e, provider);
24259     },
24260
24261     createEvent : function(response, extraProps){
24262         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
24263     }
24264 });
24265
24266 Ext.Direct = new Ext.Direct();
24267
24268 Ext.Direct.TID = 1;
24269 Ext.Direct.PROVIDERS = {};
24270 Ext.Direct.Transaction = function(config){
24271     Ext.apply(this, config);
24272     this.tid = ++Ext.Direct.TID;
24273     this.retryCount = 0;
24274 };
24275 Ext.Direct.Transaction.prototype = {
24276     send: function(){
24277         this.provider.queueTransaction(this);
24278     },
24279
24280     retry: function(){
24281         this.retryCount++;
24282         this.send();
24283     },
24284
24285     getProvider: function(){
24286         return this.provider;
24287     }
24288 };Ext.Direct.Event = function(config){
24289     Ext.apply(this, config);
24290 };
24291
24292 Ext.Direct.Event.prototype = {
24293     status: true,
24294     getData: function(){
24295         return this.data;
24296     }
24297 };
24298
24299 Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
24300     type: 'rpc',
24301     getTransaction: function(){
24302         return this.transaction || Ext.Direct.getTransaction(this.tid);
24303     }
24304 });
24305
24306 Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
24307     status: false,
24308     type: 'exception'
24309 });
24310
24311 Ext.Direct.eventTypes = {
24312     'rpc':  Ext.Direct.RemotingEvent,
24313     'event':  Ext.Direct.Event,
24314     'exception':  Ext.Direct.ExceptionEvent
24315 };
24316
24317 Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
24318     
24319         
24320         
24321     priority: 1,
24322
24323         
24324  
24325     
24326     constructor : function(config){
24327         Ext.apply(this, config);
24328         this.addEvents(
24329                         
24330             'connect',
24331                         
24332             'disconnect',
24333                         
24334             'data',
24335                                     
24336             'exception'
24337         );
24338         Ext.direct.Provider.superclass.constructor.call(this, config);
24339     },
24340
24341     
24342     isConnected: function(){
24343         return false;
24344     },
24345
24346     
24347     connect: Ext.emptyFn,
24348     
24349     
24350     disconnect: Ext.emptyFn
24351 });
24352
24353 Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
24354     parseResponse: function(xhr){
24355         if(!Ext.isEmpty(xhr.responseText)){
24356             if(typeof xhr.responseText == 'object'){
24357                 return xhr.responseText;
24358             }
24359             return Ext.decode(xhr.responseText);
24360         }
24361         return null;
24362     },
24363
24364     getEvents: function(xhr){
24365         var data = null;
24366         try{
24367             data = this.parseResponse(xhr);
24368         }catch(e){
24369             var event = new Ext.Direct.ExceptionEvent({
24370                 data: e,
24371                 xhr: xhr,
24372                 code: Ext.Direct.exceptions.PARSE,
24373                 message: 'Error parsing json response: \n\n ' + data
24374             });
24375             return [event];
24376         }
24377         var events = [];
24378         if(Ext.isArray(data)){
24379             for(var i = 0, len = data.length; i < len; i++){
24380                 events.push(Ext.Direct.createEvent(data[i]));
24381             }
24382         }else{
24383             events.push(Ext.Direct.createEvent(data));
24384         }
24385         return events;
24386     }
24387 });
24388 Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
24389     
24390     
24391     priority: 3,
24392     
24393     
24394     interval: 3000,
24395
24396     
24397     
24398     
24399
24400     
24401     constructor : function(config){
24402         Ext.direct.PollingProvider.superclass.constructor.call(this, config);
24403         this.addEvents(
24404             
24405             'beforepoll',            
24406             
24407             'poll'
24408         );
24409     },
24410
24411     
24412     isConnected: function(){
24413         return !!this.pollTask;
24414     },
24415
24416     
24417     connect: function(){
24418         if(this.url && !this.pollTask){
24419             this.pollTask = Ext.TaskMgr.start({
24420                 run: function(){
24421                     if(this.fireEvent('beforepoll', this) !== false){
24422                         if(typeof this.url == 'function'){
24423                             this.url(this.baseParams);
24424                         }else{
24425                             Ext.Ajax.request({
24426                                 url: this.url,
24427                                 callback: this.onData,
24428                                 scope: this,
24429                                 params: this.baseParams
24430                             });
24431                         }
24432                     }
24433                 },
24434                 interval: this.interval,
24435                 scope: this
24436             });
24437             this.fireEvent('connect', this);
24438         }else if(!this.url){
24439             throw 'Error initializing PollingProvider, no url configured.';
24440         }
24441     },
24442
24443     
24444     disconnect: function(){
24445         if(this.pollTask){
24446             Ext.TaskMgr.stop(this.pollTask);
24447             delete this.pollTask;
24448             this.fireEvent('disconnect', this);
24449         }
24450     },
24451
24452     
24453     onData: function(opt, success, xhr){
24454         if(success){
24455             var events = this.getEvents(xhr);
24456             for(var i = 0, len = events.length; i < len; i++){
24457                 var e = events[i];
24458                 this.fireEvent('data', this, e);
24459             }
24460         }else{
24461             var e = new Ext.Direct.ExceptionEvent({
24462                 data: e,
24463                 code: Ext.Direct.exceptions.TRANSPORT,
24464                 message: 'Unable to connect to the server.',
24465                 xhr: xhr
24466             });
24467             this.fireEvent('data', this, e);
24468         }
24469     }
24470 });
24471
24472 Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
24473 Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
24474     
24475     
24476     
24477     
24478     
24479     
24480     
24481     
24482     
24483     enableBuffer: 10,
24484     
24485     
24486     maxRetries: 1,
24487     
24488     
24489     timeout: undefined,
24490
24491     constructor : function(config){
24492         Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
24493         this.addEvents(
24494                         
24495             'beforecall',            
24496                         
24497             'call'
24498         );
24499         this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
24500         this.transactions = {};
24501         this.callBuffer = [];
24502     },
24503
24504     
24505     initAPI : function(){
24506         var o = this.actions;
24507         for(var c in o){
24508             var cls = this.namespace[c] || (this.namespace[c] = {}),
24509                 ms = o[c];
24510             for(var i = 0, len = ms.length; i < len; i++){
24511                 var m = ms[i];
24512                 cls[m.name] = this.createMethod(c, m);
24513             }
24514         }
24515     },
24516
24517     
24518     isConnected: function(){
24519         return !!this.connected;
24520     },
24521
24522     connect: function(){
24523         if(this.url){
24524             this.initAPI();
24525             this.connected = true;
24526             this.fireEvent('connect', this);
24527         }else if(!this.url){
24528             throw 'Error initializing RemotingProvider, no url configured.';
24529         }
24530     },
24531
24532     disconnect: function(){
24533         if(this.connected){
24534             this.connected = false;
24535             this.fireEvent('disconnect', this);
24536         }
24537     },
24538
24539     onData: function(opt, success, xhr){
24540         if(success){
24541             var events = this.getEvents(xhr);
24542             for(var i = 0, len = events.length; i < len; i++){
24543                 var e = events[i],
24544                     t = this.getTransaction(e);
24545                 this.fireEvent('data', this, e);
24546                 if(t){
24547                     this.doCallback(t, e, true);
24548                     Ext.Direct.removeTransaction(t);
24549                 }
24550             }
24551         }else{
24552             var ts = [].concat(opt.ts);
24553             for(var i = 0, len = ts.length; i < len; i++){
24554                 var t = this.getTransaction(ts[i]);
24555                 if(t && t.retryCount < this.maxRetries){
24556                     t.retry();
24557                 }else{
24558                     var e = new Ext.Direct.ExceptionEvent({
24559                         data: e,
24560                         transaction: t,
24561                         code: Ext.Direct.exceptions.TRANSPORT,
24562                         message: 'Unable to connect to the server.',
24563                         xhr: xhr
24564                     });
24565                     this.fireEvent('data', this, e);
24566                     if(t){
24567                         this.doCallback(t, e, false);
24568                         Ext.Direct.removeTransaction(t);
24569                     }
24570                 }
24571             }
24572         }
24573     },
24574
24575     getCallData: function(t){
24576         return {
24577             action: t.action,
24578             method: t.method,
24579             data: t.data,
24580             type: 'rpc',
24581             tid: t.tid
24582         };
24583     },
24584
24585     doSend : function(data){
24586         var o = {
24587             url: this.url,
24588             callback: this.onData,
24589             scope: this,
24590             ts: data,
24591             timeout: this.timeout
24592         }, callData;
24593
24594         if(Ext.isArray(data)){
24595             callData = [];
24596             for(var i = 0, len = data.length; i < len; i++){
24597                 callData.push(this.getCallData(data[i]));
24598             }
24599         }else{
24600             callData = this.getCallData(data);
24601         }
24602
24603         if(this.enableUrlEncode){
24604             var params = {};
24605             params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
24606             o.params = params;
24607         }else{
24608             o.jsonData = callData;
24609         }
24610         Ext.Ajax.request(o);
24611     },
24612
24613     combineAndSend : function(){
24614         var len = this.callBuffer.length;
24615         if(len > 0){
24616             this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
24617             this.callBuffer = [];
24618         }
24619     },
24620
24621     queueTransaction: function(t){
24622         if(t.form){
24623             this.processForm(t);
24624             return;
24625         }
24626         this.callBuffer.push(t);
24627         if(this.enableBuffer){
24628             if(!this.callTask){
24629                 this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
24630             }
24631             this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
24632         }else{
24633             this.combineAndSend();
24634         }
24635     },
24636
24637     doCall : function(c, m, args){
24638         var data = null, hs = args[m.len], scope = args[m.len+1];
24639
24640         if(m.len !== 0){
24641             data = args.slice(0, m.len);
24642         }
24643
24644         var t = new Ext.Direct.Transaction({
24645             provider: this,
24646             args: args,
24647             action: c,
24648             method: m.name,
24649             data: data,
24650             cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
24651         });
24652
24653         if(this.fireEvent('beforecall', this, t) !== false){
24654             Ext.Direct.addTransaction(t);
24655             this.queueTransaction(t);
24656             this.fireEvent('call', this, t);
24657         }
24658     },
24659
24660     doForm : function(c, m, form, callback, scope){
24661         var t = new Ext.Direct.Transaction({
24662             provider: this,
24663             action: c,
24664             method: m.name,
24665             args:[form, callback, scope],
24666             cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
24667             isForm: true
24668         });
24669
24670         if(this.fireEvent('beforecall', this, t) !== false){
24671             Ext.Direct.addTransaction(t);
24672             var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
24673                 params = {
24674                     extTID: t.tid,
24675                     extAction: c,
24676                     extMethod: m.name,
24677                     extType: 'rpc',
24678                     extUpload: String(isUpload)
24679                 };
24680             
24681             
24682             
24683             Ext.apply(t, {
24684                 form: Ext.getDom(form),
24685                 isUpload: isUpload,
24686                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
24687             });
24688             this.fireEvent('call', this, t);
24689             this.processForm(t);
24690         }
24691     },
24692     
24693     processForm: function(t){
24694         Ext.Ajax.request({
24695             url: this.url,
24696             params: t.params,
24697             callback: this.onData,
24698             scope: this,
24699             form: t.form,
24700             isUpload: t.isUpload,
24701             ts: t
24702         });
24703     },
24704
24705     createMethod : function(c, m){
24706         var f;
24707         if(!m.formHandler){
24708             f = function(){
24709                 this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
24710             }.createDelegate(this);
24711         }else{
24712             f = function(form, callback, scope){
24713                 this.doForm(c, m, form, callback, scope);
24714             }.createDelegate(this);
24715         }
24716         f.directCfg = {
24717             action: c,
24718             method: m
24719         };
24720         return f;
24721     },
24722
24723     getTransaction: function(opt){
24724         return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
24725     },
24726
24727     doCallback: function(t, e){
24728         var fn = e.status ? 'success' : 'failure';
24729         if(t && t.cb){
24730             var hs = t.cb,
24731                 result = Ext.isDefined(e.result) ? e.result : e.data;
24732             if(Ext.isFunction(hs)){
24733                 hs(result, e);
24734             } else{
24735                 Ext.callback(hs[fn], hs.scope, [result, e]);
24736                 Ext.callback(hs.callback, hs.scope, [result, e]);
24737             }
24738         }
24739     }
24740 });
24741 Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
24742 Ext.Resizable = Ext.extend(Ext.util.Observable, {
24743
24744     constructor: function(el, config){
24745         this.el = Ext.get(el);
24746         if(config && config.wrap){
24747             config.resizeChild = this.el;
24748             this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
24749             this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
24750             this.el.setStyle('overflow', 'hidden');
24751             this.el.setPositioning(config.resizeChild.getPositioning());
24752             config.resizeChild.clearPositioning();
24753             if(!config.width || !config.height){
24754                 var csize = config.resizeChild.getSize();
24755                 this.el.setSize(csize.width, csize.height);
24756             }
24757             if(config.pinned && !config.adjustments){
24758                 config.adjustments = 'auto';
24759             }
24760         }
24761
24762         
24763         this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
24764         this.proxy.unselectable();
24765         this.proxy.enableDisplayMode('block');
24766
24767         Ext.apply(this, config);
24768
24769         if(this.pinned){
24770             this.disableTrackOver = true;
24771             this.el.addClass('x-resizable-pinned');
24772         }
24773         
24774         var position = this.el.getStyle('position');
24775         if(position != 'absolute' && position != 'fixed'){
24776             this.el.setStyle('position', 'relative');
24777         }
24778         if(!this.handles){ 
24779             this.handles = 's,e,se';
24780             if(this.multiDirectional){
24781                 this.handles += ',n,w';
24782             }
24783         }
24784         if(this.handles == 'all'){
24785             this.handles = 'n s e w ne nw se sw';
24786         }
24787         var hs = this.handles.split(/\s*?[,;]\s*?| /);
24788         var ps = Ext.Resizable.positions;
24789         for(var i = 0, len = hs.length; i < len; i++){
24790             if(hs[i] && ps[hs[i]]){
24791                 var pos = ps[hs[i]];
24792                 this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
24793             }
24794         }
24795         
24796         this.corner = this.southeast;
24797
24798         if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
24799             this.updateBox = true;
24800         }
24801
24802         this.activeHandle = null;
24803
24804         if(this.resizeChild){
24805             if(typeof this.resizeChild == 'boolean'){
24806                 this.resizeChild = Ext.get(this.el.dom.firstChild, true);
24807             }else{
24808                 this.resizeChild = Ext.get(this.resizeChild, true);
24809             }
24810         }
24811
24812         if(this.adjustments == 'auto'){
24813             var rc = this.resizeChild;
24814             var hw = this.west, he = this.east, hn = this.north, hs = this.south;
24815             if(rc && (hw || hn)){
24816                 rc.position('relative');
24817                 rc.setLeft(hw ? hw.el.getWidth() : 0);
24818                 rc.setTop(hn ? hn.el.getHeight() : 0);
24819             }
24820             this.adjustments = [
24821                 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
24822                 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
24823             ];
24824         }
24825
24826         if(this.draggable){
24827             this.dd = this.dynamic ?
24828                 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
24829             this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
24830             if(this.constrainTo){
24831                 this.dd.constrainTo(this.constrainTo);
24832             }
24833         }
24834
24835         this.addEvents(
24836             
24837             'beforeresize',
24838             
24839             'resize'
24840         );
24841
24842         if(this.width !== null && this.height !== null){
24843             this.resizeTo(this.width, this.height);
24844         }else{
24845             this.updateChildSize();
24846         }
24847         if(Ext.isIE){
24848             this.el.dom.style.zoom = 1;
24849         }
24850         Ext.Resizable.superclass.constructor.call(this);
24851     },
24852
24853     
24854     adjustments : [0, 0],
24855     
24856     animate : false,
24857     
24858     
24859     disableTrackOver : false,
24860     
24861     draggable: false,
24862     
24863     duration : 0.35,
24864     
24865     dynamic : false,
24866     
24867     easing : 'easeOutStrong',
24868     
24869     enabled : true,
24870     
24871     
24872     handles : false,
24873     
24874     multiDirectional : false,
24875     
24876     height : null,
24877     
24878     width : null,
24879     
24880     heightIncrement : 0,
24881     
24882     widthIncrement : 0,
24883     
24884     minHeight : 5,
24885     
24886     minWidth : 5,
24887     
24888     maxHeight : 10000,
24889     
24890     maxWidth : 10000,
24891     
24892     minX: 0,
24893     
24894     minY: 0,
24895     
24896     pinned : false,
24897     
24898     preserveRatio : false,
24899     
24900     resizeChild : false,
24901     
24902     transparent: false,
24903     
24904     
24905     
24906
24907
24908     
24909     resizeTo : function(width, height){
24910         this.el.setSize(width, height);
24911         this.updateChildSize();
24912         this.fireEvent('resize', this, width, height, null);
24913     },
24914
24915     
24916     startSizing : function(e, handle){
24917         this.fireEvent('beforeresize', this, e);
24918         if(this.enabled){ 
24919
24920             if(!this.overlay){
24921                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
24922                 this.overlay.unselectable();
24923                 this.overlay.enableDisplayMode('block');
24924                 this.overlay.on({
24925                     scope: this,
24926                     mousemove: this.onMouseMove,
24927                     mouseup: this.onMouseUp
24928                 });
24929             }
24930             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
24931
24932             this.resizing = true;
24933             this.startBox = this.el.getBox();
24934             this.startPoint = e.getXY();
24935             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
24936                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
24937
24938             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
24939             this.overlay.show();
24940
24941             if(this.constrainTo) {
24942                 var ct = Ext.get(this.constrainTo);
24943                 this.resizeRegion = ct.getRegion().adjust(
24944                     ct.getFrameWidth('t'),
24945                     ct.getFrameWidth('l'),
24946                     -ct.getFrameWidth('b'),
24947                     -ct.getFrameWidth('r')
24948                 );
24949             }
24950
24951             this.proxy.setStyle('visibility', 'hidden'); 
24952             this.proxy.show();
24953             this.proxy.setBox(this.startBox);
24954             if(!this.dynamic){
24955                 this.proxy.setStyle('visibility', 'visible');
24956             }
24957         }
24958     },
24959
24960     
24961     onMouseDown : function(handle, e){
24962         if(this.enabled){
24963             e.stopEvent();
24964             this.activeHandle = handle;
24965             this.startSizing(e, handle);
24966         }
24967     },
24968
24969     
24970     onMouseUp : function(e){
24971         this.activeHandle = null;
24972         var size = this.resizeElement();
24973         this.resizing = false;
24974         this.handleOut();
24975         this.overlay.hide();
24976         this.proxy.hide();
24977         this.fireEvent('resize', this, size.width, size.height, e);
24978     },
24979
24980     
24981     updateChildSize : function(){
24982         if(this.resizeChild){
24983             var el = this.el;
24984             var child = this.resizeChild;
24985             var adj = this.adjustments;
24986             if(el.dom.offsetWidth){
24987                 var b = el.getSize(true);
24988                 child.setSize(b.width+adj[0], b.height+adj[1]);
24989             }
24990             
24991             
24992             
24993             
24994             if(Ext.isIE){
24995                 setTimeout(function(){
24996                     if(el.dom.offsetWidth){
24997                         var b = el.getSize(true);
24998                         child.setSize(b.width+adj[0], b.height+adj[1]);
24999                     }
25000                 }, 10);
25001             }
25002         }
25003     },
25004
25005     
25006     snap : function(value, inc, min){
25007         if(!inc || !value){
25008             return value;
25009         }
25010         var newValue = value;
25011         var m = value % inc;
25012         if(m > 0){
25013             if(m > (inc/2)){
25014                 newValue = value + (inc-m);
25015             }else{
25016                 newValue = value - m;
25017             }
25018         }
25019         return Math.max(min, newValue);
25020     },
25021
25022     
25023     resizeElement : function(){
25024         var box = this.proxy.getBox();
25025         if(this.updateBox){
25026             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
25027         }else{
25028             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
25029         }
25030         this.updateChildSize();
25031         if(!this.dynamic){
25032             this.proxy.hide();
25033         }
25034         if(this.draggable && this.constrainTo){
25035             this.dd.resetConstraints();
25036             this.dd.constrainTo(this.constrainTo);
25037         }
25038         return box;
25039     },
25040
25041     
25042     constrain : function(v, diff, m, mx){
25043         if(v - diff < m){
25044             diff = v - m;
25045         }else if(v - diff > mx){
25046             diff = v - mx;
25047         }
25048         return diff;
25049     },
25050
25051     
25052     onMouseMove : function(e){
25053         if(this.enabled && this.activeHandle){
25054             try{
25055
25056             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
25057                 return;
25058             }
25059
25060             
25061             var curSize = this.curSize || this.startBox,
25062                 x = this.startBox.x, y = this.startBox.y,
25063                 ox = x,
25064                 oy = y,
25065                 w = curSize.width,
25066                 h = curSize.height,
25067                 ow = w,
25068                 oh = h,
25069                 mw = this.minWidth,
25070                 mh = this.minHeight,
25071                 mxw = this.maxWidth,
25072                 mxh = this.maxHeight,
25073                 wi = this.widthIncrement,
25074                 hi = this.heightIncrement,
25075                 eventXY = e.getXY(),
25076                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
25077                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
25078                 pos = this.activeHandle.position,
25079                 tw,
25080                 th;
25081
25082             switch(pos){
25083                 case 'east':
25084                     w += diffX;
25085                     w = Math.min(Math.max(mw, w), mxw);
25086                     break;
25087                 case 'south':
25088                     h += diffY;
25089                     h = Math.min(Math.max(mh, h), mxh);
25090                     break;
25091                 case 'southeast':
25092                     w += diffX;
25093                     h += diffY;
25094                     w = Math.min(Math.max(mw, w), mxw);
25095                     h = Math.min(Math.max(mh, h), mxh);
25096                     break;
25097                 case 'north':
25098                     diffY = this.constrain(h, diffY, mh, mxh);
25099                     y += diffY;
25100                     h -= diffY;
25101                     break;
25102                 case 'west':
25103                     diffX = this.constrain(w, diffX, mw, mxw);
25104                     x += diffX;
25105                     w -= diffX;
25106                     break;
25107                 case 'northeast':
25108                     w += diffX;
25109                     w = Math.min(Math.max(mw, w), mxw);
25110                     diffY = this.constrain(h, diffY, mh, mxh);
25111                     y += diffY;
25112                     h -= diffY;
25113                     break;
25114                 case 'northwest':
25115                     diffX = this.constrain(w, diffX, mw, mxw);
25116                     diffY = this.constrain(h, diffY, mh, mxh);
25117                     y += diffY;
25118                     h -= diffY;
25119                     x += diffX;
25120                     w -= diffX;
25121                     break;
25122                case 'southwest':
25123                     diffX = this.constrain(w, diffX, mw, mxw);
25124                     h += diffY;
25125                     h = Math.min(Math.max(mh, h), mxh);
25126                     x += diffX;
25127                     w -= diffX;
25128                     break;
25129             }
25130
25131             var sw = this.snap(w, wi, mw);
25132             var sh = this.snap(h, hi, mh);
25133             if(sw != w || sh != h){
25134                 switch(pos){
25135                     case 'northeast':
25136                         y -= sh - h;
25137                     break;
25138                     case 'north':
25139                         y -= sh - h;
25140                         break;
25141                     case 'southwest':
25142                         x -= sw - w;
25143                     break;
25144                     case 'west':
25145                         x -= sw - w;
25146                         break;
25147                     case 'northwest':
25148                         x -= sw - w;
25149                         y -= sh - h;
25150                     break;
25151                 }
25152                 w = sw;
25153                 h = sh;
25154             }
25155
25156             if(this.preserveRatio){
25157                 switch(pos){
25158                     case 'southeast':
25159                     case 'east':
25160                         h = oh * (w/ow);
25161                         h = Math.min(Math.max(mh, h), mxh);
25162                         w = ow * (h/oh);
25163                        break;
25164                     case 'south':
25165                         w = ow * (h/oh);
25166                         w = Math.min(Math.max(mw, w), mxw);
25167                         h = oh * (w/ow);
25168                         break;
25169                     case 'northeast':
25170                         w = ow * (h/oh);
25171                         w = Math.min(Math.max(mw, w), mxw);
25172                         h = oh * (w/ow);
25173                     break;
25174                     case 'north':
25175                         tw = w;
25176                         w = ow * (h/oh);
25177                         w = Math.min(Math.max(mw, w), mxw);
25178                         h = oh * (w/ow);
25179                         x += (tw - w) / 2;
25180                         break;
25181                     case 'southwest':
25182                         h = oh * (w/ow);
25183                         h = Math.min(Math.max(mh, h), mxh);
25184                         tw = w;
25185                         w = ow * (h/oh);
25186                         x += tw - w;
25187                         break;
25188                     case 'west':
25189                         th = h;
25190                         h = oh * (w/ow);
25191                         h = Math.min(Math.max(mh, h), mxh);
25192                         y += (th - h) / 2;
25193                         tw = w;
25194                         w = ow * (h/oh);
25195                         x += tw - w;
25196                        break;
25197                     case 'northwest':
25198                         tw = w;
25199                         th = h;
25200                         h = oh * (w/ow);
25201                         h = Math.min(Math.max(mh, h), mxh);
25202                         w = ow * (h/oh);
25203                         y += th - h;
25204                         x += tw - w;
25205                         break;
25206
25207                 }
25208             }
25209             this.proxy.setBounds(x, y, w, h);
25210             if(this.dynamic){
25211                 this.resizeElement();
25212             }
25213             }catch(ex){}
25214         }
25215     },
25216
25217     
25218     handleOver : function(){
25219         if(this.enabled){
25220             this.el.addClass('x-resizable-over');
25221         }
25222     },
25223
25224     
25225     handleOut : function(){
25226         if(!this.resizing){
25227             this.el.removeClass('x-resizable-over');
25228         }
25229     },
25230
25231     
25232     getEl : function(){
25233         return this.el;
25234     },
25235
25236     
25237     getResizeChild : function(){
25238         return this.resizeChild;
25239     },
25240
25241     
25242     destroy : function(removeEl){
25243         Ext.destroy(this.dd, this.overlay, this.proxy);
25244         this.overlay = null;
25245         this.proxy = null;
25246
25247         var ps = Ext.Resizable.positions;
25248         for(var k in ps){
25249             if(typeof ps[k] != 'function' && this[ps[k]]){
25250                 this[ps[k]].destroy();
25251             }
25252         }
25253         if(removeEl){
25254             this.el.update('');
25255             Ext.destroy(this.el);
25256             this.el = null;
25257         }
25258         this.purgeListeners();
25259     },
25260
25261     syncHandleHeight : function(){
25262         var h = this.el.getHeight(true);
25263         if(this.west){
25264             this.west.el.setHeight(h);
25265         }
25266         if(this.east){
25267             this.east.el.setHeight(h);
25268         }
25269     }
25270 });
25271
25272
25273
25274 Ext.Resizable.positions = {
25275     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
25276 };
25277
25278 Ext.Resizable.Handle = Ext.extend(Object, {
25279     constructor : function(rz, pos, disableTrackOver, transparent, cls){
25280        if(!this.tpl){
25281             
25282             var tpl = Ext.DomHelper.createTemplate(
25283                 {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
25284             );
25285             tpl.compile();
25286             Ext.Resizable.Handle.prototype.tpl = tpl;
25287         }
25288         this.position = pos;
25289         this.rz = rz;
25290         this.el = this.tpl.append(rz.el.dom, [this.position], true);
25291         this.el.unselectable();
25292         if(transparent){
25293             this.el.setOpacity(0);
25294         }
25295         if(!Ext.isEmpty(cls)){
25296             this.el.addClass(cls);
25297         }
25298         this.el.on('mousedown', this.onMouseDown, this);
25299         if(!disableTrackOver){
25300             this.el.on({
25301                 scope: this,
25302                 mouseover: this.onMouseOver,
25303                 mouseout: this.onMouseOut
25304             });
25305         }
25306     },
25307
25308     
25309     afterResize : function(rz){
25310         
25311     },
25312     
25313     onMouseDown : function(e){
25314         this.rz.onMouseDown(this, e);
25315     },
25316     
25317     onMouseOver : function(e){
25318         this.rz.handleOver(this, e);
25319     },
25320     
25321     onMouseOut : function(e){
25322         this.rz.handleOut(this, e);
25323     },
25324     
25325     destroy : function(){
25326         Ext.destroy(this.el);
25327         this.el = null;
25328     }
25329 });
25330
25331 Ext.Window = Ext.extend(Ext.Panel, {
25332     
25333     
25334     
25335     
25336     
25337     
25338     
25339     
25340     
25341     
25342
25343     
25344     baseCls : 'x-window',
25345     
25346     resizable : true,
25347     
25348     draggable : true,
25349     
25350     closable : true,
25351     
25352     closeAction : 'close',
25353     
25354     constrain : false,
25355     
25356     constrainHeader : false,
25357     
25358     plain : false,
25359     
25360     minimizable : false,
25361     
25362     maximizable : false,
25363     
25364     minHeight : 100,
25365     
25366     minWidth : 200,
25367     
25368     expandOnShow : true,
25369
25370     
25371     collapsible : false,
25372
25373     
25374     initHidden : undefined,
25375
25376     
25377     hidden : true,
25378
25379     
25380     
25381     
25382     
25383     
25384     elements : 'header,body',
25385     
25386     frame : true,
25387     
25388     floating : true,
25389
25390     
25391     initComponent : function(){
25392         this.initTools();
25393         Ext.Window.superclass.initComponent.call(this);
25394         this.addEvents(
25395             
25396             
25397             
25398             'resize',
25399             
25400             'maximize',
25401             
25402             'minimize',
25403             
25404             'restore'
25405         );
25406         
25407         if(Ext.isDefined(this.initHidden)){
25408             this.hidden = this.initHidden;
25409         }
25410         if(this.hidden === false){
25411             this.hidden = true;
25412             this.show();
25413         }
25414     },
25415
25416     
25417     getState : function(){
25418         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
25419     },
25420
25421     
25422     onRender : function(ct, position){
25423         Ext.Window.superclass.onRender.call(this, ct, position);
25424
25425         if(this.plain){
25426             this.el.addClass('x-window-plain');
25427         }
25428
25429         
25430         this.focusEl = this.el.createChild({
25431                     tag: 'a', href:'#', cls:'x-dlg-focus',
25432                     tabIndex:'-1', html: '&#160;'});
25433         this.focusEl.swallowEvent('click', true);
25434
25435         this.proxy = this.el.createProxy('x-window-proxy');
25436         this.proxy.enableDisplayMode('block');
25437
25438         if(this.modal){
25439             this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
25440             this.mask.enableDisplayMode('block');
25441             this.mask.hide();
25442             this.mon(this.mask, 'click', this.focus, this);
25443         }
25444         if(this.maximizable){
25445             this.mon(this.header, 'dblclick', this.toggleMaximize, this);
25446         }
25447     },
25448
25449     
25450     initEvents : function(){
25451         Ext.Window.superclass.initEvents.call(this);
25452         if(this.animateTarget){
25453             this.setAnimateTarget(this.animateTarget);
25454         }
25455
25456         if(this.resizable){
25457             this.resizer = new Ext.Resizable(this.el, {
25458                 minWidth: this.minWidth,
25459                 minHeight:this.minHeight,
25460                 handles: this.resizeHandles || 'all',
25461                 pinned: true,
25462                 resizeElement : this.resizerAction,
25463                 handleCls: 'x-window-handle'
25464             });
25465             this.resizer.window = this;
25466             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
25467         }
25468
25469         if(this.draggable){
25470             this.header.addClass('x-window-draggable');
25471         }
25472         this.mon(this.el, 'mousedown', this.toFront, this);
25473         this.manager = this.manager || Ext.WindowMgr;
25474         this.manager.register(this);
25475         if(this.maximized){
25476             this.maximized = false;
25477             this.maximize();
25478         }
25479         if(this.closable){
25480             var km = this.getKeyMap();
25481             km.on(27, this.onEsc, this);
25482             km.disable();
25483         }
25484     },
25485
25486     initDraggable : function(){
25487         
25488         this.dd = new Ext.Window.DD(this);
25489     },
25490
25491    
25492     onEsc : function(k, e){
25493         e.stopEvent();
25494         this[this.closeAction]();
25495     },
25496
25497     
25498     beforeDestroy : function(){
25499         if(this.rendered){
25500             this.hide();
25501             this.clearAnchor();
25502             Ext.destroy(
25503                 this.focusEl,
25504                 this.resizer,
25505                 this.dd,
25506                 this.proxy,
25507                 this.mask
25508             );
25509         }
25510         Ext.Window.superclass.beforeDestroy.call(this);
25511     },
25512
25513     
25514     onDestroy : function(){
25515         if(this.manager){
25516             this.manager.unregister(this);
25517         }
25518         Ext.Window.superclass.onDestroy.call(this);
25519     },
25520
25521     
25522     initTools : function(){
25523         if(this.minimizable){
25524             this.addTool({
25525                 id: 'minimize',
25526                 handler: this.minimize.createDelegate(this, [])
25527             });
25528         }
25529         if(this.maximizable){
25530             this.addTool({
25531                 id: 'maximize',
25532                 handler: this.maximize.createDelegate(this, [])
25533             });
25534             this.addTool({
25535                 id: 'restore',
25536                 handler: this.restore.createDelegate(this, []),
25537                 hidden:true
25538             });
25539         }
25540         if(this.closable){
25541             this.addTool({
25542                 id: 'close',
25543                 handler: this[this.closeAction].createDelegate(this, [])
25544             });
25545         }
25546     },
25547
25548     
25549     resizerAction : function(){
25550         var box = this.proxy.getBox();
25551         this.proxy.hide();
25552         this.window.handleResize(box);
25553         return box;
25554     },
25555
25556     
25557     beforeResize : function(){
25558         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
25559         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
25560         this.resizeBox = this.el.getBox();
25561     },
25562
25563     
25564     updateHandles : function(){
25565         if(Ext.isIE && this.resizer){
25566             this.resizer.syncHandleHeight();
25567             this.el.repaint();
25568         }
25569     },
25570
25571     
25572     handleResize : function(box){
25573         var rz = this.resizeBox;
25574         if(rz.x != box.x || rz.y != box.y){
25575             this.updateBox(box);
25576         }else{
25577             this.setSize(box);
25578             if (Ext.isIE6 && Ext.isStrict) {
25579                 this.doLayout();
25580             }
25581         }
25582         this.focus();
25583         this.updateHandles();
25584         this.saveState();
25585     },
25586
25587     
25588     focus : function(){
25589         var f = this.focusEl,
25590             db = this.defaultButton,
25591             t = typeof db,
25592             el,
25593             ct;
25594         if(Ext.isDefined(db)){
25595             if(Ext.isNumber(db) && this.fbar){
25596                 f = this.fbar.items.get(db);
25597             }else if(Ext.isString(db)){
25598                 f = Ext.getCmp(db);
25599             }else{
25600                 f = db;
25601             }
25602             el = f.getEl();
25603             ct = Ext.getDom(this.container);
25604             if (el && ct) {
25605                 if (!Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
25606                     return;
25607                 }
25608             }
25609         }
25610         f = f || this.focusEl;
25611         f.focus.defer(10, f);
25612     },
25613
25614     
25615     setAnimateTarget : function(el){
25616         el = Ext.get(el);
25617         this.animateTarget = el;
25618     },
25619
25620     
25621     beforeShow : function(){
25622         delete this.el.lastXY;
25623         delete this.el.lastLT;
25624         if(this.x === undefined || this.y === undefined){
25625             var xy = this.el.getAlignToXY(this.container, 'c-c');
25626             var pos = this.el.translatePoints(xy[0], xy[1]);
25627             this.x = this.x === undefined? pos.left : this.x;
25628             this.y = this.y === undefined? pos.top : this.y;
25629         }
25630         this.el.setLeftTop(this.x, this.y);
25631
25632         if(this.expandOnShow){
25633             this.expand(false);
25634         }
25635
25636         if(this.modal){
25637             Ext.getBody().addClass('x-body-masked');
25638             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
25639             this.mask.show();
25640         }
25641     },
25642
25643     
25644     show : function(animateTarget, cb, scope){
25645         if(!this.rendered){
25646             this.render(Ext.getBody());
25647         }
25648         if(this.hidden === false){
25649             this.toFront();
25650             return this;
25651         }
25652         if(this.fireEvent('beforeshow', this) === false){
25653             return this;
25654         }
25655         if(cb){
25656             this.on('show', cb, scope, {single:true});
25657         }
25658         this.hidden = false;
25659         if(Ext.isDefined(animateTarget)){
25660             this.setAnimateTarget(animateTarget);
25661         }
25662         this.beforeShow();
25663         if(this.animateTarget){
25664             this.animShow();
25665         }else{
25666             this.afterShow();
25667         }
25668         return this;
25669     },
25670
25671     
25672     afterShow : function(isAnim){
25673         if (this.isDestroyed){
25674             return false;
25675         }
25676         this.proxy.hide();
25677         this.el.setStyle('display', 'block');
25678         this.el.show();
25679         if(this.maximized){
25680             this.fitContainer();
25681         }
25682         if(Ext.isMac && Ext.isGecko2){ 
25683             this.cascade(this.setAutoScroll);
25684         }
25685
25686         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
25687             Ext.EventManager.onWindowResize(this.onWindowResize, this);
25688         }
25689         this.doConstrain();
25690         this.doLayout();
25691         if(this.keyMap){
25692             this.keyMap.enable();
25693         }
25694         this.toFront();
25695         this.updateHandles();
25696         if(isAnim && (Ext.isIE || Ext.isWebKit)){
25697             var sz = this.getSize();
25698             this.onResize(sz.width, sz.height);
25699         }
25700         this.onShow();
25701         this.fireEvent('show', this);
25702     },
25703
25704     
25705     animShow : function(){
25706         this.proxy.show();
25707         this.proxy.setBox(this.animateTarget.getBox());
25708         this.proxy.setOpacity(0);
25709         var b = this.getBox();
25710         this.el.setStyle('display', 'none');
25711         this.proxy.shift(Ext.apply(b, {
25712             callback: this.afterShow.createDelegate(this, [true], false),
25713             scope: this,
25714             easing: 'easeNone',
25715             duration: 0.25,
25716             opacity: 0.5
25717         }));
25718     },
25719
25720     
25721     hide : function(animateTarget, cb, scope){
25722         if(this.hidden || this.fireEvent('beforehide', this) === false){
25723             return this;
25724         }
25725         if(cb){
25726             this.on('hide', cb, scope, {single:true});
25727         }
25728         this.hidden = true;
25729         if(animateTarget !== undefined){
25730             this.setAnimateTarget(animateTarget);
25731         }
25732         if(this.modal){
25733             this.mask.hide();
25734             Ext.getBody().removeClass('x-body-masked');
25735         }
25736         if(this.animateTarget){
25737             this.animHide();
25738         }else{
25739             this.el.hide();
25740             this.afterHide();
25741         }
25742         return this;
25743     },
25744
25745     
25746     afterHide : function(){
25747         this.proxy.hide();
25748         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
25749             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
25750         }
25751         if(this.keyMap){
25752             this.keyMap.disable();
25753         }
25754         this.onHide();
25755         this.fireEvent('hide', this);
25756     },
25757
25758     
25759     animHide : function(){
25760         this.proxy.setOpacity(0.5);
25761         this.proxy.show();
25762         var tb = this.getBox(false);
25763         this.proxy.setBox(tb);
25764         this.el.hide();
25765         this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
25766             callback: this.afterHide,
25767             scope: this,
25768             duration: 0.25,
25769             easing: 'easeNone',
25770             opacity: 0
25771         }));
25772     },
25773
25774     
25775     onShow : Ext.emptyFn,
25776
25777     
25778     onHide : Ext.emptyFn,
25779
25780     
25781     onWindowResize : function(){
25782         if(this.maximized){
25783             this.fitContainer();
25784         }
25785         if(this.modal){
25786             this.mask.setSize('100%', '100%');
25787             var force = this.mask.dom.offsetHeight;
25788             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
25789         }
25790         this.doConstrain();
25791     },
25792
25793     
25794     doConstrain : function(){
25795         if(this.constrain || this.constrainHeader){
25796             var offsets;
25797             if(this.constrain){
25798                 offsets = {
25799                     right:this.el.shadowOffset,
25800                     left:this.el.shadowOffset,
25801                     bottom:this.el.shadowOffset
25802                 };
25803             }else {
25804                 var s = this.getSize();
25805                 offsets = {
25806                     right:-(s.width - 100),
25807                     bottom:-(s.height - 25)
25808                 };
25809             }
25810
25811             var xy = this.el.getConstrainToXY(this.container, true, offsets);
25812             if(xy){
25813                 this.setPosition(xy[0], xy[1]);
25814             }
25815         }
25816     },
25817
25818     
25819     ghost : function(cls){
25820         var ghost = this.createGhost(cls);
25821         var box = this.getBox(true);
25822         ghost.setLeftTop(box.x, box.y);
25823         ghost.setWidth(box.width);
25824         this.el.hide();
25825         this.activeGhost = ghost;
25826         return ghost;
25827     },
25828
25829     
25830     unghost : function(show, matchPosition){
25831         if(!this.activeGhost) {
25832             return;
25833         }
25834         if(show !== false){
25835             this.el.show();
25836             this.focus.defer(10, this);
25837             if(Ext.isMac && Ext.isGecko2){ 
25838                 this.cascade(this.setAutoScroll);
25839             }
25840         }
25841         if(matchPosition !== false){
25842             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
25843         }
25844         this.activeGhost.hide();
25845         this.activeGhost.remove();
25846         delete this.activeGhost;
25847     },
25848
25849     
25850     minimize : function(){
25851         this.fireEvent('minimize', this);
25852         return this;
25853     },
25854
25855     
25856     close : function(){
25857         if(this.fireEvent('beforeclose', this) !== false){
25858             if(this.hidden){
25859                 this.doClose();
25860             }else{
25861                 this.hide(null, this.doClose, this);
25862             }
25863         }
25864     },
25865
25866     
25867     doClose : function(){
25868         this.fireEvent('close', this);
25869         this.destroy();
25870     },
25871
25872     
25873     maximize : function(){
25874         if(!this.maximized){
25875             this.expand(false);
25876             this.restoreSize = this.getSize();
25877             this.restorePos = this.getPosition(true);
25878             if (this.maximizable){
25879                 this.tools.maximize.hide();
25880                 this.tools.restore.show();
25881             }
25882             this.maximized = true;
25883             this.el.disableShadow();
25884
25885             if(this.dd){
25886                 this.dd.lock();
25887             }
25888             if(this.collapsible){
25889                 this.tools.toggle.hide();
25890             }
25891             this.el.addClass('x-window-maximized');
25892             this.container.addClass('x-window-maximized-ct');
25893
25894             this.setPosition(0, 0);
25895             this.fitContainer();
25896             this.fireEvent('maximize', this);
25897         }
25898         return this;
25899     },
25900
25901     
25902     restore : function(){
25903         if(this.maximized){
25904             var t = this.tools;
25905             this.el.removeClass('x-window-maximized');
25906             if(t.restore){
25907                 t.restore.hide();
25908             }
25909             if(t.maximize){
25910                 t.maximize.show();
25911             }
25912             this.setPosition(this.restorePos[0], this.restorePos[1]);
25913             this.setSize(this.restoreSize.width, this.restoreSize.height);
25914             delete this.restorePos;
25915             delete this.restoreSize;
25916             this.maximized = false;
25917             this.el.enableShadow(true);
25918
25919             if(this.dd){
25920                 this.dd.unlock();
25921             }
25922             if(this.collapsible && t.toggle){
25923                 t.toggle.show();
25924             }
25925             this.container.removeClass('x-window-maximized-ct');
25926
25927             this.doConstrain();
25928             this.fireEvent('restore', this);
25929         }
25930         return this;
25931     },
25932
25933     
25934     toggleMaximize : function(){
25935         return this[this.maximized ? 'restore' : 'maximize']();
25936     },
25937
25938     
25939     fitContainer : function(){
25940         var vs = this.container.getViewSize(false);
25941         this.setSize(vs.width, vs.height);
25942     },
25943
25944     
25945     
25946     setZIndex : function(index){
25947         if(this.modal){
25948             this.mask.setStyle('z-index', index);
25949         }
25950         this.el.setZIndex(++index);
25951         index += 5;
25952
25953         if(this.resizer){
25954             this.resizer.proxy.setStyle('z-index', ++index);
25955         }
25956
25957         this.lastZIndex = index;
25958     },
25959
25960     
25961     alignTo : function(element, position, offsets){
25962         var xy = this.el.getAlignToXY(element, position, offsets);
25963         this.setPagePosition(xy[0], xy[1]);
25964         return this;
25965     },
25966
25967     
25968     anchorTo : function(el, alignment, offsets, monitorScroll){
25969         this.clearAnchor();
25970         this.anchorTarget = {
25971             el: el,
25972             alignment: alignment,
25973             offsets: offsets
25974         };
25975
25976         Ext.EventManager.onWindowResize(this.doAnchor, this);
25977         var tm = typeof monitorScroll;
25978         if(tm != 'undefined'){
25979             Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
25980                 {buffer: tm == 'number' ? monitorScroll : 50});
25981         }
25982         return this.doAnchor();
25983     },
25984
25985     
25986     doAnchor : function(){
25987         var o = this.anchorTarget;
25988         this.alignTo(o.el, o.alignment, o.offsets);
25989         return this;
25990     },
25991
25992     
25993     clearAnchor : function(){
25994         if(this.anchorTarget){
25995             Ext.EventManager.removeResizeListener(this.doAnchor, this);
25996             Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
25997             delete this.anchorTarget;
25998         }
25999         return this;
26000     },
26001
26002     
26003     toFront : function(e){
26004         if(this.manager.bringToFront(this)){
26005             if(!e || !e.getTarget().focus){
26006                 this.focus();
26007             }
26008         }
26009         return this;
26010     },
26011
26012     
26013     setActive : function(active){
26014         if(active){
26015             if(!this.maximized){
26016                 this.el.enableShadow(true);
26017             }
26018             this.fireEvent('activate', this);
26019         }else{
26020             this.el.disableShadow();
26021             this.fireEvent('deactivate', this);
26022         }
26023     },
26024
26025     
26026     toBack : function(){
26027         this.manager.sendToBack(this);
26028         return this;
26029     },
26030
26031     
26032     center : function(){
26033         var xy = this.el.getAlignToXY(this.container, 'c-c');
26034         this.setPagePosition(xy[0], xy[1]);
26035         return this;
26036     }
26037
26038     
26039 });
26040 Ext.reg('window', Ext.Window);
26041
26042
26043 Ext.Window.DD = function(win){
26044     this.win = win;
26045     Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
26046     this.setHandleElId(win.header.id);
26047     this.scroll = false;
26048 };
26049
26050 Ext.extend(Ext.Window.DD, Ext.dd.DD, {
26051     moveOnly:true,
26052     headerOffsets:[100, 25],
26053     startDrag : function(){
26054         var w = this.win;
26055         this.proxy = w.ghost();
26056         if(w.constrain !== false){
26057             var so = w.el.shadowOffset;
26058             this.constrainTo(w.container, {right: so, left: so, bottom: so});
26059         }else if(w.constrainHeader !== false){
26060             var s = this.proxy.getSize();
26061             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
26062         }
26063     },
26064     b4Drag : Ext.emptyFn,
26065
26066     onDrag : function(e){
26067         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
26068     },
26069
26070     endDrag : function(e){
26071         this.win.unghost();
26072         this.win.saveState();
26073     }
26074 });
26075
26076 Ext.WindowGroup = function(){
26077     var list = {};
26078     var accessList = [];
26079     var front = null;
26080
26081     
26082     var sortWindows = function(d1, d2){
26083         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
26084     };
26085
26086     
26087     var orderWindows = function(){
26088         var a = accessList, len = a.length;
26089         if(len > 0){
26090             a.sort(sortWindows);
26091             var seed = a[0].manager.zseed;
26092             for(var i = 0; i < len; i++){
26093                 var win = a[i];
26094                 if(win && !win.hidden){
26095                     win.setZIndex(seed + (i*10));
26096                 }
26097             }
26098         }
26099         activateLast();
26100     };
26101
26102     
26103     var setActiveWin = function(win){
26104         if(win != front){
26105             if(front){
26106                 front.setActive(false);
26107             }
26108             front = win;
26109             if(win){
26110                 win.setActive(true);
26111             }
26112         }
26113     };
26114
26115     
26116     var activateLast = function(){
26117         for(var i = accessList.length-1; i >=0; --i) {
26118             if(!accessList[i].hidden){
26119                 setActiveWin(accessList[i]);
26120                 return;
26121             }
26122         }
26123         
26124         setActiveWin(null);
26125     };
26126
26127     return {
26128         
26129         zseed : 9000,
26130
26131         
26132         register : function(win){
26133             if(win.manager){
26134                 win.manager.unregister(win);
26135             }
26136             win.manager = this;
26137
26138             list[win.id] = win;
26139             accessList.push(win);
26140             win.on('hide', activateLast);
26141         },
26142
26143         
26144         unregister : function(win){
26145             delete win.manager;
26146             delete list[win.id];
26147             win.un('hide', activateLast);
26148             accessList.remove(win);
26149         },
26150
26151         
26152         get : function(id){
26153             return typeof id == "object" ? id : list[id];
26154         },
26155
26156         
26157         bringToFront : function(win){
26158             win = this.get(win);
26159             if(win != front){
26160                 win._lastAccess = new Date().getTime();
26161                 orderWindows();
26162                 return true;
26163             }
26164             return false;
26165         },
26166
26167         
26168         sendToBack : function(win){
26169             win = this.get(win);
26170             win._lastAccess = -(new Date().getTime());
26171             orderWindows();
26172             return win;
26173         },
26174
26175         
26176         hideAll : function(){
26177             for(var id in list){
26178                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
26179                     list[id].hide();
26180                 }
26181             }
26182         },
26183
26184         
26185         getActive : function(){
26186             return front;
26187         },
26188
26189         
26190         getBy : function(fn, scope){
26191             var r = [];
26192             for(var i = accessList.length-1; i >=0; --i) {
26193                 var win = accessList[i];
26194                 if(fn.call(scope||win, win) !== false){
26195                     r.push(win);
26196                 }
26197             }
26198             return r;
26199         },
26200
26201         
26202         each : function(fn, scope){
26203             for(var id in list){
26204                 if(list[id] && typeof list[id] != "function"){
26205                     if(fn.call(scope || list[id], list[id]) === false){
26206                         return;
26207                     }
26208                 }
26209             }
26210         }
26211     };
26212 };
26213
26214
26215
26216 Ext.WindowMgr = new Ext.WindowGroup();
26217 Ext.MessageBox = function(){
26218     var dlg, opt, mask, waitTimer,
26219         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
26220         buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
26221         buttonNames = ['ok', 'yes', 'no', 'cancel'];
26222
26223     
26224     var handleButton = function(button){
26225         buttons[button].blur();
26226         if(dlg.isVisible()){
26227             dlg.hide();
26228             handleHide();
26229             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
26230         }
26231     };
26232
26233     
26234     var handleHide = function(){
26235         if(opt && opt.cls){
26236             dlg.el.removeClass(opt.cls);
26237         }
26238         progressBar.reset();        
26239     };
26240
26241     
26242     var handleEsc = function(d, k, e){
26243         if(opt && opt.closable !== false){
26244             dlg.hide();
26245             handleHide();
26246         }
26247         if(e){
26248             e.stopEvent();
26249         }
26250     };
26251
26252     
26253     var updateButtons = function(b){
26254         var width = 0,
26255             cfg;
26256         if(!b){
26257             Ext.each(buttonNames, function(name){
26258                 buttons[name].hide();
26259             });
26260             return width;
26261         }
26262         dlg.footer.dom.style.display = '';
26263         Ext.iterate(buttons, function(name, btn){
26264             cfg = b[name];
26265             if(cfg){
26266                 btn.show();
26267                 btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
26268                 width += btn.getEl().getWidth() + 15;
26269             }else{
26270                 btn.hide();
26271             }
26272         });
26273         return width;
26274     };
26275
26276     return {
26277         
26278         getDialog : function(titleText){
26279            if(!dlg){
26280                 var btns = [];
26281                 
26282                 buttons = {};
26283                 Ext.each(buttonNames, function(name){
26284                     btns.push(buttons[name] = new Ext.Button({
26285                         text: this.buttonText[name],
26286                         handler: handleButton.createCallback(name),
26287                         hideMode: 'offsets'
26288                     }));
26289                 }, this);
26290                 dlg = new Ext.Window({
26291                     autoCreate : true,
26292                     title:titleText,
26293                     resizable:false,
26294                     constrain:true,
26295                     constrainHeader:true,
26296                     minimizable : false,
26297                     maximizable : false,
26298                     stateful: false,
26299                     modal: true,
26300                     shim:true,
26301                     buttonAlign:"center",
26302                     width:400,
26303                     height:100,
26304                     minHeight: 80,
26305                     plain:true,
26306                     footer:true,
26307                     closable:true,
26308                     close : function(){
26309                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
26310                             handleButton("no");
26311                         }else{
26312                             handleButton("cancel");
26313                         }
26314                     },
26315                     fbar: new Ext.Toolbar({
26316                         items: btns,
26317                         enableOverflow: false
26318                     })
26319                 });
26320                 dlg.render(document.body);
26321                 dlg.getEl().addClass('x-window-dlg');
26322                 mask = dlg.mask;
26323                 bodyEl = dlg.body.createChild({
26324                     html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
26325                 });
26326                 iconEl = Ext.get(bodyEl.dom.firstChild);
26327                 var contentEl = bodyEl.dom.childNodes[1];
26328                 msgEl = Ext.get(contentEl.firstChild);
26329                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
26330                 textboxEl.enableDisplayMode();
26331                 textboxEl.addKeyListener([10,13], function(){
26332                     if(dlg.isVisible() && opt && opt.buttons){
26333                         if(opt.buttons.ok){
26334                             handleButton("ok");
26335                         }else if(opt.buttons.yes){
26336                             handleButton("yes");
26337                         }
26338                     }
26339                 });
26340                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
26341                 textareaEl.enableDisplayMode();
26342                 progressBar = new Ext.ProgressBar({
26343                     renderTo:bodyEl
26344                 });
26345                bodyEl.createChild({cls:'x-clear'});
26346             }
26347             return dlg;
26348         },
26349
26350         
26351         updateText : function(text){
26352             if(!dlg.isVisible() && !opt.width){
26353                 dlg.setSize(this.maxWidth, 100); 
26354             }
26355             msgEl.update(text || '&#160;');
26356
26357             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
26358                 mw = msgEl.getWidth() + msgEl.getMargins('lr'),
26359                 fw = dlg.getFrameWidth('lr'),
26360                 bw = dlg.body.getFrameWidth('lr'),
26361                 w;
26362                 
26363             if (Ext.isIE && iw > 0){
26364                 
26365                 
26366                 iw += 3;
26367             }
26368             w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
26369                     Math.max(opt.minWidth || this.minWidth, bwidth || 0));
26370
26371             if(opt.prompt === true){
26372                 activeTextEl.setWidth(w-iw-fw-bw);
26373             }
26374             if(opt.progress === true || opt.wait === true){
26375                 progressBar.setSize(w-iw-fw-bw);
26376             }
26377             if(Ext.isIE && w == bwidth){
26378                 w += 4; 
26379             }
26380             dlg.setSize(w, 'auto').center();
26381             return this;
26382         },
26383
26384         
26385         updateProgress : function(value, progressText, msg){
26386             progressBar.updateProgress(value, progressText);
26387             if(msg){
26388                 this.updateText(msg);
26389             }
26390             return this;
26391         },
26392
26393         
26394         isVisible : function(){
26395             return dlg && dlg.isVisible();
26396         },
26397
26398         
26399         hide : function(){
26400             var proxy = dlg ? dlg.activeGhost : null;
26401             if(this.isVisible() || proxy){
26402                 dlg.hide();
26403                 handleHide();
26404                 if (proxy){
26405                     
26406                     
26407                     dlg.unghost(false, false);
26408                 } 
26409             }
26410             return this;
26411         },
26412
26413         
26414         show : function(options){
26415             if(this.isVisible()){
26416                 this.hide();
26417             }
26418             opt = options;
26419             var d = this.getDialog(opt.title || "&#160;");
26420
26421             d.setTitle(opt.title || "&#160;");
26422             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
26423             d.tools.close.setDisplayed(allowClose);
26424             activeTextEl = textboxEl;
26425             opt.prompt = opt.prompt || (opt.multiline ? true : false);
26426             if(opt.prompt){
26427                 if(opt.multiline){
26428                     textboxEl.hide();
26429                     textareaEl.show();
26430                     textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
26431                     activeTextEl = textareaEl;
26432                 }else{
26433                     textboxEl.show();
26434                     textareaEl.hide();
26435                 }
26436             }else{
26437                 textboxEl.hide();
26438                 textareaEl.hide();
26439             }
26440             activeTextEl.dom.value = opt.value || "";
26441             if(opt.prompt){
26442                 d.focusEl = activeTextEl;
26443             }else{
26444                 var bs = opt.buttons;
26445                 var db = null;
26446                 if(bs && bs.ok){
26447                     db = buttons["ok"];
26448                 }else if(bs && bs.yes){
26449                     db = buttons["yes"];
26450                 }
26451                 if (db){
26452                     d.focusEl = db;
26453                 }
26454             }
26455             if(opt.iconCls){
26456               d.setIconClass(opt.iconCls);
26457             }
26458             this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
26459             bwidth = updateButtons(opt.buttons);
26460             progressBar.setVisible(opt.progress === true || opt.wait === true);
26461             this.updateProgress(0, opt.progressText);
26462             this.updateText(opt.msg);
26463             if(opt.cls){
26464                 d.el.addClass(opt.cls);
26465             }
26466             d.proxyDrag = opt.proxyDrag === true;
26467             d.modal = opt.modal !== false;
26468             d.mask = opt.modal !== false ? mask : false;
26469             if(!d.isVisible()){
26470                 
26471                 document.body.appendChild(dlg.el.dom);
26472                 d.setAnimateTarget(opt.animEl);
26473                 
26474                 d.on('show', function(){
26475                     if(allowClose === true){
26476                         d.keyMap.enable();
26477                     }else{
26478                         d.keyMap.disable();
26479                     }
26480                 }, this, {single:true});
26481                 d.show(opt.animEl);
26482             }
26483             if(opt.wait === true){
26484                 progressBar.wait(opt.waitConfig);
26485             }
26486             return this;
26487         },
26488
26489         
26490         setIcon : function(icon){
26491             if(!dlg){
26492                 bufferIcon = icon;
26493                 return;
26494             }
26495             bufferIcon = undefined;
26496             if(icon && icon != ''){
26497                 iconEl.removeClass('x-hidden');
26498                 iconEl.replaceClass(iconCls, icon);
26499                 bodyEl.addClass('x-dlg-icon');
26500                 iconCls = icon;
26501             }else{
26502                 iconEl.replaceClass(iconCls, 'x-hidden');
26503                 bodyEl.removeClass('x-dlg-icon');
26504                 iconCls = '';
26505             }
26506             return this;
26507         },
26508
26509         
26510         progress : function(title, msg, progressText){
26511             this.show({
26512                 title : title,
26513                 msg : msg,
26514                 buttons: false,
26515                 progress:true,
26516                 closable:false,
26517                 minWidth: this.minProgressWidth,
26518                 progressText: progressText
26519             });
26520             return this;
26521         },
26522
26523         
26524         wait : function(msg, title, config){
26525             this.show({
26526                 title : title,
26527                 msg : msg,
26528                 buttons: false,
26529                 closable:false,
26530                 wait:true,
26531                 modal:true,
26532                 minWidth: this.minProgressWidth,
26533                 waitConfig: config
26534             });
26535             return this;
26536         },
26537
26538         
26539         alert : function(title, msg, fn, scope){
26540             this.show({
26541                 title : title,
26542                 msg : msg,
26543                 buttons: this.OK,
26544                 fn: fn,
26545                 scope : scope,
26546                 minWidth: this.minWidth
26547             });
26548             return this;
26549         },
26550
26551         
26552         confirm : function(title, msg, fn, scope){
26553             this.show({
26554                 title : title,
26555                 msg : msg,
26556                 buttons: this.YESNO,
26557                 fn: fn,
26558                 scope : scope,
26559                 icon: this.QUESTION,
26560                 minWidth: this.minWidth
26561             });
26562             return this;
26563         },
26564
26565         
26566         prompt : function(title, msg, fn, scope, multiline, value){
26567             this.show({
26568                 title : title,
26569                 msg : msg,
26570                 buttons: this.OKCANCEL,
26571                 fn: fn,
26572                 minWidth: this.minPromptWidth,
26573                 scope : scope,
26574                 prompt:true,
26575                 multiline: multiline,
26576                 value: value
26577             });
26578             return this;
26579         },
26580
26581         
26582         OK : {ok:true},
26583         
26584         CANCEL : {cancel:true},
26585         
26586         OKCANCEL : {ok:true, cancel:true},
26587         
26588         YESNO : {yes:true, no:true},
26589         
26590         YESNOCANCEL : {yes:true, no:true, cancel:true},
26591         
26592         INFO : 'ext-mb-info',
26593         
26594         WARNING : 'ext-mb-warning',
26595         
26596         QUESTION : 'ext-mb-question',
26597         
26598         ERROR : 'ext-mb-error',
26599
26600         
26601         defaultTextHeight : 75,
26602         
26603         maxWidth : 600,
26604         
26605         minWidth : 100,
26606         
26607         minProgressWidth : 250,
26608         
26609         minPromptWidth: 250,
26610         
26611         buttonText : {
26612             ok : "OK",
26613             cancel : "Cancel",
26614             yes : "Yes",
26615             no : "No"
26616         }
26617     };
26618 }();
26619
26620
26621 Ext.Msg = Ext.MessageBox;
26622 Ext.dd.PanelProxy = function(panel, config){
26623     this.panel = panel;
26624     this.id = this.panel.id +'-ddproxy';
26625     Ext.apply(this, config);
26626 };
26627
26628 Ext.dd.PanelProxy.prototype = {
26629     
26630     insertProxy : true,
26631
26632     
26633     setStatus : Ext.emptyFn,
26634     reset : Ext.emptyFn,
26635     update : Ext.emptyFn,
26636     stop : Ext.emptyFn,
26637     sync: Ext.emptyFn,
26638
26639     
26640     getEl : function(){
26641         return this.ghost;
26642     },
26643
26644     
26645     getGhost : function(){
26646         return this.ghost;
26647     },
26648
26649     
26650     getProxy : function(){
26651         return this.proxy;
26652     },
26653
26654     
26655     hide : function(){
26656         if(this.ghost){
26657             if(this.proxy){
26658                 this.proxy.remove();
26659                 delete this.proxy;
26660             }
26661             this.panel.el.dom.style.display = '';
26662             this.ghost.remove();
26663             delete this.ghost;
26664         }
26665     },
26666
26667     
26668     show : function(){
26669         if(!this.ghost){
26670             this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
26671             this.ghost.setXY(this.panel.el.getXY());
26672             if(this.insertProxy){
26673                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
26674                 this.proxy.setSize(this.panel.getSize());
26675             }
26676             this.panel.el.dom.style.display = 'none';
26677         }
26678     },
26679
26680     
26681     repair : function(xy, callback, scope){
26682         this.hide();
26683         if(typeof callback == "function"){
26684             callback.call(scope || this);
26685         }
26686     },
26687
26688     
26689     moveProxy : function(parentNode, before){
26690         if(this.proxy){
26691             parentNode.insertBefore(this.proxy.dom, before);
26692         }
26693     }
26694 };
26695
26696
26697 Ext.Panel.DD = function(panel, cfg){
26698     this.panel = panel;
26699     this.dragData = {panel: panel};
26700     this.proxy = new Ext.dd.PanelProxy(panel, cfg);
26701     Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
26702     var h = panel.header;
26703     if(h){
26704         this.setHandleElId(h.id);
26705     }
26706     (h ? h : this.panel.body).setStyle('cursor', 'move');
26707     this.scroll = false;
26708 };
26709
26710 Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
26711     showFrame: Ext.emptyFn,
26712     startDrag: Ext.emptyFn,
26713     b4StartDrag: function(x, y) {
26714         this.proxy.show();
26715     },
26716     b4MouseDown: function(e) {
26717         var x = e.getPageX();
26718         var y = e.getPageY();
26719         this.autoOffset(x, y);
26720     },
26721     onInitDrag : function(x, y){
26722         this.onStartDrag(x, y);
26723         return true;
26724     },
26725     createFrame : Ext.emptyFn,
26726     getDragEl : function(e){
26727         return this.proxy.ghost.dom;
26728     },
26729     endDrag : function(e){
26730         this.proxy.hide();
26731         this.panel.saveState();
26732     },
26733
26734     autoOffset : function(x, y) {
26735         x -= this.startPageX;
26736         y -= this.startPageY;
26737         this.setDelta(x, y);
26738     }
26739 });
26740 Ext.state.Provider = function(){
26741     
26742     this.addEvents("statechange");
26743     this.state = {};
26744     Ext.state.Provider.superclass.constructor.call(this);
26745 };
26746 Ext.extend(Ext.state.Provider, Ext.util.Observable, {
26747     
26748     get : function(name, defaultValue){
26749         return typeof this.state[name] == "undefined" ?
26750             defaultValue : this.state[name];
26751     },
26752
26753     
26754     clear : function(name){
26755         delete this.state[name];
26756         this.fireEvent("statechange", this, name, null);
26757     },
26758
26759     
26760     set : function(name, value){
26761         this.state[name] = value;
26762         this.fireEvent("statechange", this, name, value);
26763     },
26764
26765     
26766     decodeValue : function(cookie){
26767         var re = /^(a|n|d|b|s|o)\:(.*)$/;
26768         var matches = re.exec(unescape(cookie));
26769         if(!matches || !matches[1]) return; 
26770         var type = matches[1];
26771         var v = matches[2];
26772         switch(type){
26773             case "n":
26774                 return parseFloat(v);
26775             case "d":
26776                 return new Date(Date.parse(v));
26777             case "b":
26778                 return (v == "1");
26779             case "a":
26780                 var all = [];
26781                 if(v != ''){
26782                     Ext.each(v.split('^'), function(val){
26783                         all.push(this.decodeValue(val));
26784                     }, this);
26785                 }
26786                 return all;
26787            case "o":
26788                 var all = {};
26789                 if(v != ''){
26790                     Ext.each(v.split('^'), function(val){
26791                         var kv = val.split('=');
26792                         all[kv[0]] = this.decodeValue(kv[1]);
26793                     }, this);
26794                 }
26795                 return all;
26796            default:
26797                 return v;
26798         }
26799     },
26800
26801     
26802     encodeValue : function(v){
26803         var enc;
26804         if(typeof v == "number"){
26805             enc = "n:" + v;
26806         }else if(typeof v == "boolean"){
26807             enc = "b:" + (v ? "1" : "0");
26808         }else if(Ext.isDate(v)){
26809             enc = "d:" + v.toGMTString();
26810         }else if(Ext.isArray(v)){
26811             var flat = "";
26812             for(var i = 0, len = v.length; i < len; i++){
26813                 flat += this.encodeValue(v[i]);
26814                 if(i != len-1) flat += "^";
26815             }
26816             enc = "a:" + flat;
26817         }else if(typeof v == "object"){
26818             var flat = "";
26819             for(var key in v){
26820                 if(typeof v[key] != "function" && v[key] !== undefined){
26821                     flat += key + "=" + this.encodeValue(v[key]) + "^";
26822                 }
26823             }
26824             enc = "o:" + flat.substring(0, flat.length-1);
26825         }else{
26826             enc = "s:" + v;
26827         }
26828         return escape(enc);
26829     }
26830 });
26831
26832 Ext.state.Manager = function(){
26833     var provider = new Ext.state.Provider();
26834
26835     return {
26836         
26837         setProvider : function(stateProvider){
26838             provider = stateProvider;
26839         },
26840
26841         
26842         get : function(key, defaultValue){
26843             return provider.get(key, defaultValue);
26844         },
26845
26846         
26847          set : function(key, value){
26848             provider.set(key, value);
26849         },
26850
26851         
26852         clear : function(key){
26853             provider.clear(key);
26854         },
26855
26856         
26857         getProvider : function(){
26858             return provider;
26859         }
26860     };
26861 }();
26862
26863 Ext.state.CookieProvider = function(config){
26864     Ext.state.CookieProvider.superclass.constructor.call(this);
26865     this.path = "/";
26866     this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
26867     this.domain = null;
26868     this.secure = false;
26869     Ext.apply(this, config);
26870     this.state = this.readCookies();
26871 };
26872
26873 Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {
26874     
26875     set : function(name, value){
26876         if(typeof value == "undefined" || value === null){
26877             this.clear(name);
26878             return;
26879         }
26880         this.setCookie(name, value);
26881         Ext.state.CookieProvider.superclass.set.call(this, name, value);
26882     },
26883
26884     
26885     clear : function(name){
26886         this.clearCookie(name);
26887         Ext.state.CookieProvider.superclass.clear.call(this, name);
26888     },
26889
26890     
26891     readCookies : function(){
26892         var cookies = {};
26893         var c = document.cookie + ";";
26894         var re = /\s?(.*?)=(.*?);/g;
26895         var matches;
26896         while((matches = re.exec(c)) != null){
26897             var name = matches[1];
26898             var value = matches[2];
26899             if(name && name.substring(0,3) == "ys-"){
26900                 cookies[name.substr(3)] = this.decodeValue(value);
26901             }
26902         }
26903         return cookies;
26904     },
26905
26906     
26907     setCookie : function(name, value){
26908         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
26909            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
26910            ((this.path == null) ? "" : ("; path=" + this.path)) +
26911            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
26912            ((this.secure == true) ? "; secure" : "");
26913     },
26914
26915     
26916     clearCookie : function(name){
26917         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
26918            ((this.path == null) ? "" : ("; path=" + this.path)) +
26919            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
26920            ((this.secure == true) ? "; secure" : "");
26921     }
26922 });
26923 Ext.DataView = Ext.extend(Ext.BoxComponent, {
26924     
26925     
26926     
26927     
26928     
26929     
26930     
26931     
26932     
26933     selectedClass : "x-view-selected",
26934     
26935     emptyText : "",
26936
26937     
26938     deferEmptyText: true,
26939     
26940     trackOver: false,
26941     
26942     
26943     blockRefresh: false,
26944
26945     
26946     last: false,
26947
26948     
26949     initComponent : function(){
26950         Ext.DataView.superclass.initComponent.call(this);
26951         if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
26952             this.tpl = new Ext.XTemplate(this.tpl);
26953         }
26954
26955         this.addEvents(
26956             
26957             "beforeclick",
26958             
26959             "click",
26960             
26961             "mouseenter",
26962             
26963             "mouseleave",
26964             
26965             "containerclick",
26966             
26967             "dblclick",
26968             
26969             "contextmenu",
26970             
26971             "containercontextmenu",
26972             
26973             "selectionchange",
26974
26975             
26976             "beforeselect"
26977         );
26978
26979         this.store = Ext.StoreMgr.lookup(this.store);
26980         this.all = new Ext.CompositeElementLite();
26981         this.selected = new Ext.CompositeElementLite();
26982     },
26983
26984     
26985     afterRender : function(){
26986         Ext.DataView.superclass.afterRender.call(this);
26987
26988                 this.mon(this.getTemplateTarget(), {
26989             "click": this.onClick,
26990             "dblclick": this.onDblClick,
26991             "contextmenu": this.onContextMenu,
26992             scope:this
26993         });
26994
26995         if(this.overClass || this.trackOver){
26996             this.mon(this.getTemplateTarget(), {
26997                 "mouseover": this.onMouseOver,
26998                 "mouseout": this.onMouseOut,
26999                 scope:this
27000             });
27001         }
27002
27003         if(this.store){
27004             this.bindStore(this.store, true);
27005         }
27006     },
27007
27008     
27009     refresh : function() {
27010         this.clearSelections(false, true);
27011         var el = this.getTemplateTarget();
27012         el.update("");
27013         var records = this.store.getRange();
27014         if(records.length < 1){
27015             if(!this.deferEmptyText || this.hasSkippedEmptyText){
27016                 el.update(this.emptyText);
27017             }
27018             this.all.clear();
27019         }else{
27020             this.tpl.overwrite(el, this.collectData(records, 0));
27021             this.all.fill(Ext.query(this.itemSelector, el.dom));
27022             this.updateIndexes(0);
27023         }
27024         this.hasSkippedEmptyText = true;
27025     },
27026
27027     getTemplateTarget: function(){
27028         return this.el;
27029     },
27030
27031     
27032     prepareData : function(data){
27033         return data;
27034     },
27035
27036     
27037     collectData : function(records, startIndex){
27038         var r = [];
27039         for(var i = 0, len = records.length; i < len; i++){
27040             r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
27041         }
27042         return r;
27043     },
27044
27045     
27046     bufferRender : function(records){
27047         var div = document.createElement('div');
27048         this.tpl.overwrite(div, this.collectData(records));
27049         return Ext.query(this.itemSelector, div);
27050     },
27051
27052     
27053     onUpdate : function(ds, record){
27054         var index = this.store.indexOf(record);
27055         if(index > -1){
27056             var sel = this.isSelected(index);
27057             var original = this.all.elements[index];
27058             var node = this.bufferRender([record], index)[0];
27059
27060             this.all.replaceElement(index, node, true);
27061             if(sel){
27062                 this.selected.replaceElement(original, node);
27063                 this.all.item(index).addClass(this.selectedClass);
27064             }
27065             this.updateIndexes(index, index);
27066         }
27067     },
27068
27069     
27070     onAdd : function(ds, records, index){
27071         if(this.all.getCount() === 0){
27072             this.refresh();
27073             return;
27074         }
27075         var nodes = this.bufferRender(records, index), n, a = this.all.elements;
27076         if(index < this.all.getCount()){
27077             n = this.all.item(index).insertSibling(nodes, 'before', true);
27078             a.splice.apply(a, [index, 0].concat(nodes));
27079         }else{
27080             n = this.all.last().insertSibling(nodes, 'after', true);
27081             a.push.apply(a, nodes);
27082         }
27083         this.updateIndexes(index);
27084     },
27085
27086     
27087     onRemove : function(ds, record, index){
27088         this.deselect(index);
27089         this.all.removeElement(index, true);
27090         this.updateIndexes(index);
27091         if (this.store.getCount() === 0){
27092             this.refresh();
27093         }
27094     },
27095
27096     
27097     refreshNode : function(index){
27098         this.onUpdate(this.store, this.store.getAt(index));
27099     },
27100
27101     
27102     updateIndexes : function(startIndex, endIndex){
27103         var ns = this.all.elements;
27104         startIndex = startIndex || 0;
27105         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
27106         for(var i = startIndex; i <= endIndex; i++){
27107             ns[i].viewIndex = i;
27108         }
27109     },
27110     
27111     
27112     getStore : function(){
27113         return this.store;
27114     },
27115
27116     
27117     bindStore : function(store, initial){
27118         if(!initial && this.store){
27119             if(store !== this.store && this.store.autoDestroy){
27120                 this.store.destroy();
27121             }else{
27122                 this.store.un("beforeload", this.onBeforeLoad, this);
27123                 this.store.un("datachanged", this.onDataChanged, this);
27124                 this.store.un("add", this.onAdd, this);
27125                 this.store.un("remove", this.onRemove, this);
27126                 this.store.un("update", this.onUpdate, this);
27127                 this.store.un("clear", this.refresh, this);
27128             }
27129             if(!store){
27130                 this.store = null;
27131             }
27132         }
27133         if(store){
27134             store = Ext.StoreMgr.lookup(store);
27135             store.on({
27136                 scope: this,
27137                 beforeload: this.onBeforeLoad,
27138                 datachanged: this.onDataChanged,
27139                 add: this.onAdd,
27140                 remove: this.onRemove,
27141                 update: this.onUpdate,
27142                 clear: this.refresh
27143             });
27144         }
27145         this.store = store;
27146         if(store){
27147             this.refresh();
27148         }
27149     },
27150     
27151     
27152     onDataChanged: function() {
27153         if (this.blockRefresh !== true) {
27154             this.refresh.apply(this, arguments);
27155         }
27156     },
27157
27158     
27159     findItemFromChild : function(node){
27160         return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
27161     },
27162
27163     
27164     onClick : function(e){
27165         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27166         if(item){
27167             var index = this.indexOf(item);
27168             if(this.onItemClick(item, index, e) !== false){
27169                 this.fireEvent("click", this, index, item, e);
27170             }
27171         }else{
27172             if(this.fireEvent("containerclick", this, e) !== false){
27173                 this.onContainerClick(e);
27174             }
27175         }
27176     },
27177
27178     onContainerClick : function(e){
27179         this.clearSelections();
27180     },
27181
27182     
27183     onContextMenu : function(e){
27184         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27185         if(item){
27186             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
27187         }else{
27188             this.fireEvent("containercontextmenu", this, e);
27189         }
27190     },
27191
27192     
27193     onDblClick : function(e){
27194         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27195         if(item){
27196             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
27197         }
27198     },
27199
27200     
27201     onMouseOver : function(e){
27202         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27203         if(item && item !== this.lastItem){
27204             this.lastItem = item;
27205             Ext.fly(item).addClass(this.overClass);
27206             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
27207         }
27208     },
27209
27210     
27211     onMouseOut : function(e){
27212         if(this.lastItem){
27213             if(!e.within(this.lastItem, true, true)){
27214                 Ext.fly(this.lastItem).removeClass(this.overClass);
27215                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
27216                 delete this.lastItem;
27217             }
27218         }
27219     },
27220
27221     
27222     onItemClick : function(item, index, e){
27223         if(this.fireEvent("beforeclick", this, index, item, e) === false){
27224             return false;
27225         }
27226         if(this.multiSelect){
27227             this.doMultiSelection(item, index, e);
27228             e.preventDefault();
27229         }else if(this.singleSelect){
27230             this.doSingleSelection(item, index, e);
27231             e.preventDefault();
27232         }
27233         return true;
27234     },
27235
27236     
27237     doSingleSelection : function(item, index, e){
27238         if(e.ctrlKey && this.isSelected(index)){
27239             this.deselect(index);
27240         }else{
27241             this.select(index, false);
27242         }
27243     },
27244
27245     
27246     doMultiSelection : function(item, index, e){
27247         if(e.shiftKey && this.last !== false){
27248             var last = this.last;
27249             this.selectRange(last, index, e.ctrlKey);
27250             this.last = last; 
27251         }else{
27252             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
27253                 this.deselect(index);
27254             }else{
27255                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
27256             }
27257         }
27258     },
27259
27260     
27261     getSelectionCount : function(){
27262         return this.selected.getCount();
27263     },
27264
27265     
27266     getSelectedNodes : function(){
27267         return this.selected.elements;
27268     },
27269
27270     
27271     getSelectedIndexes : function(){
27272         var indexes = [], s = this.selected.elements;
27273         for(var i = 0, len = s.length; i < len; i++){
27274             indexes.push(s[i].viewIndex);
27275         }
27276         return indexes;
27277     },
27278
27279     
27280     getSelectedRecords : function(){
27281         var r = [], s = this.selected.elements;
27282         for(var i = 0, len = s.length; i < len; i++){
27283             r[r.length] = this.store.getAt(s[i].viewIndex);
27284         }
27285         return r;
27286     },
27287
27288     
27289     getRecords : function(nodes){
27290         var r = [], s = nodes;
27291         for(var i = 0, len = s.length; i < len; i++){
27292             r[r.length] = this.store.getAt(s[i].viewIndex);
27293         }
27294         return r;
27295     },
27296
27297     
27298     getRecord : function(node){
27299         return this.store.getAt(node.viewIndex);
27300     },
27301
27302     
27303     clearSelections : function(suppressEvent, skipUpdate){
27304         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
27305             if(!skipUpdate){
27306                 this.selected.removeClass(this.selectedClass);
27307             }
27308             this.selected.clear();
27309             this.last = false;
27310             if(!suppressEvent){
27311                 this.fireEvent("selectionchange", this, this.selected.elements);
27312             }
27313         }
27314     },
27315
27316     
27317     isSelected : function(node){
27318         return this.selected.contains(this.getNode(node));
27319     },
27320
27321     
27322     deselect : function(node){
27323         if(this.isSelected(node)){
27324             node = this.getNode(node);
27325             this.selected.removeElement(node);
27326             if(this.last == node.viewIndex){
27327                 this.last = false;
27328             }
27329             Ext.fly(node).removeClass(this.selectedClass);
27330             this.fireEvent("selectionchange", this, this.selected.elements);
27331         }
27332     },
27333
27334     
27335     select : function(nodeInfo, keepExisting, suppressEvent){
27336         if(Ext.isArray(nodeInfo)){
27337             if(!keepExisting){
27338                 this.clearSelections(true);
27339             }
27340             for(var i = 0, len = nodeInfo.length; i < len; i++){
27341                 this.select(nodeInfo[i], true, true);
27342             }
27343             if(!suppressEvent){
27344                 this.fireEvent("selectionchange", this, this.selected.elements);
27345             }
27346         } else{
27347             var node = this.getNode(nodeInfo);
27348             if(!keepExisting){
27349                 this.clearSelections(true);
27350             }
27351             if(node && !this.isSelected(node)){
27352                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
27353                     Ext.fly(node).addClass(this.selectedClass);
27354                     this.selected.add(node);
27355                     this.last = node.viewIndex;
27356                     if(!suppressEvent){
27357                         this.fireEvent("selectionchange", this, this.selected.elements);
27358                     }
27359                 }
27360             }
27361         }
27362     },
27363
27364     
27365     selectRange : function(start, end, keepExisting){
27366         if(!keepExisting){
27367             this.clearSelections(true);
27368         }
27369         this.select(this.getNodes(start, end), true);
27370     },
27371
27372     
27373     getNode : function(nodeInfo){
27374         if(Ext.isString(nodeInfo)){
27375             return document.getElementById(nodeInfo);
27376         }else if(Ext.isNumber(nodeInfo)){
27377             return this.all.elements[nodeInfo];
27378         }else if(nodeInfo instanceof Ext.data.Record){
27379             var idx = this.store.indexOf(nodeInfo);
27380             return this.all.elements[idx];
27381         }
27382         return nodeInfo;
27383     },
27384
27385     
27386     getNodes : function(start, end){
27387         var ns = this.all.elements;
27388         start = start || 0;
27389         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
27390         var nodes = [], i;
27391         if(start <= end){
27392             for(i = start; i <= end && ns[i]; i++){
27393                 nodes.push(ns[i]);
27394             }
27395         } else{
27396             for(i = start; i >= end && ns[i]; i--){
27397                 nodes.push(ns[i]);
27398             }
27399         }
27400         return nodes;
27401     },
27402
27403     
27404     indexOf : function(node){
27405         node = this.getNode(node);
27406         if(Ext.isNumber(node.viewIndex)){
27407             return node.viewIndex;
27408         }
27409         return this.all.indexOf(node);
27410     },
27411
27412     
27413     onBeforeLoad : function(){
27414         if(this.loadingText){
27415             this.clearSelections(false, true);
27416             this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
27417             this.all.clear();
27418         }
27419     },
27420
27421     onDestroy : function(){
27422         this.all.clear();
27423         this.selected.clear();
27424         Ext.DataView.superclass.onDestroy.call(this);
27425         this.bindStore(null);
27426     }
27427 });
27428
27429
27430 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
27431
27432 Ext.reg('dataview', Ext.DataView);
27433
27434 Ext.list.ListView = Ext.extend(Ext.DataView, {
27435     
27436     
27437     
27438     itemSelector: 'dl',
27439     
27440     selectedClass:'x-list-selected',
27441     
27442     overClass:'x-list-over',
27443     
27444     
27445     scrollOffset : undefined,
27446     
27447     columnResize: true,
27448     
27449     
27450     columnSort: true,
27451     
27452
27453     
27454     maxWidth: Ext.isIE ? 99 : 100,
27455
27456     initComponent : function(){
27457         if(this.columnResize){
27458             this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
27459             this.colResizer.init(this);
27460         }
27461         if(this.columnSort){
27462             this.colSorter = new Ext.list.Sorter(this.columnSort);
27463             this.colSorter.init(this);
27464         }
27465         if(!this.internalTpl){
27466             this.internalTpl = new Ext.XTemplate(
27467                 '<div class="x-list-header"><div class="x-list-header-inner">',
27468                     '<tpl for="columns">',
27469                     '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
27470                         '{header}',
27471                     '</em></div>',
27472                     '</tpl>',
27473                     '<div class="x-clear"></div>',
27474                 '</div></div>',
27475                 '<div class="x-list-body"><div class="x-list-body-inner">',
27476                 '</div></div>'
27477             );
27478         }
27479         if(!this.tpl){
27480             this.tpl = new Ext.XTemplate(
27481                 '<tpl for="rows">',
27482                     '<dl>',
27483                         '<tpl for="parent.columns">',
27484                         '<dt style="width:{[values.width*100]}%;text-align:{align};">',
27485                         '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
27486                             '{[values.tpl.apply(parent)]}',
27487                         '</em></dt>',
27488                         '</tpl>',
27489                         '<div class="x-clear"></div>',
27490                     '</dl>',
27491                 '</tpl>'
27492             );
27493         };
27494
27495         var cs = this.columns,
27496             allocatedWidth = 0,
27497             colsWithWidth = 0,
27498             len = cs.length,
27499             columns = [];
27500
27501         for(var i = 0; i < len; i++){
27502             var c = cs[i];
27503             if(!c.isColumn) {
27504                 c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
27505                 c = Ext.create(c);
27506             }
27507             if(c.width) {
27508                 allocatedWidth += c.width*100;
27509                 colsWithWidth++;
27510             }
27511             columns.push(c);
27512         }
27513
27514         cs = this.columns = columns;
27515
27516         
27517         if(colsWithWidth < len){
27518             var remaining = len - colsWithWidth;
27519             if(allocatedWidth < this.maxWidth){
27520                 var perCol = ((this.maxWidth-allocatedWidth) / remaining)/100;
27521                 for(var j = 0; j < len; j++){
27522                     var c = cs[j];
27523                     if(!c.width){
27524                         c.width = perCol;
27525                     }
27526                 }
27527             }
27528         }
27529         Ext.list.ListView.superclass.initComponent.call(this);
27530     },
27531
27532     onRender : function(){
27533         this.autoEl = {
27534             cls: 'x-list-wrap'
27535         };
27536         Ext.list.ListView.superclass.onRender.apply(this, arguments);
27537
27538         this.internalTpl.overwrite(this.el, {columns: this.columns});
27539
27540         this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
27541         this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
27542
27543         if(this.hideHeaders){
27544             this.el.dom.firstChild.style.display = 'none';
27545         }
27546     },
27547
27548     getTemplateTarget : function(){
27549         return this.innerBody;
27550     },
27551
27552     
27553     collectData : function(){
27554         var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
27555         return {
27556             columns: this.columns,
27557             rows: rs
27558         }
27559     },
27560
27561     verifyInternalSize : function(){
27562         if(this.lastSize){
27563             this.onResize(this.lastSize.width, this.lastSize.height);
27564         }
27565     },
27566
27567     
27568     onResize : function(w, h){
27569         var bd = this.innerBody.dom;
27570         var hd = this.innerHd.dom;
27571         if(!bd){
27572             return;
27573         }
27574         var bdp = bd.parentNode;
27575         if(Ext.isNumber(w)){
27576             var sw = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
27577             if(this.reserveScrollOffset || ((bdp.offsetWidth - bdp.clientWidth) > 10)){
27578                 bd.style.width = sw + 'px';
27579                 hd.style.width = sw + 'px';
27580             }else{
27581                 bd.style.width = w + 'px';
27582                 hd.style.width = w + 'px';
27583                 setTimeout(function(){
27584                     if((bdp.offsetWidth - bdp.clientWidth) > 10){
27585                         bd.style.width = sw + 'px';
27586                         hd.style.width = sw + 'px';
27587                     }
27588                 }, 10);
27589             }
27590         }
27591         if(Ext.isNumber(h)){
27592             bdp.style.height = (h - hd.parentNode.offsetHeight) + 'px';
27593         }
27594     },
27595
27596     updateIndexes : function(){
27597         Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
27598         this.verifyInternalSize();
27599     },
27600
27601     findHeaderIndex : function(hd){
27602         hd = hd.dom || hd;
27603         var pn = hd.parentNode, cs = pn.parentNode.childNodes;
27604         for(var i = 0, c; c = cs[i]; i++){
27605             if(c == pn){
27606                 return i;
27607             }
27608         }
27609         return -1;
27610     },
27611
27612     setHdWidths : function(){
27613         var els = this.innerHd.dom.getElementsByTagName('div');
27614         for(var i = 0, cs = this.columns, len = cs.length; i < len; i++){
27615             els[i].style.width = (cs[i].width*100) + '%';
27616         }
27617     }
27618 });
27619
27620 Ext.reg('listview', Ext.list.ListView);
27621
27622
27623 Ext.ListView = Ext.list.ListView;
27624 Ext.list.Column = Ext.extend(Object, {
27625     
27626     isColumn: true,
27627     
27628             
27629     align: 'left',
27630         
27631     header: '',
27632     
27633         
27634     width: null,
27635
27636     
27637     cls: '',
27638     
27639     
27640
27641     
27642     
27643     constructor : function(c){
27644         if(!c.tpl){
27645             c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
27646         }
27647         else if(Ext.isString(c.tpl)){
27648             c.tpl = new Ext.XTemplate(c.tpl);
27649         }
27650         
27651         Ext.apply(this, c);
27652     }
27653 });
27654
27655 Ext.reg('lvcolumn', Ext.list.Column);
27656
27657
27658 Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
27659         
27660     format: '0,000.00',
27661     
27662     constructor : function(c) {
27663         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
27664         Ext.list.NumberColumn.superclass.constructor.call(this, c);
27665     }
27666 });
27667
27668 Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
27669
27670
27671 Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
27672     format: 'm/d/Y',
27673     constructor : function(c) {
27674         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
27675         Ext.list.DateColumn.superclass.constructor.call(this, c);
27676     }
27677 });
27678 Ext.reg('lvdatecolumn', Ext.list.DateColumn);
27679
27680
27681 Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
27682     
27683     trueText: 'true',
27684     
27685     falseText: 'false',
27686     
27687     undefinedText: '&#160;',
27688     
27689     constructor : function(c) {
27690         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
27691         
27692         var t = this.trueText, f = this.falseText, u = this.undefinedText;
27693         c.tpl.format = function(v){
27694             if(v === undefined){
27695                 return u;
27696             }
27697             if(!v || v === 'false'){
27698                 return f;
27699             }
27700             return t;
27701         };
27702         
27703         Ext.list.DateColumn.superclass.constructor.call(this, c);
27704     }
27705 });
27706
27707 Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
27708 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
27709     
27710     minPct: .05,
27711
27712     constructor: function(config){
27713         Ext.apply(this, config);
27714         Ext.list.ColumnResizer.superclass.constructor.call(this);
27715     },
27716     init : function(listView){
27717         this.view = listView;
27718         listView.on('render', this.initEvents, this);
27719     },
27720
27721     initEvents : function(view){
27722         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
27723         this.tracker = new Ext.dd.DragTracker({
27724             onBeforeStart: this.onBeforeStart.createDelegate(this),
27725             onStart: this.onStart.createDelegate(this),
27726             onDrag: this.onDrag.createDelegate(this),
27727             onEnd: this.onEnd.createDelegate(this),
27728             tolerance: 3,
27729             autoStart: 300
27730         });
27731         this.tracker.initEl(view.innerHd);
27732         view.on('beforedestroy', this.tracker.destroy, this.tracker);
27733     },
27734
27735     handleHdMove : function(e, t){
27736         var hw = 5,
27737             x = e.getPageX(),
27738             hd = e.getTarget('em', 3, true);
27739         if(hd){
27740             var r = hd.getRegion(),
27741                 ss = hd.dom.style,
27742                 pn = hd.dom.parentNode;
27743
27744             if(x - r.left <= hw && pn != pn.parentNode.firstChild){
27745                 this.activeHd = Ext.get(pn.previousSibling.firstChild);
27746                 ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
27747             } else if(r.right - x <= hw && pn != pn.parentNode.lastChild.previousSibling){
27748                 this.activeHd = hd;
27749                 ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
27750             } else{
27751                 delete this.activeHd;
27752                 ss.cursor = '';
27753             }
27754         }
27755     },
27756
27757     onBeforeStart : function(e){
27758         this.dragHd = this.activeHd;
27759         return !!this.dragHd;
27760     },
27761
27762     onStart: function(e){
27763         this.view.disableHeaders = true;
27764         this.proxy = this.view.el.createChild({cls:'x-list-resizer'});
27765         this.proxy.setHeight(this.view.el.getHeight());
27766
27767         var x = this.tracker.getXY()[0],
27768             w = this.view.innerHd.getWidth();
27769
27770         this.hdX = this.dragHd.getX();
27771         this.hdIndex = this.view.findHeaderIndex(this.dragHd);
27772
27773         this.proxy.setX(this.hdX);
27774         this.proxy.setWidth(x-this.hdX);
27775
27776         this.minWidth = w*this.minPct;
27777         this.maxWidth = w - (this.minWidth*(this.view.columns.length-1-this.hdIndex));
27778     },
27779
27780     onDrag: function(e){
27781         var cursorX = this.tracker.getXY()[0];
27782         this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
27783     },
27784
27785     onEnd: function(e){
27786         
27787         var nw = this.proxy.getWidth();
27788         this.proxy.remove();
27789
27790         var index = this.hdIndex,
27791             vw = this.view,
27792             cs = vw.columns,
27793             len = cs.length,
27794             w = this.view.innerHd.getWidth(),
27795             minPct = this.minPct * 100,
27796             pct = Math.ceil((nw * vw.maxWidth) / w),
27797             diff = (cs[index].width * 100) - pct,
27798             eachItem = Math.floor(diff / (len-1-index)),
27799             mod = diff - (eachItem * (len-1-index));
27800
27801         for(var i = index+1; i < len; i++){
27802             var cw = (cs[i].width * 100) + eachItem,
27803                 ncw = Math.max(minPct, cw);
27804             if(cw != ncw){
27805                 mod += cw - ncw;
27806             }
27807             cs[i].width = ncw / 100;
27808         }
27809         cs[index].width = pct / 100;
27810         cs[index+1].width += (mod / 100);
27811         delete this.dragHd;
27812         vw.setHdWidths();
27813         vw.refresh();
27814         setTimeout(function(){
27815             vw.disableHeaders = false;
27816         }, 100);
27817     }
27818 });
27819
27820
27821 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
27822 Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
27823     
27824     sortClasses : ["sort-asc", "sort-desc"],
27825
27826     constructor: function(config){
27827         Ext.apply(this, config);
27828         Ext.list.Sorter.superclass.constructor.call(this);
27829     },
27830
27831     init : function(listView){
27832         this.view = listView;
27833         listView.on('render', this.initEvents, this);
27834     },
27835
27836     initEvents : function(view){
27837         view.mon(view.innerHd, 'click', this.onHdClick, this);
27838         view.innerHd.setStyle('cursor', 'pointer');
27839         view.mon(view.store, 'datachanged', this.updateSortState, this);
27840         this.updateSortState.defer(10, this, [view.store]);
27841     },
27842
27843     updateSortState : function(store){
27844         var state = store.getSortState();
27845         if(!state){
27846             return;
27847         }
27848         this.sortState = state;
27849         var cs = this.view.columns, sortColumn = -1;
27850         for(var i = 0, len = cs.length; i < len; i++){
27851             if(cs[i].dataIndex == state.field){
27852                 sortColumn = i;
27853                 break;
27854             }
27855         }
27856         if(sortColumn != -1){
27857             var sortDir = state.direction;
27858             this.updateSortIcon(sortColumn, sortDir);
27859         }
27860     },
27861
27862     updateSortIcon : function(col, dir){
27863         var sc = this.sortClasses;
27864         var hds = this.view.innerHd.select('em').removeClass(sc);
27865         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
27866     },
27867
27868     onHdClick : function(e){
27869         var hd = e.getTarget('em', 3);
27870         if(hd && !this.view.disableHeaders){
27871             var index = this.view.findHeaderIndex(hd);
27872             this.view.store.sort(this.view.columns[index].dataIndex);
27873         }
27874     }
27875 });
27876
27877
27878 Ext.ListView.Sorter = Ext.list.Sorter;
27879 Ext.TabPanel = Ext.extend(Ext.Panel,  {
27880     
27881     
27882     
27883     deferredRender : true,
27884     
27885     tabWidth : 120,
27886     
27887     minTabWidth : 30,
27888     
27889     resizeTabs : false,
27890     
27891     enableTabScroll : false,
27892     
27893     scrollIncrement : 0,
27894     
27895     scrollRepeatInterval : 400,
27896     
27897     scrollDuration : 0.35,
27898     
27899     animScroll : true,
27900     
27901     tabPosition : 'top',
27902     
27903     baseCls : 'x-tab-panel',
27904     
27905     autoTabs : false,
27906     
27907     autoTabSelector : 'div.x-tab',
27908     
27909     activeTab : undefined,
27910     
27911     tabMargin : 2,
27912     
27913     plain : false,
27914     
27915     wheelIncrement : 20,
27916
27917     
27918     idDelimiter : '__',
27919
27920     
27921     itemCls : 'x-tab-item',
27922
27923     
27924     elements : 'body',
27925     headerAsText : false,
27926     frame : false,
27927     hideBorders :true,
27928
27929     
27930     initComponent : function(){
27931         this.frame = false;
27932         Ext.TabPanel.superclass.initComponent.call(this);
27933         this.addEvents(
27934             
27935             'beforetabchange',
27936             
27937             'tabchange',
27938             
27939             'contextmenu'
27940         );
27941         
27942         this.setLayout(new Ext.layout.CardLayout(Ext.apply({
27943             layoutOnCardChange: this.layoutOnTabChange,
27944             deferredRender: this.deferredRender
27945         }, this.layoutConfig)));
27946
27947         if(this.tabPosition == 'top'){
27948             this.elements += ',header';
27949             this.stripTarget = 'header';
27950         }else {
27951             this.elements += ',footer';
27952             this.stripTarget = 'footer';
27953         }
27954         if(!this.stack){
27955             this.stack = Ext.TabPanel.AccessStack();
27956         }
27957         this.initItems();
27958     },
27959
27960     
27961     onRender : function(ct, position){
27962         Ext.TabPanel.superclass.onRender.call(this, ct, position);
27963
27964         if(this.plain){
27965             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
27966             this[pos].addClass('x-tab-panel-'+pos+'-plain');
27967         }
27968
27969         var st = this[this.stripTarget];
27970
27971         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
27972             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
27973
27974         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
27975         st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
27976         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
27977
27978         
27979         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
27980         this.strip.createChild({cls:'x-clear'});
27981
27982         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
27983
27984         
27985         if(!this.itemTpl){
27986             var tt = new Ext.Template(
27987                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
27988                  '<a class="x-tab-right" href="#"><em class="x-tab-left">',
27989                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
27990                  '</em></a></li>'
27991             );
27992             tt.disableFormats = true;
27993             tt.compile();
27994             Ext.TabPanel.prototype.itemTpl = tt;
27995         }
27996
27997         this.items.each(this.initTab, this);
27998     },
27999
28000     
28001     afterRender : function(){
28002         Ext.TabPanel.superclass.afterRender.call(this);
28003         if(this.autoTabs){
28004             this.readTabs(false);
28005         }
28006         if(this.activeTab !== undefined){
28007             var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
28008             delete this.activeTab;
28009             this.setActiveTab(item);
28010         }
28011     },
28012
28013     
28014     initEvents : function(){
28015         Ext.TabPanel.superclass.initEvents.call(this);
28016         this.mon(this.strip, {
28017             scope: this,
28018             mousedown: this.onStripMouseDown,
28019             contextmenu: this.onStripContextMenu
28020         });
28021         if(this.enableTabScroll){
28022             this.mon(this.strip, 'mousewheel', this.onWheel, this);
28023         }
28024     },
28025
28026     
28027     findTargets : function(e){
28028         var item = null,
28029             itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
28030
28031         if(itemEl){
28032             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
28033             if(item.disabled){
28034                 return {
28035                     close : null,
28036                     item : null,
28037                     el : null
28038                 };
28039             }
28040         }
28041         return {
28042             close : e.getTarget('.x-tab-strip-close', this.strip),
28043             item : item,
28044             el : itemEl
28045         };
28046     },
28047
28048     
28049     onStripMouseDown : function(e){
28050         if(e.button !== 0){
28051             return;
28052         }
28053         e.preventDefault();
28054         var t = this.findTargets(e);
28055         if(t.close){
28056             if (t.item.fireEvent('beforeclose', t.item) !== false) {
28057                 t.item.fireEvent('close', t.item);
28058                 this.remove(t.item);
28059             }
28060             return;
28061         }
28062         if(t.item && t.item != this.activeTab){
28063             this.setActiveTab(t.item);
28064         }
28065     },
28066
28067     
28068     onStripContextMenu : function(e){
28069         e.preventDefault();
28070         var t = this.findTargets(e);
28071         if(t.item){
28072             this.fireEvent('contextmenu', this, t.item, e);
28073         }
28074     },
28075
28076     
28077     readTabs : function(removeExisting){
28078         if(removeExisting === true){
28079             this.items.each(function(item){
28080                 this.remove(item);
28081             }, this);
28082         }
28083         var tabs = this.el.query(this.autoTabSelector);
28084         for(var i = 0, len = tabs.length; i < len; i++){
28085             var tab = tabs[i],
28086                 title = tab.getAttribute('title');
28087             tab.removeAttribute('title');
28088             this.add({
28089                 title: title,
28090                 contentEl: tab
28091             });
28092         }
28093     },
28094
28095     
28096     initTab : function(item, index){
28097         var before = this.strip.dom.childNodes[index],
28098             p = this.getTemplateArgs(item),
28099             el = before ?
28100                  this.itemTpl.insertBefore(before, p) :
28101                  this.itemTpl.append(this.strip, p),
28102             cls = 'x-tab-strip-over',
28103             tabEl = Ext.get(el);
28104
28105         tabEl.hover(function(){
28106             if(!item.disabled){
28107                 tabEl.addClass(cls);
28108             }
28109         }, function(){
28110             tabEl.removeClass(cls);
28111         });
28112
28113         if(item.tabTip){
28114             tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
28115         }
28116         item.tabEl = el;
28117
28118         
28119         tabEl.select('a').on('click', function(e){
28120             if(!e.getPageX()){
28121                 this.onStripMouseDown(e);
28122             }
28123         }, this, {preventDefault: true});
28124
28125         item.on({
28126             scope: this,
28127             disable: this.onItemDisabled,
28128             enable: this.onItemEnabled,
28129             titlechange: this.onItemTitleChanged,
28130             iconchange: this.onItemIconChanged,
28131             beforeshow: this.onBeforeShowItem
28132         });
28133     },
28134
28135
28136
28137     
28138     getTemplateArgs : function(item) {
28139         var cls = item.closable ? 'x-tab-strip-closable' : '';
28140         if(item.disabled){
28141             cls += ' x-item-disabled';
28142         }
28143         if(item.iconCls){
28144             cls += ' x-tab-with-icon';
28145         }
28146         if(item.tabCls){
28147             cls += ' ' + item.tabCls;
28148         }
28149
28150         return {
28151             id: this.id + this.idDelimiter + item.getItemId(),
28152             text: item.title,
28153             cls: cls,
28154             iconCls: item.iconCls || ''
28155         };
28156     },
28157
28158     
28159     onAdd : function(c){
28160         Ext.TabPanel.superclass.onAdd.call(this, c);
28161         if(this.rendered){
28162             var items = this.items;
28163             this.initTab(c, items.indexOf(c));
28164             this.delegateUpdates();
28165         }
28166     },
28167
28168     
28169     onBeforeAdd : function(item){
28170         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
28171         if(existing){
28172             this.setActiveTab(item);
28173             return false;
28174         }
28175         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
28176         var es = item.elements;
28177         item.elements = es ? es.replace(',header', '') : es;
28178         item.border = (item.border === true);
28179     },
28180
28181     
28182     onRemove : function(c){
28183         var te = Ext.get(c.tabEl);
28184         
28185         if(te){
28186             te.select('a').removeAllListeners();
28187             Ext.destroy(te);
28188         }
28189         Ext.TabPanel.superclass.onRemove.call(this, c);
28190         this.stack.remove(c);
28191         delete c.tabEl;
28192         c.un('disable', this.onItemDisabled, this);
28193         c.un('enable', this.onItemEnabled, this);
28194         c.un('titlechange', this.onItemTitleChanged, this);
28195         c.un('iconchange', this.onItemIconChanged, this);
28196         c.un('beforeshow', this.onBeforeShowItem, this);
28197         if(c == this.activeTab){
28198             var next = this.stack.next();
28199             if(next){
28200                 this.setActiveTab(next);
28201             }else if(this.items.getCount() > 0){
28202                 this.setActiveTab(0);
28203             }else{
28204                 this.setActiveTab(null);
28205             }
28206         }
28207         if(!this.destroying){
28208             this.delegateUpdates();
28209         }
28210     },
28211
28212     
28213     onBeforeShowItem : function(item){
28214         if(item != this.activeTab){
28215             this.setActiveTab(item);
28216             return false;
28217         }
28218     },
28219
28220     
28221     onItemDisabled : function(item){
28222         var el = this.getTabEl(item);
28223         if(el){
28224             Ext.fly(el).addClass('x-item-disabled');
28225         }
28226         this.stack.remove(item);
28227     },
28228
28229     
28230     onItemEnabled : function(item){
28231         var el = this.getTabEl(item);
28232         if(el){
28233             Ext.fly(el).removeClass('x-item-disabled');
28234         }
28235     },
28236
28237     
28238     onItemTitleChanged : function(item){
28239         var el = this.getTabEl(item);
28240         if(el){
28241             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
28242         }
28243     },
28244
28245     
28246     onItemIconChanged : function(item, iconCls, oldCls){
28247         var el = this.getTabEl(item);
28248         if(el){
28249             el = Ext.get(el);
28250             el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
28251             el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
28252         }
28253     },
28254
28255     
28256     getTabEl : function(item){
28257         var c = this.getComponent(item);
28258         return c ? c.tabEl : null;
28259     },
28260
28261     
28262     onResize : function(){
28263         Ext.TabPanel.superclass.onResize.apply(this, arguments);
28264         this.delegateUpdates();
28265     },
28266
28267     
28268     beginUpdate : function(){
28269         this.suspendUpdates = true;
28270     },
28271
28272     
28273     endUpdate : function(){
28274         this.suspendUpdates = false;
28275         this.delegateUpdates();
28276     },
28277
28278     
28279     hideTabStripItem : function(item){
28280         item = this.getComponent(item);
28281         var el = this.getTabEl(item);
28282         if(el){
28283             el.style.display = 'none';
28284             this.delegateUpdates();
28285         }
28286         this.stack.remove(item);
28287     },
28288
28289     
28290     unhideTabStripItem : function(item){
28291         item = this.getComponent(item);
28292         var el = this.getTabEl(item);
28293         if(el){
28294             el.style.display = '';
28295             this.delegateUpdates();
28296         }
28297     },
28298
28299     
28300     delegateUpdates : function(){
28301         if(this.suspendUpdates){
28302             return;
28303         }
28304         if(this.resizeTabs && this.rendered){
28305             this.autoSizeTabs();
28306         }
28307         if(this.enableTabScroll && this.rendered){
28308             this.autoScrollTabs();
28309         }
28310     },
28311
28312     
28313     autoSizeTabs : function(){
28314         var count = this.items.length,
28315             ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
28316             ow = this[ce].dom.offsetWidth,
28317             aw = this[ce].dom.clientWidth;
28318
28319         if(!this.resizeTabs || count < 1 || !aw){ 
28320             return;
28321         }
28322
28323         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
28324         this.lastTabWidth = each;
28325         var lis = this.strip.query('li:not(.x-tab-edge)');
28326         for(var i = 0, len = lis.length; i < len; i++) {
28327             var li = lis[i],
28328                 inner = Ext.fly(li).child('.x-tab-strip-inner', true),
28329                 tw = li.offsetWidth,
28330                 iw = inner.offsetWidth;
28331             inner.style.width = (each - (tw-iw)) + 'px';
28332         }
28333     },
28334
28335     
28336     adjustBodyWidth : function(w){
28337         if(this.header){
28338             this.header.setWidth(w);
28339         }
28340         if(this.footer){
28341             this.footer.setWidth(w);
28342         }
28343         return w;
28344     },
28345
28346     
28347     setActiveTab : function(item){
28348         item = this.getComponent(item);
28349         if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
28350             return;
28351         }
28352         if(!this.rendered){
28353             this.activeTab = item;
28354             return;
28355         }
28356         if(this.activeTab != item){
28357             if(this.activeTab){
28358                 var oldEl = this.getTabEl(this.activeTab);
28359                 if(oldEl){
28360                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
28361                 }
28362             }
28363             this.activeTab = item;
28364             if(item){
28365                 var el = this.getTabEl(item);
28366                 Ext.fly(el).addClass('x-tab-strip-active');
28367                 this.stack.add(item);
28368
28369                 this.layout.setActiveItem(item);
28370                 if(this.scrolling){
28371                     this.scrollToTab(item, this.animScroll);
28372                 }
28373             }
28374             this.fireEvent('tabchange', this, item);
28375         }
28376     },
28377
28378     
28379     getActiveTab : function(){
28380         return this.activeTab || null;
28381     },
28382
28383     
28384     getItem : function(item){
28385         return this.getComponent(item);
28386     },
28387
28388     
28389     autoScrollTabs : function(){
28390         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
28391         var count = this.items.length,
28392             ow = this.pos.dom.offsetWidth,
28393             tw = this.pos.dom.clientWidth,
28394             wrap = this.stripWrap,
28395             wd = wrap.dom,
28396             cw = wd.offsetWidth,
28397             pos = this.getScrollPos(),
28398             l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
28399
28400         if(!this.enableTabScroll || count < 1 || cw < 20){ 
28401             return;
28402         }
28403         if(l <= tw){
28404             wd.scrollLeft = 0;
28405             wrap.setWidth(tw);
28406             if(this.scrolling){
28407                 this.scrolling = false;
28408                 this.pos.removeClass('x-tab-scrolling');
28409                 this.scrollLeft.hide();
28410                 this.scrollRight.hide();
28411                 
28412                 if(Ext.isAir || Ext.isWebKit){
28413                     wd.style.marginLeft = '';
28414                     wd.style.marginRight = '';
28415                 }
28416             }
28417         }else{
28418             if(!this.scrolling){
28419                 this.pos.addClass('x-tab-scrolling');
28420                 
28421                 if(Ext.isAir || Ext.isWebKit){
28422                     wd.style.marginLeft = '18px';
28423                     wd.style.marginRight = '18px';
28424                 }
28425             }
28426             tw -= wrap.getMargins('lr');
28427             wrap.setWidth(tw > 20 ? tw : 20);
28428             if(!this.scrolling){
28429                 if(!this.scrollLeft){
28430                     this.createScrollers();
28431                 }else{
28432                     this.scrollLeft.show();
28433                     this.scrollRight.show();
28434                 }
28435             }
28436             this.scrolling = true;
28437             if(pos > (l-tw)){ 
28438                 wd.scrollLeft = l-tw;
28439             }else{ 
28440                 this.scrollToTab(this.activeTab, false);
28441             }
28442             this.updateScrollButtons();
28443         }
28444     },
28445
28446     
28447     createScrollers : function(){
28448         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
28449         var h = this.stripWrap.dom.offsetHeight;
28450
28451         
28452         var sl = this.pos.insertFirst({
28453             cls:'x-tab-scroller-left'
28454         });
28455         sl.setHeight(h);
28456         sl.addClassOnOver('x-tab-scroller-left-over');
28457         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
28458             interval : this.scrollRepeatInterval,
28459             handler: this.onScrollLeft,
28460             scope: this
28461         });
28462         this.scrollLeft = sl;
28463
28464         
28465         var sr = this.pos.insertFirst({
28466             cls:'x-tab-scroller-right'
28467         });
28468         sr.setHeight(h);
28469         sr.addClassOnOver('x-tab-scroller-right-over');
28470         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
28471             interval : this.scrollRepeatInterval,
28472             handler: this.onScrollRight,
28473             scope: this
28474         });
28475         this.scrollRight = sr;
28476     },
28477
28478     
28479     getScrollWidth : function(){
28480         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
28481     },
28482
28483     
28484     getScrollPos : function(){
28485         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
28486     },
28487
28488     
28489     getScrollArea : function(){
28490         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
28491     },
28492
28493     
28494     getScrollAnim : function(){
28495         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
28496     },
28497
28498     
28499     getScrollIncrement : function(){
28500         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
28501     },
28502
28503     
28504
28505     scrollToTab : function(item, animate){
28506         if(!item){
28507             return;
28508         }
28509         var el = this.getTabEl(item),
28510             pos = this.getScrollPos(),
28511             area = this.getScrollArea(),
28512             left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
28513             right = left + el.offsetWidth;
28514         if(left < pos){
28515             this.scrollTo(left, animate);
28516         }else if(right > (pos + area)){
28517             this.scrollTo(right - area, animate);
28518         }
28519     },
28520
28521     
28522     scrollTo : function(pos, animate){
28523         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
28524         if(!animate){
28525             this.updateScrollButtons();
28526         }
28527     },
28528
28529     onWheel : function(e){
28530         var d = e.getWheelDelta()*this.wheelIncrement*-1;
28531         e.stopEvent();
28532
28533         var pos = this.getScrollPos(),
28534             newpos = pos + d,
28535             sw = this.getScrollWidth()-this.getScrollArea();
28536
28537         var s = Math.max(0, Math.min(sw, newpos));
28538         if(s != pos){
28539             this.scrollTo(s, false);
28540         }
28541     },
28542
28543     
28544     onScrollRight : function(){
28545         var sw = this.getScrollWidth()-this.getScrollArea(),
28546             pos = this.getScrollPos(),
28547             s = Math.min(sw, pos + this.getScrollIncrement());
28548         if(s != pos){
28549             this.scrollTo(s, this.animScroll);
28550         }
28551     },
28552
28553     
28554     onScrollLeft : function(){
28555         var pos = this.getScrollPos(),
28556             s = Math.max(0, pos - this.getScrollIncrement());
28557         if(s != pos){
28558             this.scrollTo(s, this.animScroll);
28559         }
28560     },
28561
28562     
28563     updateScrollButtons : function(){
28564         var pos = this.getScrollPos();
28565         this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
28566         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
28567     },
28568
28569     
28570     beforeDestroy : function() {
28571         Ext.destroy(this.leftRepeater, this.rightRepeater);
28572         this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
28573         this.activeTab = null;
28574         Ext.TabPanel.superclass.beforeDestroy.apply(this);
28575     }
28576
28577     
28578     
28579     
28580     
28581     
28582     
28583     
28584     
28585     
28586     
28587     
28588     
28589 });
28590 Ext.reg('tabpanel', Ext.TabPanel);
28591
28592
28593 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
28594
28595
28596 Ext.TabPanel.AccessStack = function(){
28597     var items = [];
28598     return {
28599         add : function(item){
28600             items.push(item);
28601             if(items.length > 10){
28602                 items.shift();
28603             }
28604         },
28605
28606         remove : function(item){
28607             var s = [];
28608             for(var i = 0, len = items.length; i < len; i++) {
28609                 if(items[i] != item){
28610                     s.push(items[i]);
28611                 }
28612             }
28613             items = s;
28614         },
28615
28616         next : function(){
28617             return items.pop();
28618         }
28619     };
28620 };
28621
28622 Ext.Button = Ext.extend(Ext.BoxComponent, {
28623     
28624     hidden : false,
28625     
28626     disabled : false,
28627     
28628     pressed : false,
28629
28630     
28631
28632     
28633
28634     
28635     enableToggle : false,
28636     
28637     
28638     
28639     menuAlign : 'tl-bl?',
28640
28641     
28642     
28643     
28644     type : 'button',
28645
28646     
28647     menuClassTarget : 'tr:nth(2)',
28648
28649     
28650     clickEvent : 'click',
28651
28652     
28653     handleMouseEvents : true,
28654
28655     
28656     tooltipType : 'qtip',
28657
28658     
28659     buttonSelector : 'button:first-child',
28660
28661     
28662     scale : 'small',
28663
28664     
28665
28666     
28667     iconAlign : 'left',
28668
28669     
28670     arrowAlign : 'right',
28671
28672     
28673     
28674     
28675     
28676
28677     initComponent : function(){
28678         Ext.Button.superclass.initComponent.call(this);
28679
28680         this.addEvents(
28681             
28682             'click',
28683             
28684             'toggle',
28685             
28686             'mouseover',
28687             
28688             'mouseout',
28689             
28690             'menushow',
28691             
28692             'menuhide',
28693             
28694             'menutriggerover',
28695             
28696             'menutriggerout'
28697         );
28698         if(this.menu){
28699             this.menu = Ext.menu.MenuMgr.get(this.menu);
28700         }
28701         if(Ext.isString(this.toggleGroup)){
28702             this.enableToggle = true;
28703         }
28704     },
28705
28706
28707     getTemplateArgs : function(){
28708         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
28709     },
28710
28711     
28712     setButtonClass : function(){
28713         if(this.useSetClass){
28714             if(!Ext.isEmpty(this.oldCls)){
28715                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
28716             }
28717             this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
28718             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
28719         }
28720     },
28721
28722     
28723     getMenuClass : function(){
28724         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
28725     },
28726
28727     
28728     onRender : function(ct, position){
28729         if(!this.template){
28730             if(!Ext.Button.buttonTemplate){
28731                 
28732                 Ext.Button.buttonTemplate = new Ext.Template(
28733                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
28734                     '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
28735                     '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
28736                     '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
28737                     '</tbody></table>');
28738                 Ext.Button.buttonTemplate.compile();
28739             }
28740             this.template = Ext.Button.buttonTemplate;
28741         }
28742
28743         var btn, targs = this.getTemplateArgs();
28744
28745         if(position){
28746             btn = this.template.insertBefore(position, targs, true);
28747         }else{
28748             btn = this.template.append(ct, targs, true);
28749         }
28750         
28751         this.btnEl = btn.child(this.buttonSelector);
28752         this.mon(this.btnEl, {
28753             scope: this,
28754             focus: this.onFocus,
28755             blur: this.onBlur
28756         });
28757
28758         this.initButtonEl(btn, this.btnEl);
28759
28760         Ext.ButtonToggleMgr.register(this);
28761     },
28762
28763     
28764     initButtonEl : function(btn, btnEl){
28765         this.el = btn;
28766         this.setIcon(this.icon);
28767         this.setText(this.text);
28768         this.setIconClass(this.iconCls);
28769         if(Ext.isDefined(this.tabIndex)){
28770             btnEl.dom.tabIndex = this.tabIndex;
28771         }
28772         if(this.tooltip){
28773             this.setTooltip(this.tooltip, true);
28774         }
28775
28776         if(this.handleMouseEvents){
28777             this.mon(btn, {
28778                 scope: this,
28779                 mouseover: this.onMouseOver,
28780                 mousedown: this.onMouseDown
28781             });
28782
28783             
28784             
28785         }
28786
28787         if(this.menu){
28788             this.mon(this.menu, {
28789                 scope: this,
28790                 show: this.onMenuShow,
28791                 hide: this.onMenuHide
28792             });
28793         }
28794
28795         if(this.repeat){
28796             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
28797             this.mon(repeater, 'click', this.onClick, this);
28798         }
28799         this.mon(btn, this.clickEvent, this.onClick, this);
28800     },
28801
28802     
28803     afterRender : function(){
28804         Ext.Button.superclass.afterRender.call(this);
28805         this.useSetClass = true;
28806         this.setButtonClass();
28807         this.doc = Ext.getDoc();
28808         this.doAutoWidth();
28809     },
28810
28811     
28812     setIconClass : function(cls){
28813         this.iconCls = cls;
28814         if(this.el){
28815             this.btnEl.dom.className = '';
28816             this.btnEl.addClass(['x-btn-text', cls || '']);
28817             this.setButtonClass();
28818         }
28819         return this;
28820     },
28821
28822     
28823     setTooltip : function(tooltip,  initial){
28824         if(this.rendered){
28825             if(!initial){
28826                 this.clearTip();
28827             }
28828             if(Ext.isObject(tooltip)){
28829                 Ext.QuickTips.register(Ext.apply({
28830                       target: this.btnEl.id
28831                 }, tooltip));
28832                 this.tooltip = tooltip;
28833             }else{
28834                 this.btnEl.dom[this.tooltipType] = tooltip;
28835             }
28836         }else{
28837             this.tooltip = tooltip;
28838         }
28839         return this;
28840     },
28841
28842     
28843     clearTip : function(){
28844         if(Ext.isObject(this.tooltip)){
28845             Ext.QuickTips.unregister(this.btnEl);
28846         }
28847     },
28848
28849     
28850     beforeDestroy : function(){
28851         if(this.rendered){
28852             this.clearTip();
28853         }
28854         if(this.menu && this.destroyMenu !== false) {
28855             Ext.destroy(this.menu);
28856         }
28857         Ext.destroy(this.repeater);
28858     },
28859
28860     
28861     onDestroy : function(){
28862         if(this.rendered){
28863             this.doc.un('mouseover', this.monitorMouseOver, this);
28864             this.doc.un('mouseup', this.onMouseUp, this);
28865             delete this.doc;
28866             delete this.btnEl;
28867             Ext.ButtonToggleMgr.unregister(this);
28868         }
28869         Ext.Button.superclass.onDestroy.call(this);
28870     },
28871
28872     
28873     doAutoWidth : function(){
28874         if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
28875             this.el.setWidth('auto');
28876             if(Ext.isIE7 && Ext.isStrict){
28877                 var ib = this.btnEl;
28878                 if(ib && ib.getWidth() > 20){
28879                     ib.clip();
28880                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
28881                 }
28882             }
28883             if(this.minWidth){
28884                 if(this.el.getWidth() < this.minWidth){
28885                     this.el.setWidth(this.minWidth);
28886                 }
28887             }
28888         }
28889     },
28890
28891     
28892     setHandler : function(handler, scope){
28893         this.handler = handler;
28894         this.scope = scope;
28895         return this;
28896     },
28897
28898     
28899     setText : function(text){
28900         this.text = text;
28901         if(this.el){
28902             this.btnEl.update(text || '&#160;');
28903             this.setButtonClass();
28904         }
28905         this.doAutoWidth();
28906         return this;
28907     },
28908
28909     
28910     setIcon : function(icon){
28911         this.icon = icon;
28912         if(this.el){
28913             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
28914             this.setButtonClass();
28915         }
28916         return this;
28917     },
28918
28919     
28920     getText : function(){
28921         return this.text;
28922     },
28923
28924     
28925     toggle : function(state, suppressEvent){
28926         state = state === undefined ? !this.pressed : !!state;
28927         if(state != this.pressed){
28928             if(this.rendered){
28929                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
28930             }
28931             this.pressed = state;
28932             if(!suppressEvent){
28933                 this.fireEvent('toggle', this, state);
28934                 if(this.toggleHandler){
28935                     this.toggleHandler.call(this.scope || this, this, state);
28936                 }
28937             }
28938         }
28939         return this;
28940     },
28941
28942     
28943     onDisable : function(){
28944         this.onDisableChange(true);
28945     },
28946
28947     
28948     onEnable : function(){
28949         this.onDisableChange(false);
28950     },
28951
28952     onDisableChange : function(disabled){
28953         if(this.el){
28954             if(!Ext.isIE6 || !this.text){
28955                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
28956             }
28957             this.el.dom.disabled = disabled;
28958         }
28959         this.disabled = disabled;
28960     },
28961
28962     
28963     showMenu : function(){
28964         if(this.rendered && this.menu){
28965             if(this.tooltip){
28966                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
28967             }
28968             if(this.menu.isVisible()){
28969                 this.menu.hide();
28970             }
28971             this.menu.ownerCt = this;
28972             this.menu.show(this.el, this.menuAlign);
28973         }
28974         return this;
28975     },
28976
28977     
28978     hideMenu : function(){
28979         if(this.hasVisibleMenu()){
28980             this.menu.hide();
28981         }
28982         return this;
28983     },
28984
28985     
28986     hasVisibleMenu : function(){
28987         return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
28988     },
28989
28990     
28991     onClick : function(e){
28992         if(e){
28993             e.preventDefault();
28994         }
28995         if(e.button !== 0){
28996             return;
28997         }
28998         if(!this.disabled){
28999             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
29000                 this.toggle();
29001             }
29002             if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
29003                 this.showMenu();
29004             }
29005             this.fireEvent('click', this, e);
29006             if(this.handler){
29007                 
29008                 this.handler.call(this.scope || this, this, e);
29009             }
29010         }
29011     },
29012
29013     
29014     isMenuTriggerOver : function(e, internal){
29015         return this.menu && !internal;
29016     },
29017
29018     
29019     isMenuTriggerOut : function(e, internal){
29020         return this.menu && !internal;
29021     },
29022
29023     
29024     onMouseOver : function(e){
29025         if(!this.disabled){
29026             var internal = e.within(this.el,  true);
29027             if(!internal){
29028                 this.el.addClass('x-btn-over');
29029                 if(!this.monitoringMouseOver){
29030                     this.doc.on('mouseover', this.monitorMouseOver, this);
29031                     this.monitoringMouseOver = true;
29032                 }
29033                 this.fireEvent('mouseover', this, e);
29034             }
29035             if(this.isMenuTriggerOver(e, internal)){
29036                 this.fireEvent('menutriggerover', this, this.menu, e);
29037             }
29038         }
29039     },
29040
29041     
29042     monitorMouseOver : function(e){
29043         if(e.target != this.el.dom && !e.within(this.el)){
29044             if(this.monitoringMouseOver){
29045                 this.doc.un('mouseover', this.monitorMouseOver, this);
29046                 this.monitoringMouseOver = false;
29047             }
29048             this.onMouseOut(e);
29049         }
29050     },
29051
29052     
29053     onMouseOut : function(e){
29054         var internal = e.within(this.el) && e.target != this.el.dom;
29055         this.el.removeClass('x-btn-over');
29056         this.fireEvent('mouseout', this, e);
29057         if(this.isMenuTriggerOut(e, internal)){
29058             this.fireEvent('menutriggerout', this, this.menu, e);
29059         }
29060     },
29061
29062     focus : function() {
29063         this.btnEl.focus();
29064     },
29065
29066     blur : function() {
29067         this.btnEl.blur();
29068     },
29069
29070     
29071     onFocus : function(e){
29072         if(!this.disabled){
29073             this.el.addClass('x-btn-focus');
29074         }
29075     },
29076     
29077     onBlur : function(e){
29078         this.el.removeClass('x-btn-focus');
29079     },
29080
29081     
29082     getClickEl : function(e, isUp){
29083        return this.el;
29084     },
29085
29086     
29087     onMouseDown : function(e){
29088         if(!this.disabled && e.button === 0){
29089             this.getClickEl(e).addClass('x-btn-click');
29090             this.doc.on('mouseup', this.onMouseUp, this);
29091         }
29092     },
29093     
29094     onMouseUp : function(e){
29095         if(e.button === 0){
29096             this.getClickEl(e, true).removeClass('x-btn-click');
29097             this.doc.un('mouseup', this.onMouseUp, this);
29098         }
29099     },
29100     
29101     onMenuShow : function(e){
29102         if(this.menu.ownerCt == this){
29103             this.menu.ownerCt = this;
29104             this.ignoreNextClick = 0;
29105             this.el.addClass('x-btn-menu-active');
29106             this.fireEvent('menushow', this, this.menu);
29107         }
29108     },
29109     
29110     onMenuHide : function(e){
29111         if(this.menu.ownerCt == this){
29112             this.el.removeClass('x-btn-menu-active');
29113             this.ignoreNextClick = this.restoreClick.defer(250, this);
29114             this.fireEvent('menuhide', this, this.menu);
29115             delete this.menu.ownerCt;
29116         }
29117     },
29118
29119     
29120     restoreClick : function(){
29121         this.ignoreNextClick = 0;
29122     }
29123
29124     
29125     
29126     
29127     
29128     
29129     
29130 });
29131 Ext.reg('button', Ext.Button);
29132
29133
29134 Ext.ButtonToggleMgr = function(){
29135    var groups = {};
29136
29137    function toggleGroup(btn, state){
29138        if(state){
29139            var g = groups[btn.toggleGroup];
29140            for(var i = 0, l = g.length; i < l; i++){
29141                if(g[i] != btn){
29142                    g[i].toggle(false);
29143                }
29144            }
29145        }
29146    }
29147
29148    return {
29149        register : function(btn){
29150            if(!btn.toggleGroup){
29151                return;
29152            }
29153            var g = groups[btn.toggleGroup];
29154            if(!g){
29155                g = groups[btn.toggleGroup] = [];
29156            }
29157            g.push(btn);
29158            btn.on('toggle', toggleGroup);
29159        },
29160
29161        unregister : function(btn){
29162            if(!btn.toggleGroup){
29163                return;
29164            }
29165            var g = groups[btn.toggleGroup];
29166            if(g){
29167                g.remove(btn);
29168                btn.un('toggle', toggleGroup);
29169            }
29170        },
29171
29172        
29173        getPressed : function(group){
29174            var g = groups[group];
29175            if(g){
29176                for(var i = 0, len = g.length; i < len; i++){
29177                    if(g[i].pressed === true){
29178                        return g[i];
29179                    }
29180                }
29181            }
29182            return null;
29183        }
29184    };
29185 }();
29186
29187 Ext.SplitButton = Ext.extend(Ext.Button, {
29188         
29189     arrowSelector : 'em',
29190     split: true,
29191
29192     
29193     initComponent : function(){
29194         Ext.SplitButton.superclass.initComponent.call(this);
29195         
29196         this.addEvents("arrowclick");
29197     },
29198
29199     
29200     onRender : function(){
29201         Ext.SplitButton.superclass.onRender.apply(this, arguments);
29202         if(this.arrowTooltip){
29203             this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
29204         }
29205     },
29206
29207     
29208     setArrowHandler : function(handler, scope){
29209         this.arrowHandler = handler;
29210         this.scope = scope;
29211     },
29212
29213     getMenuClass : function(){
29214         return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
29215     },
29216
29217     isClickOnArrow : function(e){
29218         if (this.arrowAlign != 'bottom') {
29219             var visBtn = this.el.child('em.x-btn-split');
29220             var right = visBtn.getRegion().right - visBtn.getPadding('r');
29221             return e.getPageX() > right;
29222         } else {
29223             return e.getPageY() > this.btnEl.getRegion().bottom;
29224         }
29225     },
29226
29227     
29228     onClick : function(e, t){
29229         e.preventDefault();
29230         if(!this.disabled){
29231             if(this.isClickOnArrow(e)){
29232                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
29233                     this.showMenu();
29234                 }
29235                 this.fireEvent("arrowclick", this, e);
29236                 if(this.arrowHandler){
29237                     this.arrowHandler.call(this.scope || this, this, e);
29238                 }
29239             }else{
29240                 if(this.enableToggle){
29241                     this.toggle();
29242                 }
29243                 this.fireEvent("click", this, e);
29244                 if(this.handler){
29245                     this.handler.call(this.scope || this, this, e);
29246                 }
29247             }
29248         }
29249     },
29250
29251     
29252     isMenuTriggerOver : function(e){
29253         return this.menu && e.target.tagName == this.arrowSelector;
29254     },
29255
29256     
29257     isMenuTriggerOut : function(e, internal){
29258         return this.menu && e.target.tagName != this.arrowSelector;
29259     }
29260 });
29261
29262 Ext.reg('splitbutton', Ext.SplitButton);
29263 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
29264     
29265     
29266     
29267     
29268     
29269     
29270
29271     
29272     getItemText : function(item){
29273         if(item && this.showText === true){
29274             var text = '';
29275             if(this.prependText){
29276                 text += this.prependText;
29277             }
29278             text += item.text;
29279             return text;
29280         }
29281         return undefined;
29282     },
29283
29284     
29285     setActiveItem : function(item, suppressEvent){
29286         if(!Ext.isObject(item)){
29287             item = this.menu.getComponent(item);
29288         }
29289         if(item){
29290             if(!this.rendered){
29291                 this.text = this.getItemText(item);
29292                 this.iconCls = item.iconCls;
29293             }else{
29294                 var t = this.getItemText(item);
29295                 if(t){
29296                     this.setText(t);
29297                 }
29298                 this.setIconClass(item.iconCls);
29299             }
29300             this.activeItem = item;
29301             if(!item.checked){
29302                 item.setChecked(true, false);
29303             }
29304             if(this.forceIcon){
29305                 this.setIconClass(this.forceIcon);
29306             }
29307             if(!suppressEvent){
29308                 this.fireEvent('change', this, item);
29309             }
29310         }
29311     },
29312
29313     
29314     getActiveItem : function(){
29315         return this.activeItem;
29316     },
29317
29318     
29319     initComponent : function(){
29320         this.addEvents(
29321             
29322             "change"
29323         );
29324
29325         if(this.changeHandler){
29326             this.on('change', this.changeHandler, this.scope||this);
29327             delete this.changeHandler;
29328         }
29329
29330         this.itemCount = this.items.length;
29331
29332         this.menu = {cls:'x-cycle-menu', items:[]};
29333         var checked = 0;
29334         Ext.each(this.items, function(item, i){
29335             Ext.apply(item, {
29336                 group: item.group || this.id,
29337                 itemIndex: i,
29338                 checkHandler: this.checkHandler,
29339                 scope: this,
29340                 checked: item.checked || false
29341             });
29342             this.menu.items.push(item);
29343             if(item.checked){
29344                 checked = i;
29345             }
29346         }, this);
29347         Ext.CycleButton.superclass.initComponent.call(this);
29348         this.on('click', this.toggleSelected, this);
29349         this.setActiveItem(checked, true);
29350     },
29351
29352     
29353     checkHandler : function(item, pressed){
29354         if(pressed){
29355             this.setActiveItem(item);
29356         }
29357     },
29358
29359     
29360     toggleSelected : function(){
29361         var m = this.menu;
29362         m.render();
29363         
29364         if(!m.hasLayout){
29365             m.doLayout();
29366         }
29367         
29368         var nextIdx, checkItem;
29369         for (var i = 1; i < this.itemCount; i++) {
29370             nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
29371             
29372             checkItem = m.items.itemAt(nextIdx);
29373             
29374             if (!checkItem.disabled) {
29375                 checkItem.setChecked(true);
29376                 break;
29377             }
29378         }
29379     }
29380 });
29381 Ext.reg('cycle', Ext.CycleButton);
29382 Ext.Toolbar = function(config){
29383     if(Ext.isArray(config)){
29384         config = {items: config, layout: 'toolbar'};
29385     } else {
29386         config = Ext.apply({
29387             layout: 'toolbar'
29388         }, config);
29389         if(config.buttons) {
29390             config.items = config.buttons;
29391         }
29392     }
29393     Ext.Toolbar.superclass.constructor.call(this, config);
29394 };
29395
29396 (function(){
29397
29398 var T = Ext.Toolbar;
29399
29400 Ext.extend(T, Ext.Container, {
29401
29402     defaultType: 'button',
29403
29404     
29405
29406     enableOverflow : false,
29407
29408     
29409     
29410
29411     trackMenus : true,
29412     internalDefaults: {removeMode: 'container', hideParent: true},
29413     toolbarCls: 'x-toolbar',
29414
29415     initComponent : function(){
29416         T.superclass.initComponent.call(this);
29417
29418         
29419         this.addEvents('overflowchange');
29420     },
29421
29422     
29423     onRender : function(ct, position){
29424         if(!this.el){
29425             if(!this.autoCreate){
29426                 this.autoCreate = {
29427                     cls: this.toolbarCls + ' x-small-editor'
29428                 };
29429             }
29430             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
29431             Ext.Toolbar.superclass.onRender.apply(this, arguments);
29432         }
29433     },
29434
29435     
29436
29437     
29438     lookupComponent : function(c){
29439         if(Ext.isString(c)){
29440             if(c == '-'){
29441                 c = new T.Separator();
29442             }else if(c == ' '){
29443                 c = new T.Spacer();
29444             }else if(c == '->'){
29445                 c = new T.Fill();
29446             }else{
29447                 c = new T.TextItem(c);
29448             }
29449             this.applyDefaults(c);
29450         }else{
29451             if(c.isFormField || c.render){ 
29452                 c = this.createComponent(c);
29453             }else if(c.tag){ 
29454                 c = new T.Item({autoEl: c});
29455             }else if(c.tagName){ 
29456                 c = new T.Item({el:c});
29457             }else if(Ext.isObject(c)){ 
29458                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
29459             }
29460         }
29461         return c;
29462     },
29463
29464     
29465     applyDefaults : function(c){
29466         if(!Ext.isString(c)){
29467             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
29468             var d = this.internalDefaults;
29469             if(c.events){
29470                 Ext.applyIf(c.initialConfig, d);
29471                 Ext.apply(c, d);
29472             }else{
29473                 Ext.applyIf(c, d);
29474             }
29475         }
29476         return c;
29477     },
29478
29479     
29480     addSeparator : function(){
29481         return this.add(new T.Separator());
29482     },
29483
29484     
29485     addSpacer : function(){
29486         return this.add(new T.Spacer());
29487     },
29488
29489     
29490     addFill : function(){
29491         this.add(new T.Fill());
29492     },
29493
29494     
29495     addElement : function(el){
29496         return this.addItem(new T.Item({el:el}));
29497     },
29498
29499     
29500     addItem : function(item){
29501         return this.add.apply(this, arguments);
29502     },
29503
29504     
29505     addButton : function(config){
29506         if(Ext.isArray(config)){
29507             var buttons = [];
29508             for(var i = 0, len = config.length; i < len; i++) {
29509                 buttons.push(this.addButton(config[i]));
29510             }
29511             return buttons;
29512         }
29513         return this.add(this.constructButton(config));
29514     },
29515
29516     
29517     addText : function(text){
29518         return this.addItem(new T.TextItem(text));
29519     },
29520
29521     
29522     addDom : function(config){
29523         return this.add(new T.Item({autoEl: config}));
29524     },
29525
29526     
29527     addField : function(field){
29528         return this.add(field);
29529     },
29530
29531     
29532     insertButton : function(index, item){
29533         if(Ext.isArray(item)){
29534             var buttons = [];
29535             for(var i = 0, len = item.length; i < len; i++) {
29536                buttons.push(this.insertButton(index + i, item[i]));
29537             }
29538             return buttons;
29539         }
29540         return Ext.Toolbar.superclass.insert.call(this, index, item);
29541     },
29542
29543     
29544     trackMenu : function(item, remove){
29545         if(this.trackMenus && item.menu){
29546             var method = remove ? 'mun' : 'mon';
29547             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
29548             this[method](item, 'menushow', this.onButtonMenuShow, this);
29549             this[method](item, 'menuhide', this.onButtonMenuHide, this);
29550         }
29551     },
29552
29553     
29554     constructButton : function(item){
29555         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
29556         return b;
29557     },
29558
29559     
29560     onAdd : function(c){
29561         Ext.Toolbar.superclass.onAdd.call(this);
29562         this.trackMenu(c);
29563         if(this.disabled){
29564             c.disable();
29565         }
29566     },
29567
29568     
29569     onRemove : function(c){
29570         Ext.Toolbar.superclass.onRemove.call(this);
29571         this.trackMenu(c, true);
29572     },
29573
29574     
29575     onDisable : function(){
29576         this.items.each(function(item){
29577              if(item.disable){
29578                  item.disable();
29579              }
29580         });
29581     },
29582
29583     
29584     onEnable : function(){
29585         this.items.each(function(item){
29586              if(item.enable){
29587                  item.enable();
29588              }
29589         });
29590     },
29591
29592     
29593     onButtonTriggerOver : function(btn){
29594         if(this.activeMenuBtn && this.activeMenuBtn != btn){
29595             this.activeMenuBtn.hideMenu();
29596             btn.showMenu();
29597             this.activeMenuBtn = btn;
29598         }
29599     },
29600
29601     
29602     onButtonMenuShow : function(btn){
29603         this.activeMenuBtn = btn;
29604     },
29605
29606     
29607     onButtonMenuHide : function(btn){
29608         delete this.activeMenuBtn;
29609     }
29610 });
29611 Ext.reg('toolbar', Ext.Toolbar);
29612
29613
29614 T.Item = Ext.extend(Ext.BoxComponent, {
29615     hideParent: true, 
29616     enable:Ext.emptyFn,
29617     disable:Ext.emptyFn,
29618     focus:Ext.emptyFn
29619     
29620 });
29621 Ext.reg('tbitem', T.Item);
29622
29623
29624 T.Separator = Ext.extend(T.Item, {
29625     onRender : function(ct, position){
29626         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
29627     }
29628 });
29629 Ext.reg('tbseparator', T.Separator);
29630
29631
29632 T.Spacer = Ext.extend(T.Item, {
29633     
29634
29635     onRender : function(ct, position){
29636         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
29637     }
29638 });
29639 Ext.reg('tbspacer', T.Spacer);
29640
29641
29642 T.Fill = Ext.extend(T.Item, {
29643     
29644     render : Ext.emptyFn,
29645     isFill : true
29646 });
29647 Ext.reg('tbfill', T.Fill);
29648
29649
29650 T.TextItem = Ext.extend(T.Item, {
29651     
29652
29653     constructor: function(config){
29654         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
29655     },
29656
29657     
29658     onRender : function(ct, position) {
29659         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
29660         T.TextItem.superclass.onRender.call(this, ct, position);
29661     },
29662
29663     
29664     setText : function(t) {
29665         if(this.rendered){
29666             this.el.update(t);
29667         }else{
29668             this.text = t;
29669         }
29670     }
29671 });
29672 Ext.reg('tbtext', T.TextItem);
29673
29674
29675 T.Button = Ext.extend(Ext.Button, {});
29676 T.SplitButton = Ext.extend(Ext.SplitButton, {});
29677 Ext.reg('tbbutton', T.Button);
29678 Ext.reg('tbsplit', T.SplitButton);
29679
29680 })();
29681
29682 Ext.ButtonGroup = Ext.extend(Ext.Panel, {
29683     
29684     
29685     baseCls: 'x-btn-group',
29686     
29687     layout:'table',
29688     defaultType: 'button',
29689     
29690     frame: true,
29691     internalDefaults: {removeMode: 'container', hideParent: true},
29692
29693     initComponent : function(){
29694         this.layoutConfig = this.layoutConfig || {};
29695         Ext.applyIf(this.layoutConfig, {
29696             columns : this.columns
29697         });
29698         if(!this.title){
29699             this.addClass('x-btn-group-notitle');
29700         }
29701         this.on('afterlayout', this.onAfterLayout, this);
29702         Ext.ButtonGroup.superclass.initComponent.call(this);
29703     },
29704
29705     applyDefaults : function(c){
29706         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
29707         var d = this.internalDefaults;
29708         if(c.events){
29709             Ext.applyIf(c.initialConfig, d);
29710             Ext.apply(c, d);
29711         }else{
29712             Ext.applyIf(c, d);
29713         }
29714         return c;
29715     },
29716
29717     onAfterLayout : function(){
29718         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
29719         this.body.setWidth(bodyWidth);
29720         this.el.setWidth(bodyWidth + this.getFrameWidth());
29721     }
29722     
29723 });
29724
29725 Ext.reg('buttongroup', Ext.ButtonGroup);
29726
29727 (function() {
29728
29729 var T = Ext.Toolbar;
29730
29731 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
29732     
29733     
29734     
29735     pageSize : 20,
29736     
29737     
29738     displayMsg : 'Displaying {0} - {1} of {2}',
29739     
29740     emptyMsg : 'No data to display',
29741     
29742     beforePageText : 'Page',
29743     
29744     afterPageText : 'of {0}',
29745     
29746     firstText : 'First Page',
29747     
29748     prevText : 'Previous Page',
29749     
29750     nextText : 'Next Page',
29751     
29752     lastText : 'Last Page',
29753     
29754     refreshText : 'Refresh',
29755
29756     
29757
29758     
29759
29760     
29761
29762     initComponent : function(){
29763         var pagingItems = [this.first = new T.Button({
29764             tooltip: this.firstText,
29765             overflowText: this.firstText,
29766             iconCls: 'x-tbar-page-first',
29767             disabled: true,
29768             handler: this.moveFirst,
29769             scope: this
29770         }), this.prev = new T.Button({
29771             tooltip: this.prevText,
29772             overflowText: this.prevText,
29773             iconCls: 'x-tbar-page-prev',
29774             disabled: true,
29775             handler: this.movePrevious,
29776             scope: this
29777         }), '-', this.beforePageText,
29778         this.inputItem = new Ext.form.NumberField({
29779             cls: 'x-tbar-page-number',
29780             allowDecimals: false,
29781             allowNegative: false,
29782             enableKeyEvents: true,
29783             selectOnFocus: true,
29784             submitValue: false,
29785             listeners: {
29786                 scope: this,
29787                 keydown: this.onPagingKeyDown,
29788                 blur: this.onPagingBlur
29789             }
29790         }), this.afterTextItem = new T.TextItem({
29791             text: String.format(this.afterPageText, 1)
29792         }), '-', this.next = new T.Button({
29793             tooltip: this.nextText,
29794             overflowText: this.nextText,
29795             iconCls: 'x-tbar-page-next',
29796             disabled: true,
29797             handler: this.moveNext,
29798             scope: this
29799         }), this.last = new T.Button({
29800             tooltip: this.lastText,
29801             overflowText: this.lastText,
29802             iconCls: 'x-tbar-page-last',
29803             disabled: true,
29804             handler: this.moveLast,
29805             scope: this
29806         }), '-', this.refresh = new T.Button({
29807             tooltip: this.refreshText,
29808             overflowText: this.refreshText,
29809             iconCls: 'x-tbar-loading',
29810             handler: this.doRefresh,
29811             scope: this
29812         })];
29813
29814
29815         var userItems = this.items || this.buttons || [];
29816         if (this.prependButtons) {
29817             this.items = userItems.concat(pagingItems);
29818         }else{
29819             this.items = pagingItems.concat(userItems);
29820         }
29821         delete this.buttons;
29822         if(this.displayInfo){
29823             this.items.push('->');
29824             this.items.push(this.displayItem = new T.TextItem({}));
29825         }
29826         Ext.PagingToolbar.superclass.initComponent.call(this);
29827         this.addEvents(
29828             
29829             'change',
29830             
29831             'beforechange'
29832         );
29833         this.on('afterlayout', this.onFirstLayout, this, {single: true});
29834         this.cursor = 0;
29835         this.bindStore(this.store, true);
29836     },
29837
29838     
29839     onFirstLayout : function(){
29840         if(this.dsLoaded){
29841             this.onLoad.apply(this, this.dsLoaded);
29842         }
29843     },
29844
29845     
29846     updateInfo : function(){
29847         if(this.displayItem){
29848             var count = this.store.getCount();
29849             var msg = count == 0 ?
29850                 this.emptyMsg :
29851                 String.format(
29852                     this.displayMsg,
29853                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
29854                 );
29855             this.displayItem.setText(msg);
29856         }
29857     },
29858
29859     
29860     onLoad : function(store, r, o){
29861         if(!this.rendered){
29862             this.dsLoaded = [store, r, o];
29863             return;
29864         }
29865         var p = this.getParams();
29866         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
29867         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
29868
29869         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
29870         this.inputItem.setValue(ap);
29871         this.first.setDisabled(ap == 1);
29872         this.prev.setDisabled(ap == 1);
29873         this.next.setDisabled(ap == ps);
29874         this.last.setDisabled(ap == ps);
29875         this.refresh.enable();
29876         this.updateInfo();
29877         this.fireEvent('change', this, d);
29878     },
29879
29880     
29881     getPageData : function(){
29882         var total = this.store.getTotalCount();
29883         return {
29884             total : total,
29885             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
29886             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
29887         };
29888     },
29889
29890     
29891     changePage : function(page){
29892         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
29893     },
29894
29895     
29896     onLoadError : function(){
29897         if(!this.rendered){
29898             return;
29899         }
29900         this.refresh.enable();
29901     },
29902
29903     
29904     readPage : function(d){
29905         var v = this.inputItem.getValue(), pageNum;
29906         if (!v || isNaN(pageNum = parseInt(v, 10))) {
29907             this.inputItem.setValue(d.activePage);
29908             return false;
29909         }
29910         return pageNum;
29911     },
29912
29913     onPagingFocus : function(){
29914         this.inputItem.select();
29915     },
29916
29917     
29918     onPagingBlur : function(e){
29919         this.inputItem.setValue(this.getPageData().activePage);
29920     },
29921
29922     
29923     onPagingKeyDown : function(field, e){
29924         var k = e.getKey(), d = this.getPageData(), pageNum;
29925         if (k == e.RETURN) {
29926             e.stopEvent();
29927             pageNum = this.readPage(d);
29928             if(pageNum !== false){
29929                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
29930                 this.doLoad(pageNum * this.pageSize);
29931             }
29932         }else if (k == e.HOME || k == e.END){
29933             e.stopEvent();
29934             pageNum = k == e.HOME ? 1 : d.pages;
29935             field.setValue(pageNum);
29936         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
29937             e.stopEvent();
29938             if((pageNum = this.readPage(d))){
29939                 var increment = e.shiftKey ? 10 : 1;
29940                 if(k == e.DOWN || k == e.PAGEDOWN){
29941                     increment *= -1;
29942                 }
29943                 pageNum += increment;
29944                 if(pageNum >= 1 & pageNum <= d.pages){
29945                     field.setValue(pageNum);
29946                 }
29947             }
29948         }
29949     },
29950
29951     
29952     getParams : function(){
29953         
29954         return this.paramNames || this.store.paramNames;
29955     },
29956
29957     
29958     beforeLoad : function(){
29959         if(this.rendered && this.refresh){
29960             this.refresh.disable();
29961         }
29962     },
29963
29964     
29965     doLoad : function(start){
29966         var o = {}, pn = this.getParams();
29967         o[pn.start] = start;
29968         o[pn.limit] = this.pageSize;
29969         if(this.fireEvent('beforechange', this, o) !== false){
29970             this.store.load({params:o});
29971         }
29972     },
29973
29974     
29975     moveFirst : function(){
29976         this.doLoad(0);
29977     },
29978
29979     
29980     movePrevious : function(){
29981         this.doLoad(Math.max(0, this.cursor-this.pageSize));
29982     },
29983
29984     
29985     moveNext : function(){
29986         this.doLoad(this.cursor+this.pageSize);
29987     },
29988
29989     
29990     moveLast : function(){
29991         var total = this.store.getTotalCount(),
29992             extra = total % this.pageSize;
29993
29994         this.doLoad(extra ? (total - extra) : total - this.pageSize);
29995     },
29996
29997     
29998     doRefresh : function(){
29999         this.doLoad(this.cursor);
30000     },
30001
30002     
30003     bindStore : function(store, initial){
30004         var doLoad;
30005         if(!initial && this.store){
30006             if(store !== this.store && this.store.autoDestroy){
30007                 this.store.destroy();
30008             }else{
30009                 this.store.un('beforeload', this.beforeLoad, this);
30010                 this.store.un('load', this.onLoad, this);
30011                 this.store.un('exception', this.onLoadError, this);
30012             }
30013             if(!store){
30014                 this.store = null;
30015             }
30016         }
30017         if(store){
30018             store = Ext.StoreMgr.lookup(store);
30019             store.on({
30020                 scope: this,
30021                 beforeload: this.beforeLoad,
30022                 load: this.onLoad,
30023                 exception: this.onLoadError
30024             });
30025             doLoad = true;
30026         }
30027         this.store = store;
30028         if(doLoad){
30029             this.onLoad(store, null, {});
30030         }
30031     },
30032
30033     
30034     unbind : function(store){
30035         this.bindStore(null);
30036     },
30037
30038     
30039     bind : function(store){
30040         this.bindStore(store);
30041     },
30042
30043     
30044     onDestroy : function(){
30045         this.bindStore(null);
30046         Ext.PagingToolbar.superclass.onDestroy.call(this);
30047     }
30048 });
30049
30050 })();
30051 Ext.reg('paging', Ext.PagingToolbar);
30052 Ext.History = (function () {
30053     var iframe, hiddenField;
30054     var ready = false;
30055     var currentToken;
30056
30057     function getHash() {
30058         var href = top.location.href, i = href.indexOf("#");
30059         return i >= 0 ? href.substr(i + 1) : null;
30060     }
30061
30062     function doSave() {
30063         hiddenField.value = currentToken;
30064     }
30065
30066     function handleStateChange(token) {
30067         currentToken = token;
30068         Ext.History.fireEvent('change', token);
30069     }
30070
30071     function updateIFrame (token) {
30072         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
30073         try {
30074             var doc = iframe.contentWindow.document;
30075             doc.open();
30076             doc.write(html);
30077             doc.close();
30078             return true;
30079         } catch (e) {
30080             return false;
30081         }
30082     }
30083
30084     function checkIFrame() {
30085         if (!iframe.contentWindow || !iframe.contentWindow.document) {
30086             setTimeout(checkIFrame, 10);
30087             return;
30088         }
30089
30090         var doc = iframe.contentWindow.document;
30091         var elem = doc.getElementById("state");
30092         var token = elem ? elem.innerText : null;
30093
30094         var hash = getHash();
30095
30096         setInterval(function () {
30097
30098             doc = iframe.contentWindow.document;
30099             elem = doc.getElementById("state");
30100
30101             var newtoken = elem ? elem.innerText : null;
30102
30103             var newHash = getHash();
30104
30105             if (newtoken !== token) {
30106                 token = newtoken;
30107                 handleStateChange(token);
30108                 top.location.hash = token;
30109                 hash = token;
30110                 doSave();
30111             } else if (newHash !== hash) {
30112                 hash = newHash;
30113                 updateIFrame(newHash);
30114             }
30115
30116         }, 50);
30117
30118         ready = true;
30119
30120         Ext.History.fireEvent('ready', Ext.History);
30121     }
30122
30123     function startUp() {
30124         currentToken = hiddenField.value ? hiddenField.value : getHash();
30125
30126         if (Ext.isIE) {
30127             checkIFrame();
30128         } else {
30129             var hash = getHash();
30130             setInterval(function () {
30131                 var newHash = getHash();
30132                 if (newHash !== hash) {
30133                     hash = newHash;
30134                     handleStateChange(hash);
30135                     doSave();
30136                 }
30137             }, 50);
30138             ready = true;
30139             Ext.History.fireEvent('ready', Ext.History);
30140         }
30141     }
30142
30143     return {
30144         
30145         fieldId: 'x-history-field',
30146         
30147         iframeId: 'x-history-frame',
30148
30149         events:{},
30150
30151         
30152         init: function (onReady, scope) {
30153             if(ready) {
30154                 Ext.callback(onReady, scope, [this]);
30155                 return;
30156             }
30157             if(!Ext.isReady){
30158                 Ext.onReady(function(){
30159                     Ext.History.init(onReady, scope);
30160                 });
30161                 return;
30162             }
30163             hiddenField = Ext.getDom(Ext.History.fieldId);
30164             if (Ext.isIE) {
30165                 iframe = Ext.getDom(Ext.History.iframeId);
30166             }
30167             this.addEvents(
30168                 
30169                 'ready',
30170                 
30171                 'change'
30172             );
30173             if(onReady){
30174                 this.on('ready', onReady, scope, {single:true});
30175             }
30176             startUp();
30177         },
30178
30179         
30180         add: function (token, preventDup) {
30181             if(preventDup !== false){
30182                 if(this.getToken() == token){
30183                     return true;
30184                 }
30185             }
30186             if (Ext.isIE) {
30187                 return updateIFrame(token);
30188             } else {
30189                 top.location.hash = token;
30190                 return true;
30191             }
30192         },
30193
30194         
30195         back: function(){
30196             history.go(-1);
30197         },
30198
30199         
30200         forward: function(){
30201             history.go(1);
30202         },
30203
30204         
30205         getToken: function() {
30206             return ready ? currentToken : getHash();
30207         }
30208     };
30209 })();
30210 Ext.apply(Ext.History, new Ext.util.Observable());
30211 Ext.Tip = Ext.extend(Ext.Panel, {
30212     
30213     
30214     
30215     minWidth : 40,
30216     
30217     maxWidth : 300,
30218     
30219     shadow : "sides",
30220     
30221     defaultAlign : "tl-bl?",
30222     autoRender: true,
30223     quickShowInterval : 250,
30224
30225     
30226     frame:true,
30227     hidden:true,
30228     baseCls: 'x-tip',
30229     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
30230     autoHeight:true,
30231
30232     closeAction: 'hide',
30233
30234     
30235     initComponent : function(){
30236         Ext.Tip.superclass.initComponent.call(this);
30237         if(this.closable && !this.title){
30238             this.elements += ',header';
30239         }
30240     },
30241
30242     
30243     afterRender : function(){
30244         Ext.Tip.superclass.afterRender.call(this);
30245         if(this.closable){
30246             this.addTool({
30247                 id: 'close',
30248                 handler: this[this.closeAction],
30249                 scope: this
30250             });
30251         }
30252     },
30253
30254     
30255     showAt : function(xy){
30256         Ext.Tip.superclass.show.call(this);
30257         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
30258             this.doAutoWidth();
30259         }
30260         if(this.constrainPosition){
30261             xy = this.el.adjustForConstraints(xy);
30262         }
30263         this.setPagePosition(xy[0], xy[1]);
30264     },
30265
30266     
30267     doAutoWidth : function(adjust){
30268         adjust = adjust || 0;
30269         var bw = this.body.getTextWidth();
30270         if(this.title){
30271             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
30272         }
30273         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
30274         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
30275         
30276         
30277         if(Ext.isIE7 && !this.repainted){
30278             this.el.repaint();
30279             this.repainted = true;
30280         }
30281     },
30282
30283     
30284     showBy : function(el, pos){
30285         if(!this.rendered){
30286             this.render(Ext.getBody());
30287         }
30288         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
30289     },
30290
30291     initDraggable : function(){
30292         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
30293         this.header.addClass('x-tip-draggable');
30294     }
30295 });
30296
30297 Ext.reg('tip', Ext.Tip);
30298
30299
30300 Ext.Tip.DD = function(tip, config){
30301     Ext.apply(this, config);
30302     this.tip = tip;
30303     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
30304     this.setHandleElId(tip.header.id);
30305     this.scroll = false;
30306 };
30307
30308 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
30309     moveOnly:true,
30310     scroll:false,
30311     headerOffsets:[100, 25],
30312     startDrag : function(){
30313         this.tip.el.disableShadow();
30314     },
30315     endDrag : function(e){
30316         this.tip.el.enableShadow(true);
30317     }
30318 });
30319 Ext.ToolTip = Ext.extend(Ext.Tip, {
30320     
30321     
30322     
30323     
30324     showDelay : 500,
30325     
30326     hideDelay : 200,
30327     
30328     dismissDelay : 5000,
30329     
30330     
30331     trackMouse : false,
30332     
30333     anchorToTarget : true,
30334     
30335     anchorOffset : 0,
30336     
30337
30338     
30339     targetCounter : 0,
30340
30341     constrainPosition : false,
30342
30343     
30344     initComponent : function(){
30345         Ext.ToolTip.superclass.initComponent.call(this);
30346         this.lastActive = new Date();
30347         this.initTarget(this.target);
30348         this.origAnchor = this.anchor;
30349     },
30350
30351     
30352     onRender : function(ct, position){
30353         Ext.ToolTip.superclass.onRender.call(this, ct, position);
30354         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
30355         this.anchorEl = this.el.createChild({
30356             cls: 'x-tip-anchor ' + this.anchorCls
30357         });
30358     },
30359
30360     
30361     afterRender : function(){
30362         Ext.ToolTip.superclass.afterRender.call(this);
30363         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1);
30364     },
30365
30366     
30367     initTarget : function(target){
30368         var t;
30369         if((t = Ext.get(target))){
30370             if(this.target){
30371                 var tg = Ext.get(this.target);
30372                 this.mun(tg, 'mouseover', this.onTargetOver, this);
30373                 this.mun(tg, 'mouseout', this.onTargetOut, this);
30374                 this.mun(tg, 'mousemove', this.onMouseMove, this);
30375             }
30376             this.mon(t, {
30377                 mouseover: this.onTargetOver,
30378                 mouseout: this.onTargetOut,
30379                 mousemove: this.onMouseMove,
30380                 scope: this
30381             });
30382             this.target = t;
30383         }
30384         if(this.anchor){
30385             this.anchorTarget = this.target;
30386         }
30387     },
30388
30389     
30390     onMouseMove : function(e){
30391         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
30392         if (t) {
30393             this.targetXY = e.getXY();
30394             if (t === this.triggerElement) {
30395                 if(!this.hidden && this.trackMouse){
30396                     this.setPagePosition(this.getTargetXY());
30397                 }
30398             } else {
30399                 this.hide();
30400                 this.lastActive = new Date(0);
30401                 this.onTargetOver(e);
30402             }
30403         } else if (!this.closable && this.isVisible()) {
30404             this.hide();
30405         }
30406     },
30407
30408     
30409     getTargetXY : function(){
30410         if(this.delegate){
30411             this.anchorTarget = this.triggerElement;
30412         }
30413         if(this.anchor){
30414             this.targetCounter++;
30415             var offsets = this.getOffsets(),
30416                 xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
30417                 dw = Ext.lib.Dom.getViewWidth() - 5,
30418                 dh = Ext.lib.Dom.getViewHeight() - 5,
30419                 de = document.documentElement,
30420                 bd = document.body,
30421                 scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
30422                 scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
30423                 axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
30424                 sz = this.getSize();
30425                 
30426             this.anchorEl.removeClass(this.anchorCls);
30427
30428             if(this.targetCounter < 2){
30429                 if(axy[0] < scrollX){
30430                     if(this.anchorToTarget){
30431                         this.defaultAlign = 'l-r';
30432                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
30433                     }
30434                     this.anchor = 'left';
30435                     return this.getTargetXY();
30436                 }
30437                 if(axy[0]+sz.width > dw){
30438                     if(this.anchorToTarget){
30439                         this.defaultAlign = 'r-l';
30440                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
30441                     }
30442                     this.anchor = 'right';
30443                     return this.getTargetXY();
30444                 }
30445                 if(axy[1] < scrollY){
30446                     if(this.anchorToTarget){
30447                         this.defaultAlign = 't-b';
30448                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
30449                     }
30450                     this.anchor = 'top';
30451                     return this.getTargetXY();
30452                 }
30453                 if(axy[1]+sz.height > dh){
30454                     if(this.anchorToTarget){
30455                         this.defaultAlign = 'b-t';
30456                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
30457                     }
30458                     this.anchor = 'bottom';
30459                     return this.getTargetXY();
30460                 }
30461             }
30462
30463             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
30464             this.anchorEl.addClass(this.anchorCls);
30465             this.targetCounter = 0;
30466             return axy;
30467         }else{
30468             var mouseOffset = this.getMouseOffset();
30469             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
30470         }
30471     },
30472
30473     getMouseOffset : function(){
30474         var offset = this.anchor ? [0,0] : [15,18];
30475         if(this.mouseOffset){
30476             offset[0] += this.mouseOffset[0];
30477             offset[1] += this.mouseOffset[1];
30478         }
30479         return offset;
30480     },
30481
30482     
30483     getAnchorPosition : function(){
30484         if(this.anchor){
30485             this.tipAnchor = this.anchor.charAt(0);
30486         }else{
30487             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
30488             if(!m){
30489                throw 'AnchorTip.defaultAlign is invalid';
30490             }
30491             this.tipAnchor = m[1].charAt(0);
30492         }
30493
30494         switch(this.tipAnchor){
30495             case 't': return 'top';
30496             case 'b': return 'bottom';
30497             case 'r': return 'right';
30498         }
30499         return 'left';
30500     },
30501
30502     
30503     getAnchorAlign : function(){
30504         switch(this.anchor){
30505             case 'top'  : return 'tl-bl';
30506             case 'left' : return 'tl-tr';
30507             case 'right': return 'tr-tl';
30508             default     : return 'bl-tl';
30509         }
30510     },
30511
30512     
30513     getOffsets : function(){
30514         var offsets, 
30515             ap = this.getAnchorPosition().charAt(0);
30516         if(this.anchorToTarget && !this.trackMouse){
30517             switch(ap){
30518                 case 't':
30519                     offsets = [0, 9];
30520                     break;
30521                 case 'b':
30522                     offsets = [0, -13];
30523                     break;
30524                 case 'r':
30525                     offsets = [-13, 0];
30526                     break;
30527                 default:
30528                     offsets = [9, 0];
30529                     break;
30530             }
30531         }else{
30532             switch(ap){
30533                 case 't':
30534                     offsets = [-15-this.anchorOffset, 30];
30535                     break;
30536                 case 'b':
30537                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
30538                     break;
30539                 case 'r':
30540                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
30541                     break;
30542                 default:
30543                     offsets = [25, -13-this.anchorOffset];
30544                     break;
30545             }
30546         }
30547         var mouseOffset = this.getMouseOffset();
30548         offsets[0] += mouseOffset[0];
30549         offsets[1] += mouseOffset[1];
30550
30551         return offsets;
30552     },
30553
30554     
30555     onTargetOver : function(e){
30556         if(this.disabled || e.within(this.target.dom, true)){
30557             return;
30558         }
30559         var t = e.getTarget(this.delegate);
30560         if (t) {
30561             this.triggerElement = t;
30562             this.clearTimer('hide');
30563             this.targetXY = e.getXY();
30564             this.delayShow();
30565         }
30566     },
30567
30568     
30569     delayShow : function(){
30570         if(this.hidden && !this.showTimer){
30571             if(this.lastActive.getElapsed() < this.quickShowInterval){
30572                 this.show();
30573             }else{
30574                 this.showTimer = this.show.defer(this.showDelay, this);
30575             }
30576         }else if(!this.hidden && this.autoHide !== false){
30577             this.show();
30578         }
30579     },
30580
30581     
30582     onTargetOut : function(e){
30583         if(this.disabled || e.within(this.target.dom, true)){
30584             return;
30585         }
30586         this.clearTimer('show');
30587         if(this.autoHide !== false){
30588             this.delayHide();
30589         }
30590     },
30591
30592     
30593     delayHide : function(){
30594         if(!this.hidden && !this.hideTimer){
30595             this.hideTimer = this.hide.defer(this.hideDelay, this);
30596         }
30597     },
30598
30599     
30600     hide: function(){
30601         this.clearTimer('dismiss');
30602         this.lastActive = new Date();
30603         if(this.anchorEl){
30604             this.anchorEl.hide();
30605         }
30606         Ext.ToolTip.superclass.hide.call(this);
30607         delete this.triggerElement;
30608     },
30609
30610     
30611     show : function(){
30612         if(this.anchor){
30613             
30614             
30615             this.showAt([-1000,-1000]);
30616             this.origConstrainPosition = this.constrainPosition;
30617             this.constrainPosition = false;
30618             this.anchor = this.origAnchor;
30619         }
30620         this.showAt(this.getTargetXY());
30621
30622         if(this.anchor){
30623             this.syncAnchor();
30624             this.anchorEl.show();
30625             this.constrainPosition = this.origConstrainPosition;
30626         }else{
30627             this.anchorEl.hide();
30628         }
30629     },
30630
30631     
30632     showAt : function(xy){
30633         this.lastActive = new Date();
30634         this.clearTimers();
30635         Ext.ToolTip.superclass.showAt.call(this, xy);
30636         if(this.dismissDelay && this.autoHide !== false){
30637             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
30638         }
30639         if(this.anchor && !this.anchorEl.isVisible()){
30640             this.syncAnchor();
30641             this.anchorEl.show();
30642         }
30643     },
30644
30645     
30646     syncAnchor : function(){
30647         var anchorPos, targetPos, offset;
30648         switch(this.tipAnchor.charAt(0)){
30649             case 't':
30650                 anchorPos = 'b';
30651                 targetPos = 'tl';
30652                 offset = [20+this.anchorOffset, 2];
30653                 break;
30654             case 'r':
30655                 anchorPos = 'l';
30656                 targetPos = 'tr';
30657                 offset = [-2, 11+this.anchorOffset];
30658                 break;
30659             case 'b':
30660                 anchorPos = 't';
30661                 targetPos = 'bl';
30662                 offset = [20+this.anchorOffset, -2];
30663                 break;
30664             default:
30665                 anchorPos = 'r';
30666                 targetPos = 'tl';
30667                 offset = [2, 11+this.anchorOffset];
30668                 break;
30669         }
30670         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
30671     },
30672
30673     
30674     setPagePosition : function(x, y){
30675         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
30676         if(this.anchor){
30677             this.syncAnchor();
30678         }
30679     },
30680
30681     
30682     clearTimer : function(name){
30683         name = name + 'Timer';
30684         clearTimeout(this[name]);
30685         delete this[name];
30686     },
30687
30688     
30689     clearTimers : function(){
30690         this.clearTimer('show');
30691         this.clearTimer('dismiss');
30692         this.clearTimer('hide');
30693     },
30694
30695     
30696     onShow : function(){
30697         Ext.ToolTip.superclass.onShow.call(this);
30698         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
30699     },
30700
30701     
30702     onHide : function(){
30703         Ext.ToolTip.superclass.onHide.call(this);
30704         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
30705     },
30706
30707     
30708     onDocMouseDown : function(e){
30709         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
30710             this.disable();
30711             this.doEnable.defer(100, this);
30712         }
30713     },
30714     
30715     
30716     doEnable : function(){
30717         if(!this.isDestroyed){
30718             this.enable();
30719         }
30720     },
30721
30722     
30723     onDisable : function(){
30724         this.clearTimers();
30725         this.hide();
30726     },
30727
30728     
30729     adjustPosition : function(x, y){
30730         if(this.contstrainPosition){
30731             var ay = this.targetXY[1], h = this.getSize().height;
30732             if(y <= ay && (y+h) >= ay){
30733                 y = ay-h-5;
30734             }
30735         }
30736         return {x : x, y: y};
30737     },
30738     
30739     beforeDestroy : function(){
30740         this.clearTimers();
30741         Ext.destroy(this.anchorEl);
30742         delete this.anchorEl;
30743         delete this.target;
30744         delete this.anchorTarget;
30745         delete this.triggerElement;
30746         Ext.ToolTip.superclass.beforeDestroy.call(this);    
30747     },
30748
30749     
30750     onDestroy : function(){
30751         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
30752         Ext.ToolTip.superclass.onDestroy.call(this);
30753     }
30754 });
30755
30756 Ext.reg('tooltip', Ext.ToolTip);
30757 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
30758     
30759     
30760     interceptTitles : false,
30761
30762     
30763     tagConfig : {
30764         namespace : "ext",
30765         attribute : "qtip",
30766         width : "qwidth",
30767         target : "target",
30768         title : "qtitle",
30769         hide : "hide",
30770         cls : "qclass",
30771         align : "qalign",
30772         anchor : "anchor"
30773     },
30774
30775     
30776     initComponent : function(){
30777         this.target = this.target || Ext.getDoc();
30778         this.targets = this.targets || {};
30779         Ext.QuickTip.superclass.initComponent.call(this);
30780     },
30781
30782     
30783     register : function(config){
30784         var cs = Ext.isArray(config) ? config : arguments;
30785         for(var i = 0, len = cs.length; i < len; i++){
30786             var c = cs[i];
30787             var target = c.target;
30788             if(target){
30789                 if(Ext.isArray(target)){
30790                     for(var j = 0, jlen = target.length; j < jlen; j++){
30791                         this.targets[Ext.id(target[j])] = c;
30792                     }
30793                 } else{
30794                     this.targets[Ext.id(target)] = c;
30795                 }
30796             }
30797         }
30798     },
30799
30800     
30801     unregister : function(el){
30802         delete this.targets[Ext.id(el)];
30803     },
30804     
30805     
30806     cancelShow: function(el){
30807         var at = this.activeTarget;
30808         el = Ext.get(el).dom;
30809         if(this.isVisible()){
30810             if(at && at.el == el){
30811                 this.hide();
30812             }
30813         }else if(at && at.el == el){
30814             this.clearTimer('show');
30815         }
30816     },
30817     
30818     getTipCfg: function(e) {
30819         var t = e.getTarget(), 
30820             ttp, 
30821             cfg;
30822         if(this.interceptTitles && t.title && Ext.isString(t.title)){
30823             ttp = t.title;
30824             t.qtip = ttp;
30825             t.removeAttribute("title");
30826             e.preventDefault();
30827         }else{
30828             cfg = this.tagConfig;
30829             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
30830         }
30831         return ttp;
30832     },
30833
30834     
30835     onTargetOver : function(e){
30836         if(this.disabled){
30837             return;
30838         }
30839         this.targetXY = e.getXY();
30840         var t = e.getTarget();
30841         if(!t || t.nodeType !== 1 || t == document || t == document.body){
30842             return;
30843         }
30844         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
30845             this.clearTimer('hide');
30846             this.show();
30847             return;
30848         }
30849         if(t && this.targets[t.id]){
30850             this.activeTarget = this.targets[t.id];
30851             this.activeTarget.el = t;
30852             this.anchor = this.activeTarget.anchor;
30853             if(this.anchor){
30854                 this.anchorTarget = t;
30855             }
30856             this.delayShow();
30857             return;
30858         }
30859         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
30860         if(ttp = this.getTipCfg(e)){
30861             var autoHide = et.getAttribute(cfg.hide, ns);
30862             this.activeTarget = {
30863                 el: t,
30864                 text: ttp,
30865                 width: et.getAttribute(cfg.width, ns),
30866                 autoHide: autoHide != "user" && autoHide !== 'false',
30867                 title: et.getAttribute(cfg.title, ns),
30868                 cls: et.getAttribute(cfg.cls, ns),
30869                 align: et.getAttribute(cfg.align, ns)
30870                 
30871             };
30872             this.anchor = et.getAttribute(cfg.anchor, ns);
30873             if(this.anchor){
30874                 this.anchorTarget = t;
30875             }
30876             this.delayShow();
30877         }
30878     },
30879
30880     
30881     onTargetOut : function(e){
30882
30883         
30884         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
30885             return;
30886         }
30887
30888         this.clearTimer('show');
30889         if(this.autoHide !== false){
30890             this.delayHide();
30891         }
30892     },
30893
30894     
30895     showAt : function(xy){
30896         var t = this.activeTarget;
30897         if(t){
30898             if(!this.rendered){
30899                 this.render(Ext.getBody());
30900                 this.activeTarget = t;
30901             }
30902             if(t.width){
30903                 this.setWidth(t.width);
30904                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
30905                 this.measureWidth = false;
30906             } else{
30907                 this.measureWidth = true;
30908             }
30909             this.setTitle(t.title || '');
30910             this.body.update(t.text);
30911             this.autoHide = t.autoHide;
30912             this.dismissDelay = t.dismissDelay || this.dismissDelay;
30913             if(this.lastCls){
30914                 this.el.removeClass(this.lastCls);
30915                 delete this.lastCls;
30916             }
30917             if(t.cls){
30918                 this.el.addClass(t.cls);
30919                 this.lastCls = t.cls;
30920             }
30921             if(this.anchor){
30922                 this.constrainPosition = false;
30923             }else if(t.align){ 
30924                 xy = this.el.getAlignToXY(t.el, t.align);
30925                 this.constrainPosition = false;
30926             }else{
30927                 this.constrainPosition = true;
30928             }
30929         }
30930         Ext.QuickTip.superclass.showAt.call(this, xy);
30931     },
30932
30933     
30934     hide: function(){
30935         delete this.activeTarget;
30936         Ext.QuickTip.superclass.hide.call(this);
30937     }
30938 });
30939 Ext.reg('quicktip', Ext.QuickTip);
30940 Ext.QuickTips = function(){
30941     var tip, locks = [];
30942     return {
30943         
30944         init : function(autoRender){
30945             if(!tip){
30946                 if(!Ext.isReady){
30947                     Ext.onReady(function(){
30948                         Ext.QuickTips.init(autoRender);
30949                     });
30950                     return;
30951                 }
30952                 tip = new Ext.QuickTip({elements:'header,body'});
30953                 if(autoRender !== false){
30954                     tip.render(Ext.getBody());
30955                 }
30956             }
30957         },
30958
30959         
30960         enable : function(){
30961             if(tip){
30962                 locks.pop();
30963                 if(locks.length < 1){
30964                     tip.enable();
30965                 }
30966             }
30967         },
30968
30969         
30970         disable : function(){
30971             if(tip){
30972                 tip.disable();
30973             }
30974             locks.push(1);
30975         },
30976
30977         
30978         isEnabled : function(){
30979             return tip !== undefined && !tip.disabled;
30980         },
30981
30982         
30983         getQuickTip : function(){
30984             return tip;
30985         },
30986
30987         
30988         register : function(){
30989             tip.register.apply(tip, arguments);
30990         },
30991
30992         
30993         unregister : function(){
30994             tip.unregister.apply(tip, arguments);
30995         },
30996
30997         
30998         tips :function(){
30999             tip.register.apply(tip, arguments);
31000         }
31001     }
31002 }();
31003 Ext.slider.Tip = Ext.extend(Ext.Tip, {
31004     minWidth: 10,
31005     offsets : [0, -10],
31006     
31007     init: function(slider) {
31008         slider.on({
31009             scope    : this,
31010             dragstart: this.onSlide,
31011             drag     : this.onSlide,
31012             dragend  : this.hide,
31013             destroy  : this.destroy
31014         });
31015     },
31016     
31017     
31018     onSlide : function(slider, e, thumb) {
31019         this.show();
31020         this.body.update(this.getText(thumb));
31021         this.doAutoWidth();
31022         this.el.alignTo(thumb.el, 'b-t?', this.offsets);
31023     },
31024
31025     
31026     getText : function(thumb) {
31027         return String(thumb.value);
31028     }
31029 });
31030
31031
31032 Ext.ux.SliderTip = Ext.slider.Tip;
31033 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
31034     rootVisible : true,
31035     animate : Ext.enableFx,
31036     lines : true,
31037     enableDD : false,
31038     hlDrop : Ext.enableFx,
31039     pathSeparator : '/',
31040
31041     
31042     bubbleEvents : [],
31043
31044     initComponent : function(){
31045         Ext.tree.TreePanel.superclass.initComponent.call(this);
31046
31047         if(!this.eventModel){
31048             this.eventModel = new Ext.tree.TreeEventModel(this);
31049         }
31050
31051         
31052         var l = this.loader;
31053         if(!l){
31054             l = new Ext.tree.TreeLoader({
31055                 dataUrl: this.dataUrl,
31056                 requestMethod: this.requestMethod
31057             });
31058         }else if(Ext.isObject(l) && !l.load){
31059             l = new Ext.tree.TreeLoader(l);
31060         }
31061         this.loader = l;
31062
31063         this.nodeHash = {};
31064
31065         
31066         if(this.root){
31067             var r = this.root;
31068             delete this.root;
31069             this.setRootNode(r);
31070         }
31071
31072
31073         this.addEvents(
31074
31075             
31076            'append',
31077            
31078            'remove',
31079            
31080            'movenode',
31081            
31082            'insert',
31083            
31084            'beforeappend',
31085            
31086            'beforeremove',
31087            
31088            'beforemovenode',
31089            
31090             'beforeinsert',
31091
31092             
31093             'beforeload',
31094             
31095             'load',
31096             
31097             'textchange',
31098             
31099             'beforeexpandnode',
31100             
31101             'beforecollapsenode',
31102             
31103             'expandnode',
31104             
31105             'disabledchange',
31106             
31107             'collapsenode',
31108             
31109             'beforeclick',
31110             
31111             'click',
31112             
31113             'containerclick',
31114             
31115             'checkchange',
31116             
31117             'beforedblclick',
31118             
31119             'dblclick',
31120             
31121             'containerdblclick',
31122             
31123             'contextmenu',
31124             
31125             'containercontextmenu',
31126             
31127             'beforechildrenrendered',
31128            
31129             'startdrag',
31130             
31131             'enddrag',
31132             
31133             'dragdrop',
31134             
31135             'beforenodedrop',
31136             
31137             'nodedrop',
31138              
31139             'nodedragover'
31140         );
31141         if(this.singleExpand){
31142             this.on('beforeexpandnode', this.restrictExpand, this);
31143         }
31144     },
31145
31146     
31147     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
31148         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
31149             ename = ename+'node';
31150         }
31151         
31152         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
31153     },
31154
31155
31156     
31157     getRootNode : function(){
31158         return this.root;
31159     },
31160
31161     
31162     setRootNode : function(node){
31163         this.destroyRoot();
31164         if(!node.render){ 
31165             node = this.loader.createNode(node);
31166         }
31167         this.root = node;
31168         node.ownerTree = this;
31169         node.isRoot = true;
31170         this.registerNode(node);
31171         if(!this.rootVisible){
31172             var uiP = node.attributes.uiProvider;
31173             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
31174         }
31175         if(this.innerCt){
31176             this.clearInnerCt();
31177             this.renderRoot();
31178         }
31179         return node;
31180     },
31181     
31182     clearInnerCt : function(){
31183         this.innerCt.update('');    
31184     },
31185     
31186     
31187     renderRoot : function(){
31188         this.root.render();
31189         if(!this.rootVisible){
31190             this.root.renderChildren();
31191         }
31192     },
31193
31194     
31195     getNodeById : function(id){
31196         return this.nodeHash[id];
31197     },
31198
31199     
31200     registerNode : function(node){
31201         this.nodeHash[node.id] = node;
31202     },
31203
31204     
31205     unregisterNode : function(node){
31206         delete this.nodeHash[node.id];
31207     },
31208
31209     
31210     toString : function(){
31211         return '[Tree'+(this.id?' '+this.id:'')+']';
31212     },
31213
31214     
31215     restrictExpand : function(node){
31216         var p = node.parentNode;
31217         if(p){
31218             if(p.expandedChild && p.expandedChild.parentNode == p){
31219                 p.expandedChild.collapse();
31220             }
31221             p.expandedChild = node;
31222         }
31223     },
31224
31225     
31226     getChecked : function(a, startNode){
31227         startNode = startNode || this.root;
31228         var r = [];
31229         var f = function(){
31230             if(this.attributes.checked){
31231                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
31232             }
31233         };
31234         startNode.cascade(f);
31235         return r;
31236     },
31237
31238     
31239     getLoader : function(){
31240         return this.loader;
31241     },
31242
31243     
31244     expandAll : function(){
31245         this.root.expand(true);
31246     },
31247
31248     
31249     collapseAll : function(){
31250         this.root.collapse(true);
31251     },
31252
31253     
31254     getSelectionModel : function(){
31255         if(!this.selModel){
31256             this.selModel = new Ext.tree.DefaultSelectionModel();
31257         }
31258         return this.selModel;
31259     },
31260
31261     
31262     expandPath : function(path, attr, callback){
31263         attr = attr || 'id';
31264         var keys = path.split(this.pathSeparator);
31265         var curNode = this.root;
31266         if(curNode.attributes[attr] != keys[1]){ 
31267             if(callback){
31268                 callback(false, null);
31269             }
31270             return;
31271         }
31272         var index = 1;
31273         var f = function(){
31274             if(++index == keys.length){
31275                 if(callback){
31276                     callback(true, curNode);
31277                 }
31278                 return;
31279             }
31280             var c = curNode.findChild(attr, keys[index]);
31281             if(!c){
31282                 if(callback){
31283                     callback(false, curNode);
31284                 }
31285                 return;
31286             }
31287             curNode = c;
31288             c.expand(false, false, f);
31289         };
31290         curNode.expand(false, false, f);
31291     },
31292
31293     
31294     selectPath : function(path, attr, callback){
31295         attr = attr || 'id';
31296         var keys = path.split(this.pathSeparator),
31297             v = keys.pop();
31298         if(keys.length > 1){
31299             var f = function(success, node){
31300                 if(success && node){
31301                     var n = node.findChild(attr, v);
31302                     if(n){
31303                         n.select();
31304                         if(callback){
31305                             callback(true, n);
31306                         }
31307                     }else if(callback){
31308                         callback(false, n);
31309                     }
31310                 }else{
31311                     if(callback){
31312                         callback(false, n);
31313                     }
31314                 }
31315             };
31316             this.expandPath(keys.join(this.pathSeparator), attr, f);
31317         }else{
31318             this.root.select();
31319             if(callback){
31320                 callback(true, this.root);
31321             }
31322         }
31323     },
31324
31325     
31326     getTreeEl : function(){
31327         return this.body;
31328     },
31329
31330     
31331     onRender : function(ct, position){
31332         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
31333         this.el.addClass('x-tree');
31334         this.innerCt = this.body.createChild({tag:'ul',
31335                cls:'x-tree-root-ct ' +
31336                (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
31337     },
31338
31339     
31340     initEvents : function(){
31341         Ext.tree.TreePanel.superclass.initEvents.call(this);
31342
31343         if(this.containerScroll){
31344             Ext.dd.ScrollManager.register(this.body);
31345         }
31346         if((this.enableDD || this.enableDrop) && !this.dropZone){
31347            
31348              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
31349                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
31350            });
31351         }
31352         if((this.enableDD || this.enableDrag) && !this.dragZone){
31353            
31354             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
31355                ddGroup: this.ddGroup || 'TreeDD',
31356                scroll: this.ddScroll
31357            });
31358         }
31359         this.getSelectionModel().init(this);
31360     },
31361
31362     
31363     afterRender : function(){
31364         Ext.tree.TreePanel.superclass.afterRender.call(this);
31365         this.renderRoot();
31366     },
31367
31368     beforeDestroy : function(){
31369         if(this.rendered){
31370             Ext.dd.ScrollManager.unregister(this.body);
31371             Ext.destroy(this.dropZone, this.dragZone);
31372         }
31373         this.destroyRoot();
31374         Ext.destroy(this.loader);
31375         this.nodeHash = this.root = this.loader = null;
31376         Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
31377     },
31378     
31379     
31380     destroyRoot : function(){
31381         if(this.root && this.root.destroy){
31382             this.root.destroy(true);
31383         }
31384     }
31385
31386     
31387     
31388     
31389     
31390     
31391     
31392     
31393     
31394     
31395     
31396     
31397     
31398     
31399     
31400     
31401     
31402     
31403     
31404     
31405     
31406     
31407     
31408     
31409     
31410     
31411     
31412     
31413     
31414     
31415     
31416     
31417
31418
31419
31420     
31421     
31422     
31423     
31424     
31425     
31426     
31427     
31428     
31429     
31430     
31431     
31432     
31433     
31434     
31435     
31436 });
31437
31438 Ext.tree.TreePanel.nodeTypes = {};
31439
31440 Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
31441     this.tree = tree;
31442     this.tree.on('render', this.initEvents, this);
31443 };
31444
31445 Ext.tree.TreeEventModel.prototype = {
31446     initEvents : function(){
31447         var t = this.tree;
31448
31449         if(t.trackMouseOver !== false){
31450             t.mon(t.innerCt, {
31451                 scope: this,
31452                 mouseover: this.delegateOver,
31453                 mouseout: this.delegateOut
31454             });
31455         }
31456         t.mon(t.getTreeEl(), {
31457             scope: this,
31458             click: this.delegateClick,
31459             dblclick: this.delegateDblClick,
31460             contextmenu: this.delegateContextMenu
31461         });
31462     },
31463
31464     getNode : function(e){
31465         var t;
31466         if(t = e.getTarget('.x-tree-node-el', 10)){
31467             var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
31468             if(id){
31469                 return this.tree.getNodeById(id);
31470             }
31471         }
31472         return null;
31473     },
31474
31475     getNodeTarget : function(e){
31476         var t = e.getTarget('.x-tree-node-icon', 1);
31477         if(!t){
31478             t = e.getTarget('.x-tree-node-el', 6);
31479         }
31480         return t;
31481     },
31482
31483     delegateOut : function(e, t){
31484         if(!this.beforeEvent(e)){
31485             return;
31486         }
31487         if(e.getTarget('.x-tree-ec-icon', 1)){
31488             var n = this.getNode(e);
31489             this.onIconOut(e, n);
31490             if(n == this.lastEcOver){
31491                 delete this.lastEcOver;
31492             }
31493         }
31494         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
31495             this.onNodeOut(e, this.getNode(e));
31496         }
31497     },
31498
31499     delegateOver : function(e, t){
31500         if(!this.beforeEvent(e)){
31501             return;
31502         }
31503         if(Ext.isGecko && !this.trackingDoc){ 
31504             Ext.getBody().on('mouseover', this.trackExit, this);
31505             this.trackingDoc = true;
31506         }
31507         if(this.lastEcOver){ 
31508             this.onIconOut(e, this.lastEcOver);
31509             delete this.lastEcOver;
31510         }
31511         if(e.getTarget('.x-tree-ec-icon', 1)){
31512             this.lastEcOver = this.getNode(e);
31513             this.onIconOver(e, this.lastEcOver);
31514         }
31515         if(t = this.getNodeTarget(e)){
31516             this.onNodeOver(e, this.getNode(e));
31517         }
31518     },
31519
31520     trackExit : function(e){
31521         if(this.lastOverNode){
31522             if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
31523                 this.onNodeOut(e, this.lastOverNode);
31524             }
31525             delete this.lastOverNode;
31526             Ext.getBody().un('mouseover', this.trackExit, this);
31527             this.trackingDoc = false;
31528         }
31529
31530     },
31531
31532     delegateClick : function(e, t){
31533         if(this.beforeEvent(e)){
31534             if(e.getTarget('input[type=checkbox]', 1)){
31535                 this.onCheckboxClick(e, this.getNode(e));
31536             }else if(e.getTarget('.x-tree-ec-icon', 1)){
31537                 this.onIconClick(e, this.getNode(e));
31538             }else if(this.getNodeTarget(e)){
31539                 this.onNodeClick(e, this.getNode(e));
31540             }
31541         }else{
31542             this.checkContainerEvent(e, 'click');
31543         }
31544     },
31545
31546     delegateDblClick : function(e, t){
31547         if(this.beforeEvent(e)){
31548             if(this.getNodeTarget(e)){
31549                 this.onNodeDblClick(e, this.getNode(e));
31550             }
31551         }else{
31552             this.checkContainerEvent(e, 'dblclick');
31553         }
31554     },
31555
31556     delegateContextMenu : function(e, t){
31557         if(this.beforeEvent(e)){
31558             if(this.getNodeTarget(e)){
31559                 this.onNodeContextMenu(e, this.getNode(e));
31560             }
31561         }else{
31562             this.checkContainerEvent(e, 'contextmenu');
31563         }
31564     },
31565     
31566     checkContainerEvent: function(e, type){
31567         if(this.disabled){
31568             e.stopEvent();
31569             return false;
31570         }
31571         this.onContainerEvent(e, type);    
31572     },
31573
31574     onContainerEvent: function(e, type){
31575         this.tree.fireEvent('container' + type, this.tree, e);
31576     },
31577
31578     onNodeClick : function(e, node){
31579         node.ui.onClick(e);
31580     },
31581
31582     onNodeOver : function(e, node){
31583         this.lastOverNode = node;
31584         node.ui.onOver(e);
31585     },
31586
31587     onNodeOut : function(e, node){
31588         node.ui.onOut(e);
31589     },
31590
31591     onIconOver : function(e, node){
31592         node.ui.addClass('x-tree-ec-over');
31593     },
31594
31595     onIconOut : function(e, node){
31596         node.ui.removeClass('x-tree-ec-over');
31597     },
31598
31599     onIconClick : function(e, node){
31600         node.ui.ecClick(e);
31601     },
31602
31603     onCheckboxClick : function(e, node){
31604         node.ui.onCheckChange(e);
31605     },
31606
31607     onNodeDblClick : function(e, node){
31608         node.ui.onDblClick(e);
31609     },
31610
31611     onNodeContextMenu : function(e, node){
31612         node.ui.onContextMenu(e);
31613     },
31614
31615     beforeEvent : function(e){
31616         var node = this.getNode(e);
31617         if(this.disabled || !node || !node.ui){
31618             e.stopEvent();
31619             return false;
31620         }
31621         return true;
31622     },
31623
31624     disable: function(){
31625         this.disabled = true;
31626     },
31627
31628     enable: function(){
31629         this.disabled = false;
31630     }
31631 };
31632 Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
31633     
31634     constructor : function(config){
31635         this.selNode = null;
31636    
31637         this.addEvents(
31638             
31639             'selectionchange',
31640
31641             
31642             'beforeselect'
31643         );
31644
31645         Ext.apply(this, config);
31646         Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
31647     },
31648     
31649     init : function(tree){
31650         this.tree = tree;
31651         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
31652         tree.on('click', this.onNodeClick, this);
31653     },
31654     
31655     onNodeClick : function(node, e){
31656         this.select(node);
31657     },
31658     
31659     
31660     select : function(node,  selectNextNode){
31661         
31662         if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
31663             return selectNextNode.call(this, node);
31664         }
31665         var last = this.selNode;
31666         if(node == last){
31667             node.ui.onSelectedChange(true);
31668         }else if(this.fireEvent('beforeselect', this, node, last) !== false){
31669             if(last && last.ui){
31670                 last.ui.onSelectedChange(false);
31671             }
31672             this.selNode = node;
31673             node.ui.onSelectedChange(true);
31674             this.fireEvent('selectionchange', this, node, last);
31675         }
31676         return node;
31677     },
31678     
31679     
31680     unselect : function(node, silent){
31681         if(this.selNode == node){
31682             this.clearSelections(silent);
31683         }    
31684     },
31685     
31686     
31687     clearSelections : function(silent){
31688         var n = this.selNode;
31689         if(n){
31690             n.ui.onSelectedChange(false);
31691             this.selNode = null;
31692             if(silent !== true){
31693                 this.fireEvent('selectionchange', this, null);
31694             }
31695         }
31696         return n;
31697     },
31698     
31699     
31700     getSelectedNode : function(){
31701         return this.selNode;    
31702     },
31703     
31704     
31705     isSelected : function(node){
31706         return this.selNode == node;  
31707     },
31708
31709     
31710     selectPrevious : function( s){
31711         if(!(s = s || this.selNode || this.lastSelNode)){
31712             return null;
31713         }
31714         
31715         var ps = s.previousSibling;
31716         if(ps){
31717             if(!ps.isExpanded() || ps.childNodes.length < 1){
31718                 return this.select(ps, this.selectPrevious);
31719             } else{
31720                 var lc = ps.lastChild;
31721                 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
31722                     lc = lc.lastChild;
31723                 }
31724                 return this.select(lc, this.selectPrevious);
31725             }
31726         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
31727             return this.select(s.parentNode, this.selectPrevious);
31728         }
31729         return null;
31730     },
31731
31732     
31733     selectNext : function( s){
31734         if(!(s = s || this.selNode || this.lastSelNode)){
31735             return null;
31736         }
31737         
31738         if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
31739              return this.select(s.firstChild, this.selectNext);
31740          }else if(s.nextSibling){
31741              return this.select(s.nextSibling, this.selectNext);
31742          }else if(s.parentNode){
31743             var newS = null;
31744             s.parentNode.bubble(function(){
31745                 if(this.nextSibling){
31746                     newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
31747                     return false;
31748                 }
31749             });
31750             return newS;
31751          }
31752         return null;
31753     },
31754
31755     onKeyDown : function(e){
31756         var s = this.selNode || this.lastSelNode;
31757         
31758         var sm = this;
31759         if(!s){
31760             return;
31761         }
31762         var k = e.getKey();
31763         switch(k){
31764              case e.DOWN:
31765                  e.stopEvent();
31766                  this.selectNext();
31767              break;
31768              case e.UP:
31769                  e.stopEvent();
31770                  this.selectPrevious();
31771              break;
31772              case e.RIGHT:
31773                  e.preventDefault();
31774                  if(s.hasChildNodes()){
31775                      if(!s.isExpanded()){
31776                          s.expand();
31777                      }else if(s.firstChild){
31778                          this.select(s.firstChild, e);
31779                      }
31780                  }
31781              break;
31782              case e.LEFT:
31783                  e.preventDefault();
31784                  if(s.hasChildNodes() && s.isExpanded()){
31785                      s.collapse();
31786                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
31787                      this.select(s.parentNode, e);
31788                  }
31789              break;
31790         };
31791     }
31792 });
31793
31794
31795 Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
31796     
31797     constructor : function(config){
31798         this.selNodes = [];
31799         this.selMap = {};
31800         this.addEvents(
31801             
31802             'selectionchange'
31803         );
31804         Ext.apply(this, config);
31805         Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
31806     },
31807     
31808     init : function(tree){
31809         this.tree = tree;
31810         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
31811         tree.on('click', this.onNodeClick, this);
31812     },
31813     
31814     onNodeClick : function(node, e){
31815         if(e.ctrlKey && this.isSelected(node)){
31816             this.unselect(node);
31817         }else{
31818             this.select(node, e, e.ctrlKey);
31819         }
31820     },
31821     
31822     
31823     select : function(node, e, keepExisting){
31824         if(keepExisting !== true){
31825             this.clearSelections(true);
31826         }
31827         if(this.isSelected(node)){
31828             this.lastSelNode = node;
31829             return node;
31830         }
31831         this.selNodes.push(node);
31832         this.selMap[node.id] = node;
31833         this.lastSelNode = node;
31834         node.ui.onSelectedChange(true);
31835         this.fireEvent('selectionchange', this, this.selNodes);
31836         return node;
31837     },
31838     
31839     
31840     unselect : function(node){
31841         if(this.selMap[node.id]){
31842             node.ui.onSelectedChange(false);
31843             var sn = this.selNodes;
31844             var index = sn.indexOf(node);
31845             if(index != -1){
31846                 this.selNodes.splice(index, 1);
31847             }
31848             delete this.selMap[node.id];
31849             this.fireEvent('selectionchange', this, this.selNodes);
31850         }
31851     },
31852     
31853     
31854     clearSelections : function(suppressEvent){
31855         var sn = this.selNodes;
31856         if(sn.length > 0){
31857             for(var i = 0, len = sn.length; i < len; i++){
31858                 sn[i].ui.onSelectedChange(false);
31859             }
31860             this.selNodes = [];
31861             this.selMap = {};
31862             if(suppressEvent !== true){
31863                 this.fireEvent('selectionchange', this, this.selNodes);
31864             }
31865         }
31866     },
31867     
31868     
31869     isSelected : function(node){
31870         return this.selMap[node.id] ? true : false;  
31871     },
31872     
31873     
31874     getSelectedNodes : function(){
31875         return this.selNodes.concat([]);
31876     },
31877
31878     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
31879
31880     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
31881
31882     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
31883 });
31884 Ext.data.Tree = function(root){
31885    this.nodeHash = {};
31886    
31887    this.root = null;
31888    if(root){
31889        this.setRootNode(root);
31890    }
31891    this.addEvents(
31892        
31893        "append",
31894        
31895        "remove",
31896        
31897        "move",
31898        
31899        "insert",
31900        
31901        "beforeappend",
31902        
31903        "beforeremove",
31904        
31905        "beforemove",
31906        
31907        "beforeinsert"
31908    );
31909
31910     Ext.data.Tree.superclass.constructor.call(this);
31911 };
31912
31913 Ext.extend(Ext.data.Tree, Ext.util.Observable, {
31914     
31915     pathSeparator: "/",
31916
31917     
31918     proxyNodeEvent : function(){
31919         return this.fireEvent.apply(this, arguments);
31920     },
31921
31922     
31923     getRootNode : function(){
31924         return this.root;
31925     },
31926
31927     
31928     setRootNode : function(node){
31929         this.root = node;
31930         node.ownerTree = this;
31931         node.isRoot = true;
31932         this.registerNode(node);
31933         return node;
31934     },
31935
31936     
31937     getNodeById : function(id){
31938         return this.nodeHash[id];
31939     },
31940
31941     
31942     registerNode : function(node){
31943         this.nodeHash[node.id] = node;
31944     },
31945
31946     
31947     unregisterNode : function(node){
31948         delete this.nodeHash[node.id];
31949     },
31950
31951     toString : function(){
31952         return "[Tree"+(this.id?" "+this.id:"")+"]";
31953     }
31954 });
31955
31956
31957 Ext.data.Node = function(attributes){
31958     
31959     this.attributes = attributes || {};
31960     this.leaf = this.attributes.leaf;
31961     
31962     this.id = this.attributes.id;
31963     if(!this.id){
31964         this.id = Ext.id(null, "xnode-");
31965         this.attributes.id = this.id;
31966     }
31967     
31968     this.childNodes = [];
31969     if(!this.childNodes.indexOf){ 
31970         this.childNodes.indexOf = function(o){
31971             for(var i = 0, len = this.length; i < len; i++){
31972                 if(this[i] == o){
31973                     return i;
31974                 }
31975             }
31976             return -1;
31977         };
31978     }
31979     
31980     this.parentNode = null;
31981     
31982     this.firstChild = null;
31983     
31984     this.lastChild = null;
31985     
31986     this.previousSibling = null;
31987     
31988     this.nextSibling = null;
31989
31990     this.addEvents({
31991        
31992        "append" : true,
31993        
31994        "remove" : true,
31995        
31996        "move" : true,
31997        
31998        "insert" : true,
31999        
32000        "beforeappend" : true,
32001        
32002        "beforeremove" : true,
32003        
32004        "beforemove" : true,
32005        
32006        "beforeinsert" : true
32007    });
32008     this.listeners = this.attributes.listeners;
32009     Ext.data.Node.superclass.constructor.call(this);
32010 };
32011
32012 Ext.extend(Ext.data.Node, Ext.util.Observable, {
32013     
32014     fireEvent : function(evtName){
32015         
32016         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
32017             return false;
32018         }
32019         
32020         var ot = this.getOwnerTree();
32021         if(ot){
32022             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
32023                 return false;
32024             }
32025         }
32026         return true;
32027     },
32028
32029     
32030     isLeaf : function(){
32031         return this.leaf === true;
32032     },
32033
32034     
32035     setFirstChild : function(node){
32036         this.firstChild = node;
32037     },
32038
32039     
32040     setLastChild : function(node){
32041         this.lastChild = node;
32042     },
32043
32044
32045     
32046     isLast : function(){
32047        return (!this.parentNode ? true : this.parentNode.lastChild == this);
32048     },
32049
32050     
32051     isFirst : function(){
32052        return (!this.parentNode ? true : this.parentNode.firstChild == this);
32053     },
32054
32055     
32056     hasChildNodes : function(){
32057         return !this.isLeaf() && this.childNodes.length > 0;
32058     },
32059
32060     
32061     isExpandable : function(){
32062         return this.attributes.expandable || this.hasChildNodes();
32063     },
32064
32065     
32066     appendChild : function(node){
32067         var multi = false;
32068         if(Ext.isArray(node)){
32069             multi = node;
32070         }else if(arguments.length > 1){
32071             multi = arguments;
32072         }
32073         
32074         if(multi){
32075             for(var i = 0, len = multi.length; i < len; i++) {
32076                 this.appendChild(multi[i]);
32077             }
32078         }else{
32079             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
32080                 return false;
32081             }
32082             var index = this.childNodes.length;
32083             var oldParent = node.parentNode;
32084             
32085             if(oldParent){
32086                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
32087                     return false;
32088                 }
32089                 oldParent.removeChild(node);
32090             }
32091             index = this.childNodes.length;
32092             if(index === 0){
32093                 this.setFirstChild(node);
32094             }
32095             this.childNodes.push(node);
32096             node.parentNode = this;
32097             var ps = this.childNodes[index-1];
32098             if(ps){
32099                 node.previousSibling = ps;
32100                 ps.nextSibling = node;
32101             }else{
32102                 node.previousSibling = null;
32103             }
32104             node.nextSibling = null;
32105             this.setLastChild(node);
32106             node.setOwnerTree(this.getOwnerTree());
32107             this.fireEvent("append", this.ownerTree, this, node, index);
32108             if(oldParent){
32109                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
32110             }
32111             return node;
32112         }
32113     },
32114
32115     
32116     removeChild : function(node, destroy){
32117         var index = this.childNodes.indexOf(node);
32118         if(index == -1){
32119             return false;
32120         }
32121         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
32122             return false;
32123         }
32124
32125         
32126         this.childNodes.splice(index, 1);
32127
32128         
32129         if(node.previousSibling){
32130             node.previousSibling.nextSibling = node.nextSibling;
32131         }
32132         if(node.nextSibling){
32133             node.nextSibling.previousSibling = node.previousSibling;
32134         }
32135
32136         
32137         if(this.firstChild == node){
32138             this.setFirstChild(node.nextSibling);
32139         }
32140         if(this.lastChild == node){
32141             this.setLastChild(node.previousSibling);
32142         }
32143
32144         this.fireEvent("remove", this.ownerTree, this, node);
32145         if(destroy){
32146             node.destroy(true);
32147         }else{
32148             node.clear();
32149         }
32150         return node;
32151     },
32152
32153     
32154     clear : function(destroy){
32155         
32156         this.setOwnerTree(null, destroy);
32157         this.parentNode = this.previousSibling = this.nextSibling = null;
32158         if(destroy){
32159             this.firstChild = this.lastChild = null;
32160         }
32161     },
32162
32163     
32164     destroy : function( silent){
32165         
32166         if(silent === true){
32167             this.purgeListeners();
32168             this.clear(true);
32169             Ext.each(this.childNodes, function(n){
32170                 n.destroy(true);
32171             });
32172             this.childNodes = null;
32173         }else{
32174             this.remove(true);
32175         }
32176     },
32177
32178     
32179     insertBefore : function(node, refNode){
32180         if(!refNode){ 
32181             return this.appendChild(node);
32182         }
32183         
32184         if(node == refNode){
32185             return false;
32186         }
32187
32188         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
32189             return false;
32190         }
32191         var index = this.childNodes.indexOf(refNode);
32192         var oldParent = node.parentNode;
32193         var refIndex = index;
32194
32195         
32196         if(oldParent == this && this.childNodes.indexOf(node) < index){
32197             refIndex--;
32198         }
32199
32200         
32201         if(oldParent){
32202             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
32203                 return false;
32204             }
32205             oldParent.removeChild(node);
32206         }
32207         if(refIndex === 0){
32208             this.setFirstChild(node);
32209         }
32210         this.childNodes.splice(refIndex, 0, node);
32211         node.parentNode = this;
32212         var ps = this.childNodes[refIndex-1];
32213         if(ps){
32214             node.previousSibling = ps;
32215             ps.nextSibling = node;
32216         }else{
32217             node.previousSibling = null;
32218         }
32219         node.nextSibling = refNode;
32220         refNode.previousSibling = node;
32221         node.setOwnerTree(this.getOwnerTree());
32222         this.fireEvent("insert", this.ownerTree, this, node, refNode);
32223         if(oldParent){
32224             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
32225         }
32226         return node;
32227     },
32228
32229     
32230     remove : function(destroy){
32231         if (this.parentNode) {
32232             this.parentNode.removeChild(this, destroy);
32233         }
32234         return this;
32235     },
32236
32237     
32238     removeAll : function(destroy){
32239         var cn = this.childNodes,
32240             n;
32241         while((n = cn[0])){
32242             this.removeChild(n, destroy);
32243         }
32244         return this;
32245     },
32246
32247     
32248     item : function(index){
32249         return this.childNodes[index];
32250     },
32251
32252     
32253     replaceChild : function(newChild, oldChild){
32254         var s = oldChild ? oldChild.nextSibling : null;
32255         this.removeChild(oldChild);
32256         this.insertBefore(newChild, s);
32257         return oldChild;
32258     },
32259
32260     
32261     indexOf : function(child){
32262         return this.childNodes.indexOf(child);
32263     },
32264
32265     
32266     getOwnerTree : function(){
32267         
32268         if(!this.ownerTree){
32269             var p = this;
32270             while(p){
32271                 if(p.ownerTree){
32272                     this.ownerTree = p.ownerTree;
32273                     break;
32274                 }
32275                 p = p.parentNode;
32276             }
32277         }
32278         return this.ownerTree;
32279     },
32280
32281     
32282     getDepth : function(){
32283         var depth = 0;
32284         var p = this;
32285         while(p.parentNode){
32286             ++depth;
32287             p = p.parentNode;
32288         }
32289         return depth;
32290     },
32291
32292     
32293     setOwnerTree : function(tree, destroy){
32294         
32295         if(tree != this.ownerTree){
32296             if(this.ownerTree){
32297                 this.ownerTree.unregisterNode(this);
32298             }
32299             this.ownerTree = tree;
32300             
32301             if(destroy !== true){
32302                 Ext.each(this.childNodes, function(n){
32303                     n.setOwnerTree(tree);
32304                 });
32305             }
32306             if(tree){
32307                 tree.registerNode(this);
32308             }
32309         }
32310     },
32311
32312     
32313     setId: function(id){
32314         if(id !== this.id){
32315             var t = this.ownerTree;
32316             if(t){
32317                 t.unregisterNode(this);
32318             }
32319             this.id = this.attributes.id = id;
32320             if(t){
32321                 t.registerNode(this);
32322             }
32323             this.onIdChange(id);
32324         }
32325     },
32326
32327     
32328     onIdChange: Ext.emptyFn,
32329
32330     
32331     getPath : function(attr){
32332         attr = attr || "id";
32333         var p = this.parentNode;
32334         var b = [this.attributes[attr]];
32335         while(p){
32336             b.unshift(p.attributes[attr]);
32337             p = p.parentNode;
32338         }
32339         var sep = this.getOwnerTree().pathSeparator;
32340         return sep + b.join(sep);
32341     },
32342
32343     
32344     bubble : function(fn, scope, args){
32345         var p = this;
32346         while(p){
32347             if(fn.apply(scope || p, args || [p]) === false){
32348                 break;
32349             }
32350             p = p.parentNode;
32351         }
32352     },
32353
32354     
32355     cascade : function(fn, scope, args){
32356         if(fn.apply(scope || this, args || [this]) !== false){
32357             var cs = this.childNodes;
32358             for(var i = 0, len = cs.length; i < len; i++) {
32359                 cs[i].cascade(fn, scope, args);
32360             }
32361         }
32362     },
32363
32364     
32365     eachChild : function(fn, scope, args){
32366         var cs = this.childNodes;
32367         for(var i = 0, len = cs.length; i < len; i++) {
32368             if(fn.apply(scope || this, args || [cs[i]]) === false){
32369                 break;
32370             }
32371         }
32372     },
32373
32374     
32375     findChild : function(attribute, value, deep){
32376         return this.findChildBy(function(){
32377             return this.attributes[attribute] == value;
32378         }, null, deep);
32379     },
32380
32381     
32382     findChildBy : function(fn, scope, deep){
32383         var cs = this.childNodes,
32384             len = cs.length,
32385             i = 0,
32386             n,
32387             res;
32388         for(; i < len; i++){
32389             n = cs[i];
32390             if(fn.call(scope || n, n) === true){
32391                 return n;
32392             }else if (deep){
32393                 res = n.findChildBy(fn, scope, deep);
32394                 if(res != null){
32395                     return res;
32396                 }
32397             }
32398             
32399         }
32400         return null;
32401     },
32402
32403     
32404     sort : function(fn, scope){
32405         var cs = this.childNodes;
32406         var len = cs.length;
32407         if(len > 0){
32408             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
32409             cs.sort(sortFn);
32410             for(var i = 0; i < len; i++){
32411                 var n = cs[i];
32412                 n.previousSibling = cs[i-1];
32413                 n.nextSibling = cs[i+1];
32414                 if(i === 0){
32415                     this.setFirstChild(n);
32416                 }
32417                 if(i == len-1){
32418                     this.setLastChild(n);
32419                 }
32420             }
32421         }
32422     },
32423
32424     
32425     contains : function(node){
32426         return node.isAncestor(this);
32427     },
32428
32429     
32430     isAncestor : function(node){
32431         var p = this.parentNode;
32432         while(p){
32433             if(p == node){
32434                 return true;
32435             }
32436             p = p.parentNode;
32437         }
32438         return false;
32439     },
32440
32441     toString : function(){
32442         return "[Node"+(this.id?" "+this.id:"")+"]";
32443     }
32444 });
32445 Ext.tree.TreeNode = function(attributes){
32446     attributes = attributes || {};
32447     if(Ext.isString(attributes)){
32448         attributes = {text: attributes};
32449     }
32450     this.childrenRendered = false;
32451     this.rendered = false;
32452     Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
32453     this.expanded = attributes.expanded === true;
32454     this.isTarget = attributes.isTarget !== false;
32455     this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
32456     this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
32457
32458     
32459     this.text = attributes.text;
32460     
32461     this.disabled = attributes.disabled === true;
32462     
32463     this.hidden = attributes.hidden === true;
32464
32465     this.addEvents(
32466         
32467         'textchange',
32468         
32469         'beforeexpand',
32470         
32471         'beforecollapse',
32472         
32473         'expand',
32474         
32475         'disabledchange',
32476         
32477         'collapse',
32478         
32479         'beforeclick',
32480         
32481         'click',
32482         
32483         'checkchange',
32484         
32485         'beforedblclick',
32486         
32487         'dblclick',
32488         
32489         'contextmenu',
32490         
32491         'beforechildrenrendered'
32492     );
32493
32494     var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
32495
32496     
32497     this.ui = new uiClass(this);
32498 };
32499 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
32500     preventHScroll : true,
32501     
32502     isExpanded : function(){
32503         return this.expanded;
32504     },
32505
32506
32507     getUI : function(){
32508         return this.ui;
32509     },
32510
32511     getLoader : function(){
32512         var owner;
32513         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
32514     },
32515
32516     
32517     setFirstChild : function(node){
32518         var of = this.firstChild;
32519         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
32520         if(this.childrenRendered && of && node != of){
32521             of.renderIndent(true, true);
32522         }
32523         if(this.rendered){
32524             this.renderIndent(true, true);
32525         }
32526     },
32527
32528     
32529     setLastChild : function(node){
32530         var ol = this.lastChild;
32531         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
32532         if(this.childrenRendered && ol && node != ol){
32533             ol.renderIndent(true, true);
32534         }
32535         if(this.rendered){
32536             this.renderIndent(true, true);
32537         }
32538     },
32539
32540     
32541     
32542     appendChild : function(n){
32543         if(!n.render && !Ext.isArray(n)){
32544             n = this.getLoader().createNode(n);
32545         }
32546         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
32547         if(node && this.childrenRendered){
32548             node.render();
32549         }
32550         this.ui.updateExpandIcon();
32551         return node;
32552     },
32553
32554     
32555     removeChild : function(node, destroy){
32556         this.ownerTree.getSelectionModel().unselect(node);
32557         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
32558         
32559         if(!destroy){
32560             
32561             if(node.ui.rendered){
32562                 node.ui.remove();
32563             }
32564             if(this.childNodes.length < 1){
32565                 this.collapse(false, false);
32566             }else{
32567                 this.ui.updateExpandIcon();
32568             }
32569             if(!this.firstChild && !this.isHiddenRoot()){
32570                 this.childrenRendered = false;
32571             }
32572         }
32573         return node;
32574     },
32575
32576     
32577     insertBefore : function(node, refNode){
32578         if(!node.render){
32579             node = this.getLoader().createNode(node);
32580         }
32581         var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
32582         if(newNode && refNode && this.childrenRendered){
32583             node.render();
32584         }
32585         this.ui.updateExpandIcon();
32586         return newNode;
32587     },
32588
32589     
32590     setText : function(text){
32591         var oldText = this.text;
32592         this.text = this.attributes.text = text;
32593         if(this.rendered){ 
32594             this.ui.onTextChange(this, text, oldText);
32595         }
32596         this.fireEvent('textchange', this, text, oldText);
32597     },
32598
32599     
32600     select : function(){
32601         var t = this.getOwnerTree();
32602         if(t){
32603             t.getSelectionModel().select(this);
32604         }
32605     },
32606
32607     
32608     unselect : function(silent){
32609         var t = this.getOwnerTree();
32610         if(t){
32611             t.getSelectionModel().unselect(this, silent);
32612         }
32613     },
32614
32615     
32616     isSelected : function(){
32617         var t = this.getOwnerTree();
32618         return t ? t.getSelectionModel().isSelected(this) : false;
32619     },
32620
32621     
32622     expand : function(deep, anim, callback, scope){
32623         if(!this.expanded){
32624             if(this.fireEvent('beforeexpand', this, deep, anim) === false){
32625                 return;
32626             }
32627             if(!this.childrenRendered){
32628                 this.renderChildren();
32629             }
32630             this.expanded = true;
32631             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
32632                 this.ui.animExpand(function(){
32633                     this.fireEvent('expand', this);
32634                     this.runCallback(callback, scope || this, [this]);
32635                     if(deep === true){
32636                         this.expandChildNodes(true);
32637                     }
32638                 }.createDelegate(this));
32639                 return;
32640             }else{
32641                 this.ui.expand();
32642                 this.fireEvent('expand', this);
32643                 this.runCallback(callback, scope || this, [this]);
32644             }
32645         }else{
32646            this.runCallback(callback, scope || this, [this]);
32647         }
32648         if(deep === true){
32649             this.expandChildNodes(true);
32650         }
32651     },
32652
32653     runCallback : function(cb, scope, args){
32654         if(Ext.isFunction(cb)){
32655             cb.apply(scope, args);
32656         }
32657     },
32658
32659     isHiddenRoot : function(){
32660         return this.isRoot && !this.getOwnerTree().rootVisible;
32661     },
32662
32663     
32664     collapse : function(deep, anim, callback, scope){
32665         if(this.expanded && !this.isHiddenRoot()){
32666             if(this.fireEvent('beforecollapse', this, deep, anim) === false){
32667                 return;
32668             }
32669             this.expanded = false;
32670             if((this.getOwnerTree().animate && anim !== false) || anim){
32671                 this.ui.animCollapse(function(){
32672                     this.fireEvent('collapse', this);
32673                     this.runCallback(callback, scope || this, [this]);
32674                     if(deep === true){
32675                         this.collapseChildNodes(true);
32676                     }
32677                 }.createDelegate(this));
32678                 return;
32679             }else{
32680                 this.ui.collapse();
32681                 this.fireEvent('collapse', this);
32682                 this.runCallback(callback, scope || this, [this]);
32683             }
32684         }else if(!this.expanded){
32685             this.runCallback(callback, scope || this, [this]);
32686         }
32687         if(deep === true){
32688             var cs = this.childNodes;
32689             for(var i = 0, len = cs.length; i < len; i++) {
32690                 cs[i].collapse(true, false);
32691             }
32692         }
32693     },
32694
32695     
32696     delayedExpand : function(delay){
32697         if(!this.expandProcId){
32698             this.expandProcId = this.expand.defer(delay, this);
32699         }
32700     },
32701
32702     
32703     cancelExpand : function(){
32704         if(this.expandProcId){
32705             clearTimeout(this.expandProcId);
32706         }
32707         this.expandProcId = false;
32708     },
32709
32710     
32711     toggle : function(){
32712         if(this.expanded){
32713             this.collapse();
32714         }else{
32715             this.expand();
32716         }
32717     },
32718
32719     
32720     ensureVisible : function(callback, scope){
32721         var tree = this.getOwnerTree();
32722         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
32723             var node = tree.getNodeById(this.id);  
32724             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
32725             this.runCallback(callback, scope || this, [this]);
32726         }.createDelegate(this));
32727     },
32728
32729     
32730     expandChildNodes : function(deep){
32731         var cs = this.childNodes;
32732         for(var i = 0, len = cs.length; i < len; i++) {
32733                 cs[i].expand(deep);
32734         }
32735     },
32736
32737     
32738     collapseChildNodes : function(deep){
32739         var cs = this.childNodes;
32740         for(var i = 0, len = cs.length; i < len; i++) {
32741                 cs[i].collapse(deep);
32742         }
32743     },
32744
32745     
32746     disable : function(){
32747         this.disabled = true;
32748         this.unselect();
32749         if(this.rendered && this.ui.onDisableChange){ 
32750             this.ui.onDisableChange(this, true);
32751         }
32752         this.fireEvent('disabledchange', this, true);
32753     },
32754
32755     
32756     enable : function(){
32757         this.disabled = false;
32758         if(this.rendered && this.ui.onDisableChange){ 
32759             this.ui.onDisableChange(this, false);
32760         }
32761         this.fireEvent('disabledchange', this, false);
32762     },
32763
32764     
32765     renderChildren : function(suppressEvent){
32766         if(suppressEvent !== false){
32767             this.fireEvent('beforechildrenrendered', this);
32768         }
32769         var cs = this.childNodes;
32770         for(var i = 0, len = cs.length; i < len; i++){
32771             cs[i].render(true);
32772         }
32773         this.childrenRendered = true;
32774     },
32775
32776     
32777     sort : function(fn, scope){
32778         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
32779         if(this.childrenRendered){
32780             var cs = this.childNodes;
32781             for(var i = 0, len = cs.length; i < len; i++){
32782                 cs[i].render(true);
32783             }
32784         }
32785     },
32786
32787     
32788     render : function(bulkRender){
32789         this.ui.render(bulkRender);
32790         if(!this.rendered){
32791             
32792             this.getOwnerTree().registerNode(this);
32793             this.rendered = true;
32794             if(this.expanded){
32795                 this.expanded = false;
32796                 this.expand(false, false);
32797             }
32798         }
32799     },
32800
32801     
32802     renderIndent : function(deep, refresh){
32803         if(refresh){
32804             this.ui.childIndent = null;
32805         }
32806         this.ui.renderIndent();
32807         if(deep === true && this.childrenRendered){
32808             var cs = this.childNodes;
32809             for(var i = 0, len = cs.length; i < len; i++){
32810                 cs[i].renderIndent(true, refresh);
32811             }
32812         }
32813     },
32814
32815     beginUpdate : function(){
32816         this.childrenRendered = false;
32817     },
32818
32819     endUpdate : function(){
32820         if(this.expanded && this.rendered){
32821             this.renderChildren();
32822         }
32823     },
32824
32825     
32826     destroy : function(silent){
32827         if(silent === true){
32828             this.unselect(true);
32829         }
32830         Ext.tree.TreeNode.superclass.destroy.call(this, silent);
32831         Ext.destroy(this.ui, this.loader);
32832         this.ui = this.loader = null;
32833     },
32834
32835     
32836     onIdChange : function(id){
32837         this.ui.onIdChange(id);
32838     }
32839 });
32840
32841 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
32842  Ext.tree.AsyncTreeNode = function(config){
32843     this.loaded = config && config.loaded === true;
32844     this.loading = false;
32845     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
32846     
32847     this.addEvents('beforeload', 'load');
32848     
32849     
32850 };
32851 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
32852     expand : function(deep, anim, callback, scope){
32853         if(this.loading){ 
32854             var timer;
32855             var f = function(){
32856                 if(!this.loading){ 
32857                     clearInterval(timer);
32858                     this.expand(deep, anim, callback, scope);
32859                 }
32860             }.createDelegate(this);
32861             timer = setInterval(f, 200);
32862             return;
32863         }
32864         if(!this.loaded){
32865             if(this.fireEvent("beforeload", this) === false){
32866                 return;
32867             }
32868             this.loading = true;
32869             this.ui.beforeLoad(this);
32870             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
32871             if(loader){
32872                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
32873                 return;
32874             }
32875         }
32876         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
32877     },
32878     
32879     
32880     isLoading : function(){
32881         return this.loading;  
32882     },
32883     
32884     loadComplete : function(deep, anim, callback, scope){
32885         this.loading = false;
32886         this.loaded = true;
32887         this.ui.afterLoad(this);
32888         this.fireEvent("load", this);
32889         this.expand(deep, anim, callback, scope);
32890     },
32891     
32892     
32893     isLoaded : function(){
32894         return this.loaded;
32895     },
32896     
32897     hasChildNodes : function(){
32898         if(!this.isLeaf() && !this.loaded){
32899             return true;
32900         }else{
32901             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
32902         }
32903     },
32904
32905     
32906     reload : function(callback, scope){
32907         this.collapse(false, false);
32908         while(this.firstChild){
32909             this.removeChild(this.firstChild).destroy();
32910         }
32911         this.childrenRendered = false;
32912         this.loaded = false;
32913         if(this.isHiddenRoot()){
32914             this.expanded = false;
32915         }
32916         this.expand(false, false, callback, scope);
32917     }
32918 });
32919
32920 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
32921 Ext.tree.TreeNodeUI = function(node){
32922     this.node = node;
32923     this.rendered = false;
32924     this.animating = false;
32925     this.wasLeaf = true;
32926     this.ecc = 'x-tree-ec-icon x-tree-elbow';
32927     this.emptyIcon = Ext.BLANK_IMAGE_URL;
32928 };
32929
32930 Ext.tree.TreeNodeUI.prototype = {
32931     
32932     removeChild : function(node){
32933         if(this.rendered){
32934             this.ctNode.removeChild(node.ui.getEl());
32935         }
32936     },
32937
32938     
32939     beforeLoad : function(){
32940          this.addClass("x-tree-node-loading");
32941     },
32942
32943     
32944     afterLoad : function(){
32945          this.removeClass("x-tree-node-loading");
32946     },
32947
32948     
32949     onTextChange : function(node, text, oldText){
32950         if(this.rendered){
32951             this.textNode.innerHTML = text;
32952         }
32953     },
32954
32955     
32956     onDisableChange : function(node, state){
32957         this.disabled = state;
32958         if (this.checkbox) {
32959             this.checkbox.disabled = state;
32960         }
32961         if(state){
32962             this.addClass("x-tree-node-disabled");
32963         }else{
32964             this.removeClass("x-tree-node-disabled");
32965         }
32966     },
32967
32968     
32969     onSelectedChange : function(state){
32970         if(state){
32971             this.focus();
32972             this.addClass("x-tree-selected");
32973         }else{
32974             
32975             this.removeClass("x-tree-selected");
32976         }
32977     },
32978
32979     
32980     onMove : function(tree, node, oldParent, newParent, index, refNode){
32981         this.childIndent = null;
32982         if(this.rendered){
32983             var targetNode = newParent.ui.getContainer();
32984             if(!targetNode){
32985                 this.holder = document.createElement("div");
32986                 this.holder.appendChild(this.wrap);
32987                 return;
32988             }
32989             var insertBefore = refNode ? refNode.ui.getEl() : null;
32990             if(insertBefore){
32991                 targetNode.insertBefore(this.wrap, insertBefore);
32992             }else{
32993                 targetNode.appendChild(this.wrap);
32994             }
32995             this.node.renderIndent(true, oldParent != newParent);
32996         }
32997     },
32998
32999
33000     addClass : function(cls){
33001         if(this.elNode){
33002             Ext.fly(this.elNode).addClass(cls);
33003         }
33004     },
33005
33006
33007     removeClass : function(cls){
33008         if(this.elNode){
33009             Ext.fly(this.elNode).removeClass(cls);
33010         }
33011     },
33012
33013     
33014     remove : function(){
33015         if(this.rendered){
33016             this.holder = document.createElement("div");
33017             this.holder.appendChild(this.wrap);
33018         }
33019     },
33020
33021     
33022     fireEvent : function(){
33023         return this.node.fireEvent.apply(this.node, arguments);
33024     },
33025
33026     
33027     initEvents : function(){
33028         this.node.on("move", this.onMove, this);
33029
33030         if(this.node.disabled){
33031             this.onDisableChange(this.node, true);
33032         }
33033         if(this.node.hidden){
33034             this.hide();
33035         }
33036         var ot = this.node.getOwnerTree();
33037         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
33038         if(dd && (!this.node.isRoot || ot.rootVisible)){
33039             Ext.dd.Registry.register(this.elNode, {
33040                 node: this.node,
33041                 handles: this.getDDHandles(),
33042                 isHandle: false
33043             });
33044         }
33045     },
33046
33047     
33048     getDDHandles : function(){
33049         return [this.iconNode, this.textNode, this.elNode];
33050     },
33051
33052
33053     hide : function(){
33054         this.node.hidden = true;
33055         if(this.wrap){
33056             this.wrap.style.display = "none";
33057         }
33058     },
33059
33060
33061     show : function(){
33062         this.node.hidden = false;
33063         if(this.wrap){
33064             this.wrap.style.display = "";
33065         }
33066     },
33067
33068     
33069     onContextMenu : function(e){
33070         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
33071             e.preventDefault();
33072             this.focus();
33073             this.fireEvent("contextmenu", this.node, e);
33074         }
33075     },
33076
33077     
33078     onClick : function(e){
33079         if(this.dropping){
33080             e.stopEvent();
33081             return;
33082         }
33083         if(this.fireEvent("beforeclick", this.node, e) !== false){
33084             var a = e.getTarget('a');
33085             if(!this.disabled && this.node.attributes.href && a){
33086                 this.fireEvent("click", this.node, e);
33087                 return;
33088             }else if(a && e.ctrlKey){
33089                 e.stopEvent();
33090             }
33091             e.preventDefault();
33092             if(this.disabled){
33093                 return;
33094             }
33095
33096             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
33097                 this.node.toggle();
33098             }
33099
33100             this.fireEvent("click", this.node, e);
33101         }else{
33102             e.stopEvent();
33103         }
33104     },
33105
33106     
33107     onDblClick : function(e){
33108         e.preventDefault();
33109         if(this.disabled){
33110             return;
33111         }
33112         if(this.fireEvent("beforedblclick", this.node, e) !== false){
33113             if(this.checkbox){
33114                 this.toggleCheck();
33115             }
33116             if(!this.animating && this.node.isExpandable()){
33117                 this.node.toggle();
33118             }
33119             this.fireEvent("dblclick", this.node, e);
33120         }
33121     },
33122
33123     onOver : function(e){
33124         this.addClass('x-tree-node-over');
33125     },
33126
33127     onOut : function(e){
33128         this.removeClass('x-tree-node-over');
33129     },
33130
33131     
33132     onCheckChange : function(){
33133         var checked = this.checkbox.checked;
33134         
33135         this.checkbox.defaultChecked = checked;
33136         this.node.attributes.checked = checked;
33137         this.fireEvent('checkchange', this.node, checked);
33138     },
33139
33140     
33141     ecClick : function(e){
33142         if(!this.animating && this.node.isExpandable()){
33143             this.node.toggle();
33144         }
33145     },
33146
33147     
33148     startDrop : function(){
33149         this.dropping = true;
33150     },
33151
33152     
33153     endDrop : function(){
33154        setTimeout(function(){
33155            this.dropping = false;
33156        }.createDelegate(this), 50);
33157     },
33158
33159     
33160     expand : function(){
33161         this.updateExpandIcon();
33162         this.ctNode.style.display = "";
33163     },
33164
33165     
33166     focus : function(){
33167         if(!this.node.preventHScroll){
33168             try{this.anchor.focus();
33169             }catch(e){}
33170         }else{
33171             try{
33172                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
33173                 var l = noscroll.scrollLeft;
33174                 this.anchor.focus();
33175                 noscroll.scrollLeft = l;
33176             }catch(e){}
33177         }
33178     },
33179
33180
33181     toggleCheck : function(value){
33182         var cb = this.checkbox;
33183         if(cb){
33184             cb.checked = (value === undefined ? !cb.checked : value);
33185             this.onCheckChange();
33186         }
33187     },
33188
33189     
33190     blur : function(){
33191         try{
33192             this.anchor.blur();
33193         }catch(e){}
33194     },
33195
33196     
33197     animExpand : function(callback){
33198         var ct = Ext.get(this.ctNode);
33199         ct.stopFx();
33200         if(!this.node.isExpandable()){
33201             this.updateExpandIcon();
33202             this.ctNode.style.display = "";
33203             Ext.callback(callback);
33204             return;
33205         }
33206         this.animating = true;
33207         this.updateExpandIcon();
33208
33209         ct.slideIn('t', {
33210            callback : function(){
33211                this.animating = false;
33212                Ext.callback(callback);
33213             },
33214             scope: this,
33215             duration: this.node.ownerTree.duration || .25
33216         });
33217     },
33218
33219     
33220     highlight : function(){
33221         var tree = this.node.getOwnerTree();
33222         Ext.fly(this.wrap).highlight(
33223             tree.hlColor || "C3DAF9",
33224             {endColor: tree.hlBaseColor}
33225         );
33226     },
33227
33228     
33229     collapse : function(){
33230         this.updateExpandIcon();
33231         this.ctNode.style.display = "none";
33232     },
33233
33234     
33235     animCollapse : function(callback){
33236         var ct = Ext.get(this.ctNode);
33237         ct.enableDisplayMode('block');
33238         ct.stopFx();
33239
33240         this.animating = true;
33241         this.updateExpandIcon();
33242
33243         ct.slideOut('t', {
33244             callback : function(){
33245                this.animating = false;
33246                Ext.callback(callback);
33247             },
33248             scope: this,
33249             duration: this.node.ownerTree.duration || .25
33250         });
33251     },
33252
33253     
33254     getContainer : function(){
33255         return this.ctNode;
33256     },
33257
33258
33259     getEl : function(){
33260         return this.wrap;
33261     },
33262
33263     
33264     appendDDGhost : function(ghostNode){
33265         ghostNode.appendChild(this.elNode.cloneNode(true));
33266     },
33267
33268     
33269     getDDRepairXY : function(){
33270         return Ext.lib.Dom.getXY(this.iconNode);
33271     },
33272
33273     
33274     onRender : function(){
33275         this.render();
33276     },
33277
33278     
33279     render : function(bulkRender){
33280         var n = this.node, a = n.attributes;
33281         var targetNode = n.parentNode ?
33282               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
33283
33284         if(!this.rendered){
33285             this.rendered = true;
33286
33287             this.renderElements(n, a, targetNode, bulkRender);
33288
33289             if(a.qtip){
33290                if(this.textNode.setAttributeNS){
33291                    this.textNode.setAttributeNS("ext", "qtip", a.qtip);
33292                    if(a.qtipTitle){
33293                        this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
33294                    }
33295                }else{
33296                    this.textNode.setAttribute("ext:qtip", a.qtip);
33297                    if(a.qtipTitle){
33298                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
33299                    }
33300                }
33301             }else if(a.qtipCfg){
33302                 a.qtipCfg.target = Ext.id(this.textNode);
33303                 Ext.QuickTips.register(a.qtipCfg);
33304             }
33305             this.initEvents();
33306             if(!this.node.expanded){
33307                 this.updateExpandIcon(true);
33308             }
33309         }else{
33310             if(bulkRender === true) {
33311                 targetNode.appendChild(this.wrap);
33312             }
33313         }
33314     },
33315
33316     
33317     renderElements : function(n, a, targetNode, bulkRender){
33318         
33319         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
33320
33321         var cb = Ext.isBoolean(a.checked),
33322             nel,
33323             href = a.href ? a.href : Ext.isGecko ? "" : "#",
33324             buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
33325             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
33326             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
33327             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
33328             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
33329             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
33330              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
33331             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
33332             "</li>"].join('');
33333
33334         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
33335             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
33336         }else{
33337             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
33338         }
33339
33340         this.elNode = this.wrap.childNodes[0];
33341         this.ctNode = this.wrap.childNodes[1];
33342         var cs = this.elNode.childNodes;
33343         this.indentNode = cs[0];
33344         this.ecNode = cs[1];
33345         this.iconNode = cs[2];
33346         var index = 3;
33347         if(cb){
33348             this.checkbox = cs[3];
33349             
33350             this.checkbox.defaultChecked = this.checkbox.checked;
33351             index++;
33352         }
33353         this.anchor = cs[index];
33354         this.textNode = cs[index].firstChild;
33355     },
33356
33357
33358     getAnchor : function(){
33359         return this.anchor;
33360     },
33361
33362
33363     getTextEl : function(){
33364         return this.textNode;
33365     },
33366
33367
33368     getIconEl : function(){
33369         return this.iconNode;
33370     },
33371
33372
33373     isChecked : function(){
33374         return this.checkbox ? this.checkbox.checked : false;
33375     },
33376
33377     
33378     updateExpandIcon : function(){
33379         if(this.rendered){
33380             var n = this.node,
33381                 c1,
33382                 c2,
33383                 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
33384                 hasChild = n.hasChildNodes();
33385             if(hasChild || n.attributes.expandable){
33386                 if(n.expanded){
33387                     cls += "-minus";
33388                     c1 = "x-tree-node-collapsed";
33389                     c2 = "x-tree-node-expanded";
33390                 }else{
33391                     cls += "-plus";
33392                     c1 = "x-tree-node-expanded";
33393                     c2 = "x-tree-node-collapsed";
33394                 }
33395                 if(this.wasLeaf){
33396                     this.removeClass("x-tree-node-leaf");
33397                     this.wasLeaf = false;
33398                 }
33399                 if(this.c1 != c1 || this.c2 != c2){
33400                     Ext.fly(this.elNode).replaceClass(c1, c2);
33401                     this.c1 = c1; this.c2 = c2;
33402                 }
33403             }else{
33404                 if(!this.wasLeaf){
33405                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
33406                     delete this.c1;
33407                     delete this.c2;
33408                     this.wasLeaf = true;
33409                 }
33410             }
33411             var ecc = "x-tree-ec-icon "+cls;
33412             if(this.ecc != ecc){
33413                 this.ecNode.className = ecc;
33414                 this.ecc = ecc;
33415             }
33416         }
33417     },
33418
33419     
33420     onIdChange: function(id){
33421         if(this.rendered){
33422             this.elNode.setAttribute('ext:tree-node-id', id);
33423         }
33424     },
33425
33426     
33427     getChildIndent : function(){
33428         if(!this.childIndent){
33429             var buf = [],
33430                 p = this.node;
33431             while(p){
33432                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
33433                     if(!p.isLast()) {
33434                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
33435                     } else {
33436                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
33437                     }
33438                 }
33439                 p = p.parentNode;
33440             }
33441             this.childIndent = buf.join("");
33442         }
33443         return this.childIndent;
33444     },
33445
33446     
33447     renderIndent : function(){
33448         if(this.rendered){
33449             var indent = "",
33450                 p = this.node.parentNode;
33451             if(p){
33452                 indent = p.ui.getChildIndent();
33453             }
33454             if(this.indentMarkup != indent){ 
33455                 this.indentNode.innerHTML = indent;
33456                 this.indentMarkup = indent;
33457             }
33458             this.updateExpandIcon();
33459         }
33460     },
33461
33462     destroy : function(){
33463         if(this.elNode){
33464             Ext.dd.Registry.unregister(this.elNode.id);
33465         }
33466
33467         Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
33468             if(this[el]){
33469                 Ext.fly(this[el]).remove();
33470                 delete this[el];
33471             }
33472         }, this);
33473         delete this.node;
33474     }
33475 };
33476
33477
33478 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
33479     
33480     render : function(){
33481         if(!this.rendered){
33482             var targetNode = this.node.ownerTree.innerCt.dom;
33483             this.node.expanded = true;
33484             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
33485             this.wrap = this.ctNode = targetNode.firstChild;
33486         }
33487     },
33488     collapse : Ext.emptyFn,
33489     expand : Ext.emptyFn
33490 });
33491 Ext.tree.TreeLoader = function(config){
33492     this.baseParams = {};
33493     Ext.apply(this, config);
33494
33495     this.addEvents(
33496         
33497         "beforeload",
33498         
33499         "load",
33500         
33501         "loadexception"
33502     );
33503     Ext.tree.TreeLoader.superclass.constructor.call(this);
33504     if(Ext.isString(this.paramOrder)){
33505         this.paramOrder = this.paramOrder.split(/[\s,|]/);
33506     }
33507 };
33508
33509 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
33510     
33511     
33512     
33513     
33514     
33515     
33516     
33517     uiProviders : {},
33518
33519     
33520     clearOnLoad : true,
33521
33522     
33523     paramOrder: undefined,
33524
33525     
33526     paramsAsHash: false,
33527
33528     
33529     nodeParameter: 'node',
33530
33531     
33532     directFn : undefined,
33533
33534     
33535     load : function(node, callback, scope){
33536         if(this.clearOnLoad){
33537             while(node.firstChild){
33538                 node.removeChild(node.firstChild);
33539             }
33540         }
33541         if(this.doPreload(node)){ 
33542             this.runCallback(callback, scope || node, [node]);
33543         }else if(this.directFn || this.dataUrl || this.url){
33544             this.requestData(node, callback, scope || node);
33545         }
33546     },
33547
33548     doPreload : function(node){
33549         if(node.attributes.children){
33550             if(node.childNodes.length < 1){ 
33551                 var cs = node.attributes.children;
33552                 node.beginUpdate();
33553                 for(var i = 0, len = cs.length; i < len; i++){
33554                     var cn = node.appendChild(this.createNode(cs[i]));
33555                     if(this.preloadChildren){
33556                         this.doPreload(cn);
33557                     }
33558                 }
33559                 node.endUpdate();
33560             }
33561             return true;
33562         }
33563         return false;
33564     },
33565
33566     getParams: function(node){
33567         var bp = Ext.apply({}, this.baseParams),
33568             np = this.nodeParameter,
33569             po = this.paramOrder;
33570
33571         np && (bp[ np ] = node.id);
33572
33573         if(this.directFn){
33574             var buf = [node.id];
33575             if(po){
33576                 
33577                 if(np && po.indexOf(np) > -1){
33578                     buf = [];
33579                 }
33580
33581                 for(var i = 0, len = po.length; i < len; i++){
33582                     buf.push(bp[ po[i] ]);
33583                 }
33584             }else if(this.paramsAsHash){
33585                 buf = [bp];
33586             }
33587             return buf;
33588         }else{
33589             return bp;
33590         }
33591     },
33592
33593     requestData : function(node, callback, scope){
33594         if(this.fireEvent("beforeload", this, node, callback) !== false){
33595             if(this.directFn){
33596                 var args = this.getParams(node);
33597                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
33598                 this.directFn.apply(window, args);
33599             }else{
33600                 this.transId = Ext.Ajax.request({
33601                     method:this.requestMethod,
33602                     url: this.dataUrl||this.url,
33603                     success: this.handleResponse,
33604                     failure: this.handleFailure,
33605                     scope: this,
33606                     argument: {callback: callback, node: node, scope: scope},
33607                     params: this.getParams(node)
33608                 });
33609             }
33610         }else{
33611             
33612             
33613             this.runCallback(callback, scope || node, []);
33614         }
33615     },
33616
33617     processDirectResponse: function(result, response, args){
33618         if(response.status){
33619             this.handleResponse({
33620                 responseData: Ext.isArray(result) ? result : null,
33621                 responseText: result,
33622                 argument: args
33623             });
33624         }else{
33625             this.handleFailure({
33626                 argument: args
33627             });
33628         }
33629     },
33630
33631     
33632     runCallback: function(cb, scope, args){
33633         if(Ext.isFunction(cb)){
33634             cb.apply(scope, args);
33635         }
33636     },
33637
33638     isLoading : function(){
33639         return !!this.transId;
33640     },
33641
33642     abort : function(){
33643         if(this.isLoading()){
33644             Ext.Ajax.abort(this.transId);
33645         }
33646     },
33647
33648     
33649     createNode : function(attr){
33650         
33651         if(this.baseAttrs){
33652             Ext.applyIf(attr, this.baseAttrs);
33653         }
33654         if(this.applyLoader !== false && !attr.loader){
33655             attr.loader = this;
33656         }
33657         if(Ext.isString(attr.uiProvider)){
33658            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
33659         }
33660         if(attr.nodeType){
33661             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
33662         }else{
33663             return attr.leaf ?
33664                         new Ext.tree.TreeNode(attr) :
33665                         new Ext.tree.AsyncTreeNode(attr);
33666         }
33667     },
33668
33669     processResponse : function(response, node, callback, scope){
33670         var json = response.responseText;
33671         try {
33672             var o = response.responseData || Ext.decode(json);
33673             node.beginUpdate();
33674             for(var i = 0, len = o.length; i < len; i++){
33675                 var n = this.createNode(o[i]);
33676                 if(n){
33677                     node.appendChild(n);
33678                 }
33679             }
33680             node.endUpdate();
33681             this.runCallback(callback, scope || node, [node]);
33682         }catch(e){
33683             this.handleFailure(response);
33684         }
33685     },
33686
33687     handleResponse : function(response){
33688         this.transId = false;
33689         var a = response.argument;
33690         this.processResponse(response, a.node, a.callback, a.scope);
33691         this.fireEvent("load", this, a.node, response);
33692     },
33693
33694     handleFailure : function(response){
33695         this.transId = false;
33696         var a = response.argument;
33697         this.fireEvent("loadexception", this, a.node, response);
33698         this.runCallback(a.callback, a.scope || a.node, [a.node]);
33699     },
33700
33701     destroy : function(){
33702         this.abort();
33703         this.purgeListeners();
33704     }
33705 });
33706 Ext.tree.TreeFilter = function(tree, config){
33707     this.tree = tree;
33708     this.filtered = {};
33709     Ext.apply(this, config);
33710 };
33711
33712 Ext.tree.TreeFilter.prototype = {
33713     clearBlank:false,
33714     reverse:false,
33715     autoClear:false,
33716     remove:false,
33717
33718      
33719     filter : function(value, attr, startNode){
33720         attr = attr || "text";
33721         var f;
33722         if(typeof value == "string"){
33723             var vlen = value.length;
33724             
33725             if(vlen == 0 && this.clearBlank){
33726                 this.clear();
33727                 return;
33728             }
33729             value = value.toLowerCase();
33730             f = function(n){
33731                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
33732             };
33733         }else if(value.exec){ 
33734             f = function(n){
33735                 return value.test(n.attributes[attr]);
33736             };
33737         }else{
33738             throw 'Illegal filter type, must be string or regex';
33739         }
33740         this.filterBy(f, null, startNode);
33741         },
33742
33743     
33744     filterBy : function(fn, scope, startNode){
33745         startNode = startNode || this.tree.root;
33746         if(this.autoClear){
33747             this.clear();
33748         }
33749         var af = this.filtered, rv = this.reverse;
33750         var f = function(n){
33751             if(n == startNode){
33752                 return true;
33753             }
33754             if(af[n.id]){
33755                 return false;
33756             }
33757             var m = fn.call(scope || n, n);
33758             if(!m || rv){
33759                 af[n.id] = n;
33760                 n.ui.hide();
33761                 return false;
33762             }
33763             return true;
33764         };
33765         startNode.cascade(f);
33766         if(this.remove){
33767            for(var id in af){
33768                if(typeof id != "function"){
33769                    var n = af[id];
33770                    if(n && n.parentNode){
33771                        n.parentNode.removeChild(n);
33772                    }
33773                }
33774            }
33775         }
33776     },
33777
33778     
33779     clear : function(){
33780         var t = this.tree;
33781         var af = this.filtered;
33782         for(var id in af){
33783             if(typeof id != "function"){
33784                 var n = af[id];
33785                 if(n){
33786                     n.ui.show();
33787                 }
33788             }
33789         }
33790         this.filtered = {};
33791     }
33792 };
33793
33794 Ext.tree.TreeSorter = function(tree, config){
33795     
33796     
33797     
33798     
33799     
33800     
33801
33802     Ext.apply(this, config);
33803     tree.on("beforechildrenrendered", this.doSort, this);
33804     tree.on("append", this.updateSort, this);
33805     tree.on("insert", this.updateSort, this);
33806     tree.on("textchange", this.updateSortParent, this);
33807
33808     var dsc = this.dir && this.dir.toLowerCase() == "desc";
33809     var p = this.property || "text";
33810     var sortType = this.sortType;
33811     var fs = this.folderSort;
33812     var cs = this.caseSensitive === true;
33813     var leafAttr = this.leafAttr || 'leaf';
33814
33815     this.sortFn = function(n1, n2){
33816         if(fs){
33817             if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
33818                 return 1;
33819             }
33820             if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
33821                 return -1;
33822             }
33823         }
33824         var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
33825         var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
33826         if(v1 < v2){
33827             return dsc ? +1 : -1;
33828         }else if(v1 > v2){
33829             return dsc ? -1 : +1;
33830         }else{
33831             return 0;
33832         }
33833     };
33834 };
33835
33836 Ext.tree.TreeSorter.prototype = {
33837     doSort : function(node){
33838         node.sort(this.sortFn);
33839     },
33840
33841     compareNodes : function(n1, n2){
33842         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
33843     },
33844
33845     updateSort : function(tree, node){
33846         if(node.childrenRendered){
33847             this.doSort.defer(1, this, [node]);
33848         }
33849     },
33850
33851     updateSortParent : function(node){
33852         var p = node.parentNode;
33853         if(p && p.childrenRendered){
33854             this.doSort.defer(1, this, [p]);
33855         }
33856     }
33857 };
33858 if(Ext.dd.DropZone){
33859     
33860 Ext.tree.TreeDropZone = function(tree, config){
33861     
33862     this.allowParentInsert = config.allowParentInsert || false;
33863     
33864     this.allowContainerDrop = config.allowContainerDrop || false;
33865     
33866     this.appendOnly = config.appendOnly || false;
33867
33868     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
33869     
33870     this.tree = tree;
33871     
33872     this.dragOverData = {};
33873     
33874     this.lastInsertClass = "x-tree-no-status";
33875 };
33876
33877 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
33878     
33879     ddGroup : "TreeDD",
33880
33881     
33882     expandDelay : 1000,
33883
33884     
33885     expandNode : function(node){
33886         if(node.hasChildNodes() && !node.isExpanded()){
33887             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
33888         }
33889     },
33890
33891     
33892     queueExpand : function(node){
33893         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
33894     },
33895
33896     
33897     cancelExpand : function(){
33898         if(this.expandProcId){
33899             clearTimeout(this.expandProcId);
33900             this.expandProcId = false;
33901         }
33902     },
33903
33904     
33905     isValidDropPoint : function(n, pt, dd, e, data){
33906         if(!n || !data){ return false; }
33907         var targetNode = n.node;
33908         var dropNode = data.node;
33909         
33910         if(!(targetNode && targetNode.isTarget && pt)){
33911             return false;
33912         }
33913         if(pt == "append" && targetNode.allowChildren === false){
33914             return false;
33915         }
33916         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
33917             return false;
33918         }
33919         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
33920             return false;
33921         }
33922         
33923         var overEvent = this.dragOverData;
33924         overEvent.tree = this.tree;
33925         overEvent.target = targetNode;
33926         overEvent.data = data;
33927         overEvent.point = pt;
33928         overEvent.source = dd;
33929         overEvent.rawEvent = e;
33930         overEvent.dropNode = dropNode;
33931         overEvent.cancel = false;  
33932         var result = this.tree.fireEvent("nodedragover", overEvent);
33933         return overEvent.cancel === false && result !== false;
33934     },
33935
33936     
33937     getDropPoint : function(e, n, dd){
33938         var tn = n.node;
33939         if(tn.isRoot){
33940             return tn.allowChildren !== false ? "append" : false; 
33941         }
33942         var dragEl = n.ddel;
33943         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
33944         var y = Ext.lib.Event.getPageY(e);
33945         var noAppend = tn.allowChildren === false || tn.isLeaf();
33946         if(this.appendOnly || tn.parentNode.allowChildren === false){
33947             return noAppend ? false : "append";
33948         }
33949         var noBelow = false;
33950         if(!this.allowParentInsert){
33951             noBelow = tn.hasChildNodes() && tn.isExpanded();
33952         }
33953         var q = (b - t) / (noAppend ? 2 : 3);
33954         if(y >= t && y < (t + q)){
33955             return "above";
33956         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
33957             return "below";
33958         }else{
33959             return "append";
33960         }
33961     },
33962
33963     
33964     onNodeEnter : function(n, dd, e, data){
33965         this.cancelExpand();
33966     },
33967     
33968     onContainerOver : function(dd, e, data) {
33969         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
33970             return this.dropAllowed;
33971         }
33972         return this.dropNotAllowed;
33973     },
33974
33975     
33976     onNodeOver : function(n, dd, e, data){
33977         var pt = this.getDropPoint(e, n, dd);
33978         var node = n.node;
33979         
33980         
33981         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
33982             this.queueExpand(node);
33983         }else if(pt != "append"){
33984             this.cancelExpand();
33985         }
33986         
33987         
33988         var returnCls = this.dropNotAllowed;
33989         if(this.isValidDropPoint(n, pt, dd, e, data)){
33990            if(pt){
33991                var el = n.ddel;
33992                var cls;
33993                if(pt == "above"){
33994                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
33995                    cls = "x-tree-drag-insert-above";
33996                }else if(pt == "below"){
33997                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
33998                    cls = "x-tree-drag-insert-below";
33999                }else{
34000                    returnCls = "x-tree-drop-ok-append";
34001                    cls = "x-tree-drag-append";
34002                }
34003                if(this.lastInsertClass != cls){
34004                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
34005                    this.lastInsertClass = cls;
34006                }
34007            }
34008        }
34009        return returnCls;
34010     },
34011
34012     
34013     onNodeOut : function(n, dd, e, data){
34014         this.cancelExpand();
34015         this.removeDropIndicators(n);
34016     },
34017
34018     
34019     onNodeDrop : function(n, dd, e, data){
34020         var point = this.getDropPoint(e, n, dd);
34021         var targetNode = n.node;
34022         targetNode.ui.startDrop();
34023         if(!this.isValidDropPoint(n, point, dd, e, data)){
34024             targetNode.ui.endDrop();
34025             return false;
34026         }
34027         
34028         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
34029         return this.processDrop(targetNode, data, point, dd, e, dropNode);
34030     },
34031     
34032     onContainerDrop : function(dd, e, data){
34033         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
34034             var targetNode = this.tree.getRootNode();       
34035             targetNode.ui.startDrop();
34036             var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
34037             return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
34038         }
34039         return false;
34040     },
34041     
34042     
34043     processDrop: function(target, data, point, dd, e, dropNode){
34044         var dropEvent = {
34045             tree : this.tree,
34046             target: target,
34047             data: data,
34048             point: point,
34049             source: dd,
34050             rawEvent: e,
34051             dropNode: dropNode,
34052             cancel: !dropNode,
34053             dropStatus: false
34054         };
34055         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
34056         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
34057             target.ui.endDrop();
34058             return dropEvent.dropStatus;
34059         }
34060     
34061         target = dropEvent.target;
34062         if(point == 'append' && !target.isExpanded()){
34063             target.expand(false, null, function(){
34064                 this.completeDrop(dropEvent);
34065             }.createDelegate(this));
34066         }else{
34067             this.completeDrop(dropEvent);
34068         }
34069         return true;
34070     },
34071
34072     
34073     completeDrop : function(de){
34074         var ns = de.dropNode, p = de.point, t = de.target;
34075         if(!Ext.isArray(ns)){
34076             ns = [ns];
34077         }
34078         var n;
34079         for(var i = 0, len = ns.length; i < len; i++){
34080             n = ns[i];
34081             if(p == "above"){
34082                 t.parentNode.insertBefore(n, t);
34083             }else if(p == "below"){
34084                 t.parentNode.insertBefore(n, t.nextSibling);
34085             }else{
34086                 t.appendChild(n);
34087             }
34088         }
34089         n.ui.focus();
34090         if(Ext.enableFx && this.tree.hlDrop){
34091             n.ui.highlight();
34092         }
34093         t.ui.endDrop();
34094         this.tree.fireEvent("nodedrop", de);
34095     },
34096
34097     
34098     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
34099         if(Ext.enableFx && this.tree.hlDrop){
34100             dropNode.ui.focus();
34101             dropNode.ui.highlight();
34102         }
34103         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
34104     },
34105
34106     
34107     getTree : function(){
34108         return this.tree;
34109     },
34110
34111     
34112     removeDropIndicators : function(n){
34113         if(n && n.ddel){
34114             var el = n.ddel;
34115             Ext.fly(el).removeClass([
34116                     "x-tree-drag-insert-above",
34117                     "x-tree-drag-insert-below",
34118                     "x-tree-drag-append"]);
34119             this.lastInsertClass = "_noclass";
34120         }
34121     },
34122
34123     
34124     beforeDragDrop : function(target, e, id){
34125         this.cancelExpand();
34126         return true;
34127     },
34128
34129     
34130     afterRepair : function(data){
34131         if(data && Ext.enableFx){
34132             data.node.ui.highlight();
34133         }
34134         this.hideProxy();
34135     }    
34136 });
34137
34138 }
34139 if(Ext.dd.DragZone){
34140 Ext.tree.TreeDragZone = function(tree, config){
34141     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
34142     
34143     this.tree = tree;
34144 };
34145
34146 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
34147     
34148     ddGroup : "TreeDD",
34149
34150     
34151     onBeforeDrag : function(data, e){
34152         var n = data.node;
34153         return n && n.draggable && !n.disabled;
34154     },
34155
34156     
34157     onInitDrag : function(e){
34158         var data = this.dragData;
34159         this.tree.getSelectionModel().select(data.node);
34160         this.tree.eventModel.disable();
34161         this.proxy.update("");
34162         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
34163         this.tree.fireEvent("startdrag", this.tree, data.node, e);
34164     },
34165
34166     
34167     getRepairXY : function(e, data){
34168         return data.node.ui.getDDRepairXY();
34169     },
34170
34171     
34172     onEndDrag : function(data, e){
34173         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
34174         this.tree.fireEvent("enddrag", this.tree, data.node, e);
34175     },
34176
34177     
34178     onValidDrop : function(dd, e, id){
34179         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
34180         this.hideProxy();
34181     },
34182
34183     
34184     beforeInvalidDrop : function(e, id){
34185         
34186         var sm = this.tree.getSelectionModel();
34187         sm.clearSelections();
34188         sm.select(this.dragData.node);
34189     },
34190     
34191     
34192     afterRepair : function(){
34193         if (Ext.enableFx && this.tree.hlDrop) {
34194             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
34195         }
34196         this.dragging = false;
34197     }
34198 });
34199 }
34200 Ext.tree.TreeEditor = function(tree, fc, config){
34201     fc = fc || {};
34202     var field = fc.events ? fc : new Ext.form.TextField(fc);
34203     
34204     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
34205
34206     this.tree = tree;
34207
34208     if(!tree.rendered){
34209         tree.on('render', this.initEditor, this);
34210     }else{
34211         this.initEditor(tree);
34212     }
34213 };
34214
34215 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
34216     
34217     alignment: "l-l",
34218     
34219     autoSize: false,
34220     
34221     hideEl : false,
34222     
34223     cls: "x-small-editor x-tree-editor",
34224     
34225     shim:false,
34226     
34227     shadow:"frame",
34228     
34229     maxWidth: 250,
34230     
34231     editDelay : 350,
34232
34233     initEditor : function(tree){
34234         tree.on({
34235             scope      : this,
34236             beforeclick: this.beforeNodeClick,
34237             dblclick   : this.onNodeDblClick
34238         });
34239         
34240         this.on({
34241             scope          : this,
34242             complete       : this.updateNode,
34243             beforestartedit: this.fitToTree,
34244             specialkey     : this.onSpecialKey
34245         });
34246         
34247         this.on('startedit', this.bindScroll, this, {delay:10});
34248     },
34249
34250     
34251     fitToTree : function(ed, el){
34252         var td = this.tree.getTreeEl().dom, nd = el.dom;
34253         if(td.scrollLeft >  nd.offsetLeft){ 
34254             td.scrollLeft = nd.offsetLeft;
34255         }
34256         var w = Math.min(
34257                 this.maxWidth,
34258                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
34259         this.setSize(w, '');
34260     },
34261
34262     
34263     triggerEdit : function(node, defer){
34264         this.completeEdit();
34265                 if(node.attributes.editable !== false){
34266            
34267                         this.editNode = node;
34268             if(this.tree.autoScroll){
34269                 Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
34270             }
34271             var value = node.text || '';
34272             if (!Ext.isGecko && Ext.isEmpty(node.text)){
34273                 node.setText('&#160;');
34274             }
34275             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
34276             return false;
34277         }
34278     },
34279
34280     
34281     bindScroll : function(){
34282         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
34283     },
34284
34285     
34286     beforeNodeClick : function(node, e){
34287         clearTimeout(this.autoEditTimer);
34288         if(this.tree.getSelectionModel().isSelected(node)){
34289             e.stopEvent();
34290             return this.triggerEdit(node);
34291         }
34292     },
34293
34294     onNodeDblClick : function(node, e){
34295         clearTimeout(this.autoEditTimer);
34296     },
34297
34298     
34299     updateNode : function(ed, value){
34300         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
34301         this.editNode.setText(value);
34302     },
34303
34304     
34305     onHide : function(){
34306         Ext.tree.TreeEditor.superclass.onHide.call(this);
34307         if(this.editNode){
34308             this.editNode.ui.focus.defer(50, this.editNode.ui);
34309         }
34310     },
34311
34312     
34313     onSpecialKey : function(field, e){
34314         var k = e.getKey();
34315         if(k == e.ESC){
34316             e.stopEvent();
34317             this.cancelEdit();
34318         }else if(k == e.ENTER && !e.hasModifier()){
34319             e.stopEvent();
34320             this.completeEdit();
34321         }
34322     },
34323     
34324     onDestroy : function(){
34325         clearTimeout(this.autoEditTimer);
34326         Ext.tree.TreeEditor.superclass.onDestroy.call(this);
34327         var tree = this.tree;
34328         tree.un('beforeclick', this.beforeNodeClick, this);
34329         tree.un('dblclick', this.onNodeDblClick, this);
34330     }
34331 });
34332
34333 var swfobject = function() {
34334     
34335     var UNDEF = "undefined",
34336         OBJECT = "object",
34337         SHOCKWAVE_FLASH = "Shockwave Flash",
34338         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
34339         FLASH_MIME_TYPE = "application/x-shockwave-flash",
34340         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
34341         ON_READY_STATE_CHANGE = "onreadystatechange",
34342         
34343         win = window,
34344         doc = document,
34345         nav = navigator,
34346         
34347         plugin = false,
34348         domLoadFnArr = [main],
34349         regObjArr = [],
34350         objIdArr = [],
34351         listenersArr = [],
34352         storedAltContent,
34353         storedAltContentId,
34354         storedCallbackFn,
34355         storedCallbackObj,
34356         isDomLoaded = false,
34357         isExpressInstallActive = false,
34358         dynamicStylesheet,
34359         dynamicStylesheetMedia,
34360         autoHideShow = true,
34361     
34362       
34363     ua = function() {
34364         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
34365             u = nav.userAgent.toLowerCase(),
34366             p = nav.platform.toLowerCase(),
34367             windows = p ? /win/.test(p) : /win/.test(u),
34368             mac = p ? /mac/.test(p) : /mac/.test(u),
34369             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
34370             ie = !+"\v1", 
34371             playerVersion = [0,0,0],
34372             d = null;
34373         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
34374             d = nav.plugins[SHOCKWAVE_FLASH].description;
34375             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
34376                 plugin = true;
34377                 ie = false; 
34378                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
34379                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
34380                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
34381                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
34382             }
34383         }
34384         else if (typeof win.ActiveXObject != UNDEF) {
34385             try {
34386                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
34387                 if (a) { 
34388                     d = a.GetVariable("$version");
34389                     if (d) {
34390                         ie = true; 
34391                         d = d.split(" ")[1].split(",");
34392                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
34393                     }
34394                 }
34395             }
34396             catch(e) {}
34397         }
34398         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
34399     }(),
34400     
34401      
34402     onDomLoad = function() {
34403         if (!ua.w3) { return; }
34404         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
34405             callDomLoadFunctions();
34406         }
34407         if (!isDomLoaded) {
34408             if (typeof doc.addEventListener != UNDEF) {
34409                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
34410             }       
34411             if (ua.ie && ua.win) {
34412                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
34413                     if (doc.readyState == "complete") {
34414                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
34415                         callDomLoadFunctions();
34416                     }
34417                 });
34418                 if (win == top) { 
34419                     (function(){
34420                         if (isDomLoaded) { return; }
34421                         try {
34422                             doc.documentElement.doScroll("left");
34423                         }
34424                         catch(e) {
34425                             setTimeout(arguments.callee, 0);
34426                             return;
34427                         }
34428                         callDomLoadFunctions();
34429                     })();
34430                 }
34431             }
34432             if (ua.wk) {
34433                 (function(){
34434                     if (isDomLoaded) { return; }
34435                     if (!/loaded|complete/.test(doc.readyState)) {
34436                         setTimeout(arguments.callee, 0);
34437                         return;
34438                     }
34439                     callDomLoadFunctions();
34440                 })();
34441             }
34442             addLoadEvent(callDomLoadFunctions);
34443         }
34444     }();
34445     
34446     function callDomLoadFunctions() {
34447         if (isDomLoaded) { return; }
34448         try { 
34449             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
34450             t.parentNode.removeChild(t);
34451         }
34452         catch (e) { return; }
34453         isDomLoaded = true;
34454         var dl = domLoadFnArr.length;
34455         for (var i = 0; i < dl; i++) {
34456             domLoadFnArr[i]();
34457         }
34458     }
34459     
34460     function addDomLoadEvent(fn) {
34461         if (isDomLoaded) {
34462             fn();
34463         }
34464         else { 
34465             domLoadFnArr[domLoadFnArr.length] = fn; 
34466         }
34467     }
34468     
34469     
34470     function addLoadEvent(fn) {
34471         if (typeof win.addEventListener != UNDEF) {
34472             win.addEventListener("load", fn, false);
34473         }
34474         else if (typeof doc.addEventListener != UNDEF) {
34475             doc.addEventListener("load", fn, false);
34476         }
34477         else if (typeof win.attachEvent != UNDEF) {
34478             addListener(win, "onload", fn);
34479         }
34480         else if (typeof win.onload == "function") {
34481             var fnOld = win.onload;
34482             win.onload = function() {
34483                 fnOld();
34484                 fn();
34485             };
34486         }
34487         else {
34488             win.onload = fn;
34489         }
34490     }
34491     
34492     
34493     function main() { 
34494         if (plugin) {
34495             testPlayerVersion();
34496         }
34497         else {
34498             matchVersions();
34499         }
34500     }
34501     
34502     
34503     function testPlayerVersion() {
34504         var b = doc.getElementsByTagName("body")[0];
34505         var o = createElement(OBJECT);
34506         o.setAttribute("type", FLASH_MIME_TYPE);
34507         var t = b.appendChild(o);
34508         if (t) {
34509             var counter = 0;
34510             (function(){
34511                 if (typeof t.GetVariable != UNDEF) {
34512                     var d = t.GetVariable("$version");
34513                     if (d) {
34514                         d = d.split(" ")[1].split(",");
34515                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
34516                     }
34517                 }
34518                 else if (counter < 10) {
34519                     counter++;
34520                     setTimeout(arguments.callee, 10);
34521                     return;
34522                 }
34523                 b.removeChild(o);
34524                 t = null;
34525                 matchVersions();
34526             })();
34527         }
34528         else {
34529             matchVersions();
34530         }
34531     }
34532     
34533     
34534     function matchVersions() {
34535         var rl = regObjArr.length;
34536         if (rl > 0) {
34537             for (var i = 0; i < rl; i++) { 
34538                 var id = regObjArr[i].id;
34539                 var cb = regObjArr[i].callbackFn;
34540                 var cbObj = {success:false, id:id};
34541                 if (ua.pv[0] > 0) {
34542                     var obj = getElementById(id);
34543                     if (obj) {
34544                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
34545                             setVisibility(id, true);
34546                             if (cb) {
34547                                 cbObj.success = true;
34548                                 cbObj.ref = getObjectById(id);
34549                                 cb(cbObj);
34550                             }
34551                         }
34552                         else if (regObjArr[i].expressInstall && canExpressInstall()) { 
34553                             var att = {};
34554                             att.data = regObjArr[i].expressInstall;
34555                             att.width = obj.getAttribute("width") || "0";
34556                             att.height = obj.getAttribute("height") || "0";
34557                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
34558                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
34559                             
34560                             var par = {};
34561                             var p = obj.getElementsByTagName("param");
34562                             var pl = p.length;
34563                             for (var j = 0; j < pl; j++) {
34564                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
34565                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
34566                                 }
34567                             }
34568                             showExpressInstall(att, par, id, cb);
34569                         }
34570                         else { 
34571                             displayAltContent(obj);
34572                             if (cb) { cb(cbObj); }
34573                         }
34574                     }
34575                 }
34576                 else {  
34577                     setVisibility(id, true);
34578                     if (cb) {
34579                         var o = getObjectById(id); 
34580                         if (o && typeof o.SetVariable != UNDEF) { 
34581                             cbObj.success = true;
34582                             cbObj.ref = o;
34583                         }
34584                         cb(cbObj);
34585                     }
34586                 }
34587             }
34588         }
34589     }
34590     
34591     function getObjectById(objectIdStr) {
34592         var r = null;
34593         var o = getElementById(objectIdStr);
34594         if (o && o.nodeName == "OBJECT") {
34595             if (typeof o.SetVariable != UNDEF) {
34596                 r = o;
34597             }
34598             else {
34599                 var n = o.getElementsByTagName(OBJECT)[0];
34600                 if (n) {
34601                     r = n;
34602                 }
34603             }
34604         }
34605         return r;
34606     }
34607     
34608     
34609     function canExpressInstall() {
34610         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
34611     }
34612     
34613     
34614     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
34615         isExpressInstallActive = true;
34616         storedCallbackFn = callbackFn || null;
34617         storedCallbackObj = {success:false, id:replaceElemIdStr};
34618         var obj = getElementById(replaceElemIdStr);
34619         if (obj) {
34620             if (obj.nodeName == "OBJECT") { 
34621                 storedAltContent = abstractAltContent(obj);
34622                 storedAltContentId = null;
34623             }
34624             else { 
34625                 storedAltContent = obj;
34626                 storedAltContentId = replaceElemIdStr;
34627             }
34628             att.id = EXPRESS_INSTALL_ID;
34629             if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
34630             if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
34631             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
34632             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
34633                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
34634             if (typeof par.flashvars != UNDEF) {
34635                 par.flashvars += "&" + fv;
34636             }
34637             else {
34638                 par.flashvars = fv;
34639             }
34640             
34641             
34642             if (ua.ie && ua.win && obj.readyState != 4) {
34643                 var newObj = createElement("div");
34644                 replaceElemIdStr += "SWFObjectNew";
34645                 newObj.setAttribute("id", replaceElemIdStr);
34646                 obj.parentNode.insertBefore(newObj, obj); 
34647                 obj.style.display = "none";
34648                 (function(){
34649                     if (obj.readyState == 4) {
34650                         obj.parentNode.removeChild(obj);
34651                     }
34652                     else {
34653                         setTimeout(arguments.callee, 10);
34654                     }
34655                 })();
34656             }
34657             createSWF(att, par, replaceElemIdStr);
34658         }
34659     }
34660     
34661     
34662     function displayAltContent(obj) {
34663         if (ua.ie && ua.win && obj.readyState != 4) {
34664             
34665             
34666             var el = createElement("div");
34667             obj.parentNode.insertBefore(el, obj); 
34668             el.parentNode.replaceChild(abstractAltContent(obj), el);
34669             obj.style.display = "none";
34670             (function(){
34671                 if (obj.readyState == 4) {
34672                     obj.parentNode.removeChild(obj);
34673                 }
34674                 else {
34675                     setTimeout(arguments.callee, 10);
34676                 }
34677             })();
34678         }
34679         else {
34680             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
34681         }
34682     } 
34683
34684     function abstractAltContent(obj) {
34685         var ac = createElement("div");
34686         if (ua.win && ua.ie) {
34687             ac.innerHTML = obj.innerHTML;
34688         }
34689         else {
34690             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
34691             if (nestedObj) {
34692                 var c = nestedObj.childNodes;
34693                 if (c) {
34694                     var cl = c.length;
34695                     for (var i = 0; i < cl; i++) {
34696                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
34697                             ac.appendChild(c[i].cloneNode(true));
34698                         }
34699                     }
34700                 }
34701             }
34702         }
34703         return ac;
34704     }
34705     
34706     
34707     function createSWF(attObj, parObj, id) {
34708         var r, el = getElementById(id);
34709         if (ua.wk && ua.wk < 312) { return r; }
34710         if (el) {
34711             if (typeof attObj.id == UNDEF) { 
34712                 attObj.id = id;
34713             }
34714             if (ua.ie && ua.win) { 
34715                 var att = "";
34716                 for (var i in attObj) {
34717                     if (attObj[i] != Object.prototype[i]) { 
34718                         if (i.toLowerCase() == "data") {
34719                             parObj.movie = attObj[i];
34720                         }
34721                         else if (i.toLowerCase() == "styleclass") { 
34722                             att += ' class="' + attObj[i] + '"';
34723                         }
34724                         else if (i.toLowerCase() != "classid") {
34725                             att += ' ' + i + '="' + attObj[i] + '"';
34726                         }
34727                     }
34728                 }
34729                 var par = "";
34730                 for (var j in parObj) {
34731                     if (parObj[j] != Object.prototype[j]) { 
34732                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
34733                     }
34734                 }
34735                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
34736                 objIdArr[objIdArr.length] = attObj.id; 
34737                 r = getElementById(attObj.id);  
34738             }
34739             else { 
34740                 var o = createElement(OBJECT);
34741                 o.setAttribute("type", FLASH_MIME_TYPE);
34742                 for (var m in attObj) {
34743                     if (attObj[m] != Object.prototype[m]) { 
34744                         if (m.toLowerCase() == "styleclass") { 
34745                             o.setAttribute("class", attObj[m]);
34746                         }
34747                         else if (m.toLowerCase() != "classid") { 
34748                             o.setAttribute(m, attObj[m]);
34749                         }
34750                     }
34751                 }
34752                 for (var n in parObj) {
34753                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
34754                         createObjParam(o, n, parObj[n]);
34755                     }
34756                 }
34757                 el.parentNode.replaceChild(o, el);
34758                 r = o;
34759             }
34760         }
34761         return r;
34762     }
34763     
34764     function createObjParam(el, pName, pValue) {
34765         var p = createElement("param");
34766         p.setAttribute("name", pName);  
34767         p.setAttribute("value", pValue);
34768         el.appendChild(p);
34769     }
34770     
34771     
34772     function removeSWF(id) {
34773         var obj = getElementById(id);
34774         if (obj && obj.nodeName == "OBJECT") {
34775             if (ua.ie && ua.win) {
34776                 obj.style.display = "none";
34777                 (function(){
34778                     if (obj.readyState == 4) {
34779                         removeObjectInIE(id);
34780                     }
34781                     else {
34782                         setTimeout(arguments.callee, 10);
34783                     }
34784                 })();
34785             }
34786             else {
34787                 obj.parentNode.removeChild(obj);
34788             }
34789         }
34790     }
34791     
34792     function removeObjectInIE(id) {
34793         var obj = getElementById(id);
34794         if (obj) {
34795             for (var i in obj) {
34796                 if (typeof obj[i] == "function") {
34797                     obj[i] = null;
34798                 }
34799             }
34800             obj.parentNode.removeChild(obj);
34801         }
34802     }
34803     
34804     
34805     function getElementById(id) {
34806         var el = null;
34807         try {
34808             el = doc.getElementById(id);
34809         }
34810         catch (e) {}
34811         return el;
34812     }
34813     
34814     function createElement(el) {
34815         return doc.createElement(el);
34816     }
34817     
34818       
34819     function addListener(target, eventType, fn) {
34820         target.attachEvent(eventType, fn);
34821         listenersArr[listenersArr.length] = [target, eventType, fn];
34822     }
34823     
34824     
34825     function hasPlayerVersion(rv) {
34826         var pv = ua.pv, v = rv.split(".");
34827         v[0] = parseInt(v[0], 10);
34828         v[1] = parseInt(v[1], 10) || 0; 
34829         v[2] = parseInt(v[2], 10) || 0;
34830         return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
34831     }
34832     
34833       
34834     function createCSS(sel, decl, media, newStyle) {
34835         if (ua.ie && ua.mac) { return; }
34836         var h = doc.getElementsByTagName("head")[0];
34837         if (!h) { return; } 
34838         var m = (media && typeof media == "string") ? media : "screen";
34839         if (newStyle) {
34840             dynamicStylesheet = null;
34841             dynamicStylesheetMedia = null;
34842         }
34843         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
34844             
34845             var s = createElement("style");
34846             s.setAttribute("type", "text/css");
34847             s.setAttribute("media", m);
34848             dynamicStylesheet = h.appendChild(s);
34849             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
34850                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
34851             }
34852             dynamicStylesheetMedia = m;
34853         }
34854         
34855         if (ua.ie && ua.win) {
34856             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
34857                 dynamicStylesheet.addRule(sel, decl);
34858             }
34859         }
34860         else {
34861             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
34862                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
34863             }
34864         }
34865     }
34866     
34867     function setVisibility(id, isVisible) {
34868         if (!autoHideShow) { return; }
34869         var v = isVisible ? "visible" : "hidden";
34870         if (isDomLoaded && getElementById(id)) {
34871             getElementById(id).style.visibility = v;
34872         }
34873         else {
34874             createCSS("#" + id, "visibility:" + v);
34875         }
34876     }
34877
34878     
34879     function urlEncodeIfNecessary(s) {
34880         var regex = /[\\\"<>\.;]/;
34881         var hasBadChars = regex.exec(s) != null;
34882         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
34883     }
34884     
34885     
34886     var cleanup = function() {
34887         if (ua.ie && ua.win) {
34888             window.attachEvent("onunload", function() {
34889                 
34890                 var ll = listenersArr.length;
34891                 for (var i = 0; i < ll; i++) {
34892                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
34893                 }
34894                 
34895                 var il = objIdArr.length;
34896                 for (var j = 0; j < il; j++) {
34897                     removeSWF(objIdArr[j]);
34898                 }
34899                 
34900                 for (var k in ua) {
34901                     ua[k] = null;
34902                 }
34903                 ua = null;
34904                 for (var l in swfobject) {
34905                     swfobject[l] = null;
34906                 }
34907                 swfobject = null;
34908             });
34909         }
34910     }();
34911     
34912     return {
34913          
34914         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
34915             if (ua.w3 && objectIdStr && swfVersionStr) {
34916                 var regObj = {};
34917                 regObj.id = objectIdStr;
34918                 regObj.swfVersion = swfVersionStr;
34919                 regObj.expressInstall = xiSwfUrlStr;
34920                 regObj.callbackFn = callbackFn;
34921                 regObjArr[regObjArr.length] = regObj;
34922                 setVisibility(objectIdStr, false);
34923             }
34924             else if (callbackFn) {
34925                 callbackFn({success:false, id:objectIdStr});
34926             }
34927         },
34928         
34929         getObjectById: function(objectIdStr) {
34930             if (ua.w3) {
34931                 return getObjectById(objectIdStr);
34932             }
34933         },
34934         
34935         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
34936             var callbackObj = {success:false, id:replaceElemIdStr};
34937             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
34938                 setVisibility(replaceElemIdStr, false);
34939                 addDomLoadEvent(function() {
34940                     widthStr += ""; 
34941                     heightStr += "";
34942                     var att = {};
34943                     if (attObj && typeof attObj === OBJECT) {
34944                         for (var i in attObj) { 
34945                             att[i] = attObj[i];
34946                         }
34947                     }
34948                     att.data = swfUrlStr;
34949                     att.width = widthStr;
34950                     att.height = heightStr;
34951                     var par = {}; 
34952                     if (parObj && typeof parObj === OBJECT) {
34953                         for (var j in parObj) { 
34954                             par[j] = parObj[j];
34955                         }
34956                     }
34957                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
34958                         for (var k in flashvarsObj) { 
34959                             if (typeof par.flashvars != UNDEF) {
34960                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
34961                             }
34962                             else {
34963                                 par.flashvars = k + "=" + flashvarsObj[k];
34964                             }
34965                         }
34966                     }
34967                     if (hasPlayerVersion(swfVersionStr)) { 
34968                         var obj = createSWF(att, par, replaceElemIdStr);
34969                         if (att.id == replaceElemIdStr) {
34970                             setVisibility(replaceElemIdStr, true);
34971                         }
34972                         callbackObj.success = true;
34973                         callbackObj.ref = obj;
34974                     }
34975                     else if (xiSwfUrlStr && canExpressInstall()) { 
34976                         att.data = xiSwfUrlStr;
34977                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
34978                         return;
34979                     }
34980                     else { 
34981                         setVisibility(replaceElemIdStr, true);
34982                     }
34983                     if (callbackFn) { callbackFn(callbackObj); }
34984                 });
34985             }
34986             else if (callbackFn) { callbackFn(callbackObj); }
34987         },
34988         
34989         switchOffAutoHideShow: function() {
34990             autoHideShow = false;
34991         },
34992         
34993         ua: ua,
34994         
34995         getFlashPlayerVersion: function() {
34996             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
34997         },
34998         
34999         hasFlashPlayerVersion: hasPlayerVersion,
35000         
35001         createSWF: function(attObj, parObj, replaceElemIdStr) {
35002             if (ua.w3) {
35003                 return createSWF(attObj, parObj, replaceElemIdStr);
35004             }
35005             else {
35006                 return undefined;
35007             }
35008         },
35009         
35010         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
35011             if (ua.w3 && canExpressInstall()) {
35012                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
35013             }
35014         },
35015         
35016         removeSWF: function(objElemIdStr) {
35017             if (ua.w3) {
35018                 removeSWF(objElemIdStr);
35019             }
35020         },
35021         
35022         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
35023             if (ua.w3) {
35024                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
35025             }
35026         },
35027         
35028         addDomLoadEvent: addDomLoadEvent,
35029         
35030         addLoadEvent: addLoadEvent,
35031         
35032         getQueryParamValue: function(param) {
35033             var q = doc.location.search || doc.location.hash;
35034             if (q) {
35035                 if (/\?/.test(q)) { q = q.split("?")[1]; } 
35036                 if (param == null) {
35037                     return urlEncodeIfNecessary(q);
35038                 }
35039                 var pairs = q.split("&");
35040                 for (var i = 0; i < pairs.length; i++) {
35041                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
35042                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
35043                     }
35044                 }
35045             }
35046             return "";
35047         },
35048         
35049         
35050         expressInstallCallback: function() {
35051             if (isExpressInstallActive) {
35052                 var obj = getElementById(EXPRESS_INSTALL_ID);
35053                 if (obj && storedAltContent) {
35054                     obj.parentNode.replaceChild(storedAltContent, obj);
35055                     if (storedAltContentId) {
35056                         setVisibility(storedAltContentId, true);
35057                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
35058                     }
35059                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
35060                 }
35061                 isExpressInstallActive = false;
35062             } 
35063         }
35064     };
35065 }();
35066
35067 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
35068     
35069     flashVersion : '9.0.115',
35070
35071     
35072     backgroundColor: '#ffffff',
35073
35074     
35075     wmode: 'opaque',
35076
35077     
35078     flashVars: undefined,
35079
35080     
35081     flashParams: undefined,
35082
35083     
35084     url: undefined,
35085     swfId : undefined,
35086     swfWidth: '100%',
35087     swfHeight: '100%',
35088
35089     
35090     expressInstall: false,
35091
35092     initComponent : function(){
35093         Ext.FlashComponent.superclass.initComponent.call(this);
35094
35095         this.addEvents(
35096             
35097             'initialize'
35098         );
35099     },
35100
35101     onRender : function(){
35102         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
35103
35104         var params = Ext.apply({
35105             allowScriptAccess: 'always',
35106             bgcolor: this.backgroundColor,
35107             wmode: this.wmode
35108         }, this.flashParams), vars = Ext.apply({
35109             allowedDomain: document.location.hostname,
35110             YUISwfId: this.getId(),
35111             YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
35112         }, this.flashVars);
35113
35114         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
35115             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
35116
35117         this.swf = Ext.getDom(this.id);
35118         this.el = Ext.get(this.swf);
35119     },
35120
35121     getSwfId : function(){
35122         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
35123     },
35124
35125     getId : function(){
35126         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
35127     },
35128
35129     onFlashEvent : function(e){
35130         switch(e.type){
35131             case "swfReady":
35132                 this.initSwf();
35133                 return;
35134             case "log":
35135                 return;
35136         }
35137         e.component = this;
35138         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
35139     },
35140
35141     initSwf : function(){
35142         this.onSwfReady(!!this.isInitialized);
35143         this.isInitialized = true;
35144         this.fireEvent('initialize', this);
35145     },
35146
35147     beforeDestroy: function(){
35148         if(this.rendered){
35149             swfobject.removeSWF(this.swf.id);
35150         }
35151         Ext.FlashComponent.superclass.beforeDestroy.call(this);
35152     },
35153
35154     onSwfReady : Ext.emptyFn
35155 });
35156
35157
35158 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
35159
35160 Ext.reg('flash', Ext.FlashComponent);
35161 Ext.FlashEventProxy = {
35162     onEvent : function(id, e){
35163         var fp = Ext.getCmp(id);
35164         if(fp){
35165             fp.onFlashEvent(e);
35166         }else{
35167             arguments.callee.defer(10, this, [id, e]);
35168         }
35169     }
35170 };
35171
35172  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
35173     refreshBuffer: 100,
35174
35175     
35176
35177     
35178     chartStyle: {
35179         padding: 10,
35180         animationEnabled: true,
35181         font: {
35182             name: 'Tahoma',
35183             color: 0x444444,
35184             size: 11
35185         },
35186         dataTip: {
35187             padding: 5,
35188             border: {
35189                 color: 0x99bbe8,
35190                 size:1
35191             },
35192             background: {
35193                 color: 0xDAE7F6,
35194                 alpha: .9
35195             },
35196             font: {
35197                 name: 'Tahoma',
35198                 color: 0x15428B,
35199                 size: 10,
35200                 bold: true
35201             }
35202         }
35203     },
35204
35205     
35206
35207     
35208     extraStyle: null,
35209
35210     
35211     seriesStyles: null,
35212
35213     
35214     disableCaching: Ext.isIE || Ext.isOpera,
35215     disableCacheParam: '_dc',
35216
35217     initComponent : function(){
35218         Ext.chart.Chart.superclass.initComponent.call(this);
35219         if(!this.url){
35220             this.url = Ext.chart.Chart.CHART_URL;
35221         }
35222         if(this.disableCaching){
35223             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
35224         }
35225         this.addEvents(
35226             'itemmouseover',
35227             'itemmouseout',
35228             'itemclick',
35229             'itemdoubleclick',
35230             'itemdragstart',
35231             'itemdrag',
35232             'itemdragend',
35233             
35234             'beforerefresh',
35235             
35236             'refresh'
35237         );
35238         this.store = Ext.StoreMgr.lookup(this.store);
35239     },
35240
35241     
35242      setStyle: function(name, value){
35243          this.swf.setStyle(name, Ext.encode(value));
35244      },
35245
35246     
35247     setStyles: function(styles){
35248         this.swf.setStyles(Ext.encode(styles));
35249     },
35250
35251     
35252     setSeriesStyles: function(styles){
35253         this.seriesStyles = styles;
35254         var s = [];
35255         Ext.each(styles, function(style){
35256             s.push(Ext.encode(style));
35257         });
35258         this.swf.setSeriesStyles(s);
35259     },
35260
35261     setCategoryNames : function(names){
35262         this.swf.setCategoryNames(names);
35263     },
35264
35265     setLegendRenderer : function(fn, scope){
35266         var chart = this;
35267         scope = scope || chart;
35268         chart.removeFnProxy(chart.legendFnName);
35269         chart.legendFnName = chart.createFnProxy(function(name){
35270             return fn.call(scope, name);
35271         });
35272         chart.swf.setLegendLabelFunction(chart.legendFnName);
35273     },
35274
35275     setTipRenderer : function(fn, scope){
35276         var chart = this;
35277         scope = scope || chart;
35278         chart.removeFnProxy(chart.tipFnName);
35279         chart.tipFnName = chart.createFnProxy(function(item, index, series){
35280             var record = chart.store.getAt(index);
35281             return fn.call(scope, chart, record, index, series);
35282         });
35283         chart.swf.setDataTipFunction(chart.tipFnName);
35284     },
35285
35286     setSeries : function(series){
35287         this.series = series;
35288         this.refresh();
35289     },
35290
35291     
35292     bindStore : function(store, initial){
35293         if(!initial && this.store){
35294             if(store !== this.store && this.store.autoDestroy){
35295                 this.store.destroy();
35296             }else{
35297                 this.store.un("datachanged", this.refresh, this);
35298                 this.store.un("add", this.delayRefresh, this);
35299                 this.store.un("remove", this.delayRefresh, this);
35300                 this.store.un("update", this.delayRefresh, this);
35301                 this.store.un("clear", this.refresh, this);
35302             }
35303         }
35304         if(store){
35305             store = Ext.StoreMgr.lookup(store);
35306             store.on({
35307                 scope: this,
35308                 datachanged: this.refresh,
35309                 add: this.delayRefresh,
35310                 remove: this.delayRefresh,
35311                 update: this.delayRefresh,
35312                 clear: this.refresh
35313             });
35314         }
35315         this.store = store;
35316         if(store && !initial){
35317             this.refresh();
35318         }
35319     },
35320
35321     onSwfReady : function(isReset){
35322         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
35323         var ref;
35324         this.swf.setType(this.type);
35325
35326         if(this.chartStyle){
35327             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
35328         }
35329
35330         if(this.categoryNames){
35331             this.setCategoryNames(this.categoryNames);
35332         }
35333
35334         if(this.tipRenderer){
35335             ref = this.getFunctionRef(this.tipRenderer);
35336             this.setTipRenderer(ref.fn, ref.scope);
35337         }
35338         if(this.legendRenderer){
35339             ref = this.getFunctionRef(this.legendRenderer);
35340             this.setLegendRenderer(ref.fn, ref.scope);
35341         }
35342         if(!isReset){
35343             this.bindStore(this.store, true);
35344         }
35345         this.refresh.defer(10, this);
35346     },
35347
35348     delayRefresh : function(){
35349         if(!this.refreshTask){
35350             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
35351         }
35352         this.refreshTask.delay(this.refreshBuffer);
35353     },
35354
35355     refresh : function(){
35356         if(this.fireEvent('beforerefresh', this) !== false){
35357             var styleChanged = false;
35358             
35359             var data = [], rs = this.store.data.items;
35360             for(var j = 0, len = rs.length; j < len; j++){
35361                 data[j] = rs[j].data;
35362             }
35363             
35364             
35365             var dataProvider = [];
35366             var seriesCount = 0;
35367             var currentSeries = null;
35368             var i = 0;
35369             if(this.series){
35370                 seriesCount = this.series.length;
35371                 for(i = 0; i < seriesCount; i++){
35372                     currentSeries = this.series[i];
35373                     var clonedSeries = {};
35374                     for(var prop in currentSeries){
35375                         if(prop == "style" && currentSeries.style !== null){
35376                             clonedSeries.style = Ext.encode(currentSeries.style);
35377                             styleChanged = true;
35378                             
35379                             
35380                             
35381                             
35382                         } else{
35383                             clonedSeries[prop] = currentSeries[prop];
35384                         }
35385                     }
35386                     dataProvider.push(clonedSeries);
35387                 }
35388             }
35389
35390             if(seriesCount > 0){
35391                 for(i = 0; i < seriesCount; i++){
35392                     currentSeries = dataProvider[i];
35393                     if(!currentSeries.type){
35394                         currentSeries.type = this.type;
35395                     }
35396                     currentSeries.dataProvider = data;
35397                 }
35398             } else{
35399                 dataProvider.push({type: this.type, dataProvider: data});
35400             }
35401             this.swf.setDataProvider(dataProvider);
35402             if(this.seriesStyles){
35403                 this.setSeriesStyles(this.seriesStyles);
35404             }
35405             this.fireEvent('refresh', this);
35406         }
35407     },
35408
35409     
35410     createFnProxy : function(fn){
35411         var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
35412         Ext.chart.Chart.proxyFunction[fnName] = fn;
35413         return 'Ext.chart.Chart.proxyFunction.' + fnName;
35414     },
35415
35416     
35417     removeFnProxy : function(fn){
35418         if(!Ext.isEmpty(fn)){
35419             fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
35420             delete Ext.chart.Chart.proxyFunction[fn];
35421         }
35422     },
35423
35424     
35425     getFunctionRef : function(val){
35426         if(Ext.isFunction(val)){
35427             return {
35428                 fn: val,
35429                 scope: this
35430             };
35431         }else{
35432             return {
35433                 fn: val.fn,
35434                 scope: val.scope || this
35435             }
35436         }
35437     },
35438
35439     
35440     onDestroy: function(){
35441         if (this.refreshTask && this.refreshTask.cancel){
35442             this.refreshTask.cancel();
35443         }
35444         Ext.chart.Chart.superclass.onDestroy.call(this);
35445         this.bindStore(null);
35446         this.removeFnProxy(this.tipFnName);
35447         this.removeFnProxy(this.legendFnName);
35448     }
35449 });
35450 Ext.reg('chart', Ext.chart.Chart);
35451 Ext.chart.Chart.PROXY_FN_ID = 0;
35452 Ext.chart.Chart.proxyFunction = {};
35453
35454
35455 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.0/build/charts/assets/charts.swf';
35456
35457
35458 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
35459     type: 'pie',
35460
35461     onSwfReady : function(isReset){
35462         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
35463
35464         this.setDataField(this.dataField);
35465         this.setCategoryField(this.categoryField);
35466     },
35467
35468     setDataField : function(field){
35469         this.dataField = field;
35470         this.swf.setDataField(field);
35471     },
35472
35473     setCategoryField : function(field){
35474         this.categoryField = field;
35475         this.swf.setCategoryField(field);
35476     }
35477 });
35478 Ext.reg('piechart', Ext.chart.PieChart);
35479
35480
35481 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
35482     onSwfReady : function(isReset){
35483         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
35484         this.labelFn = [];
35485         if(this.xField){
35486             this.setXField(this.xField);
35487         }
35488         if(this.yField){
35489             this.setYField(this.yField);
35490         }
35491         if(this.xAxis){
35492             this.setXAxis(this.xAxis);
35493         }
35494         if(this.xAxes){
35495             this.setXAxes(this.xAxes);
35496         }
35497         if(this.yAxis){
35498             this.setYAxis(this.yAxis);
35499         }
35500         if(this.yAxes){
35501             this.setYAxes(this.yAxes);
35502         }
35503         if(Ext.isDefined(this.constrainViewport)){
35504             this.swf.setConstrainViewport(this.constrainViewport);
35505         }
35506     },
35507
35508     setXField : function(value){
35509         this.xField = value;
35510         this.swf.setHorizontalField(value);
35511     },
35512
35513     setYField : function(value){
35514         this.yField = value;
35515         this.swf.setVerticalField(value);
35516     },
35517
35518     setXAxis : function(value){
35519         this.xAxis = this.createAxis('xAxis', value);
35520         this.swf.setHorizontalAxis(this.xAxis);
35521     },
35522
35523     setXAxes : function(value){
35524         var axis;
35525         for(var i = 0; i < value.length; i++) {
35526             axis = this.createAxis('xAxis' + i, value[i]);
35527             this.swf.setHorizontalAxis(axis);
35528         }
35529     },
35530
35531     setYAxis : function(value){
35532         this.yAxis = this.createAxis('yAxis', value);
35533         this.swf.setVerticalAxis(this.yAxis);
35534     },
35535
35536     setYAxes : function(value){
35537         var axis;
35538         for(var i = 0; i < value.length; i++) {
35539             axis = this.createAxis('yAxis' + i, value[i]);
35540             this.swf.setVerticalAxis(axis);
35541         }
35542     },
35543
35544     createAxis : function(axis, value){
35545         var o = Ext.apply({}, value),
35546             ref,
35547             old;
35548
35549         if(this[axis]){
35550             old = this[axis].labelFunction;
35551             this.removeFnProxy(old);
35552             this.labelFn.remove(old);
35553         }
35554         if(o.labelRenderer){
35555             ref = this.getFunctionRef(o.labelRenderer);
35556             o.labelFunction = this.createFnProxy(function(v){
35557                 return ref.fn.call(ref.scope, v);
35558             });
35559             delete o.labelRenderer;
35560             this.labelFn.push(o.labelFunction);
35561         }
35562         if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
35563             o.position = 'bottom';
35564         }
35565         return o;
35566     },
35567
35568     onDestroy : function(){
35569         Ext.chart.CartesianChart.superclass.onDestroy.call(this);
35570         Ext.each(this.labelFn, function(fn){
35571             this.removeFnProxy(fn);
35572         }, this);
35573     }
35574 });
35575 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
35576
35577
35578 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
35579     type: 'line'
35580 });
35581 Ext.reg('linechart', Ext.chart.LineChart);
35582
35583
35584 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
35585     type: 'column'
35586 });
35587 Ext.reg('columnchart', Ext.chart.ColumnChart);
35588
35589
35590 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
35591     type: 'stackcolumn'
35592 });
35593 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
35594
35595
35596 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
35597     type: 'bar'
35598 });
35599 Ext.reg('barchart', Ext.chart.BarChart);
35600
35601
35602 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
35603     type: 'stackbar'
35604 });
35605 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
35606
35607
35608
35609
35610 Ext.chart.Axis = function(config){
35611     Ext.apply(this, config);
35612 };
35613
35614 Ext.chart.Axis.prototype =
35615 {
35616     
35617     type: null,
35618
35619     
35620     orientation: "horizontal",
35621
35622     
35623     reverse: false,
35624
35625     
35626     labelFunction: null,
35627
35628     
35629     hideOverlappingLabels: true,
35630
35631     
35632     labelSpacing: 2
35633 };
35634
35635
35636 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
35637     type: "numeric",
35638
35639     
35640     minimum: NaN,
35641
35642     
35643     maximum: NaN,
35644
35645     
35646     majorUnit: NaN,
35647
35648     
35649     minorUnit: NaN,
35650
35651     
35652     snapToUnits: true,
35653
35654     
35655     alwaysShowZero: true,
35656
35657     
35658     scale: "linear",
35659
35660     
35661     roundMajorUnit: true,
35662
35663     
35664     calculateByLabelSize: true,
35665
35666     
35667     position: 'left',
35668
35669     
35670     adjustMaximumByMajorUnit: true,
35671
35672     
35673     adjustMinimumByMajorUnit: true
35674
35675 });
35676
35677
35678 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
35679     type: "time",
35680
35681     
35682     minimum: null,
35683
35684     
35685     maximum: null,
35686
35687     
35688     majorUnit: NaN,
35689
35690     
35691     majorTimeUnit: null,
35692
35693     
35694     minorUnit: NaN,
35695
35696     
35697     minorTimeUnit: null,
35698
35699     
35700     snapToUnits: true,
35701
35702     
35703     stackingEnabled: false,
35704
35705     
35706     calculateByLabelSize: true
35707
35708 });
35709
35710
35711 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
35712     type: "category",
35713
35714     
35715     categoryNames: null,
35716
35717     
35718     calculateCategoryCount: false
35719
35720 });
35721
35722
35723 Ext.chart.Series = function(config) { Ext.apply(this, config); };
35724
35725 Ext.chart.Series.prototype =
35726 {
35727     
35728     type: null,
35729
35730     
35731     displayName: null
35732 };
35733
35734
35735 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
35736     
35737     xField: null,
35738
35739     
35740     yField: null,
35741
35742     
35743     showInLegend: true,
35744
35745     
35746     axis: 'primary'
35747 });
35748
35749
35750 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
35751     type: "column"
35752 });
35753
35754
35755 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
35756     type: "line"
35757 });
35758
35759
35760 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
35761     type: "bar"
35762 });
35763
35764
35765
35766 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
35767     type: "pie",
35768     dataField: null,
35769     categoryField: null
35770 });
35771 Ext.menu.Menu = Ext.extend(Ext.Container, {
35772     
35773     
35774     
35775     minWidth : 120,
35776     
35777     shadow : 'sides',
35778     
35779     subMenuAlign : 'tl-tr?',
35780     
35781     defaultAlign : 'tl-bl?',
35782     
35783     allowOtherMenus : false,
35784     
35785     ignoreParentClicks : false,
35786     
35787     enableScrolling : true,
35788     
35789     maxHeight : null,
35790     
35791     scrollIncrement : 24,
35792     
35793     showSeparator : true,
35794     
35795     defaultOffsets : [0, 0],
35796
35797     
35798     plain : false,
35799
35800     
35801     floating : true,
35802
35803
35804     
35805     zIndex: 15000,
35806
35807     
35808     hidden : true,
35809
35810     
35811     layout : 'menu',
35812     hideMode : 'offsets',    
35813     scrollerHeight : 8,
35814     autoLayout : true,       
35815     defaultType : 'menuitem',
35816     bufferResize : false,
35817
35818     initComponent : function(){
35819         if(Ext.isArray(this.initialConfig)){
35820             Ext.apply(this, {items:this.initialConfig});
35821         }
35822         this.addEvents(
35823             
35824             'click',
35825             
35826             'mouseover',
35827             
35828             'mouseout',
35829             
35830             'itemclick'
35831         );
35832         Ext.menu.MenuMgr.register(this);
35833         if(this.floating){
35834             Ext.EventManager.onWindowResize(this.hide, this);
35835         }else{
35836             if(this.initialConfig.hidden !== false){
35837                 this.hidden = false;
35838             }
35839             this.internalDefaults = {hideOnClick: false};
35840         }
35841         Ext.menu.Menu.superclass.initComponent.call(this);
35842         if(this.autoLayout){
35843             var fn = this.doLayout.createDelegate(this, []);
35844             this.on({
35845                 add: fn,
35846                 remove: fn
35847             });
35848         }
35849     },
35850
35851     
35852     getLayoutTarget : function() {
35853         return this.ul;
35854     },
35855
35856     
35857     onRender : function(ct, position){
35858         if(!ct){
35859             ct = Ext.getBody();
35860         }
35861
35862         var dh = {
35863             id: this.getId(),
35864             cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
35865             style: this.style,
35866             cn: [
35867                 {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
35868                 {tag: 'ul', cls: 'x-menu-list'}
35869             ]
35870         };
35871         if(this.floating){
35872             this.el = new Ext.Layer({
35873                 shadow: this.shadow,
35874                 dh: dh,
35875                 constrain: false,
35876                 parentEl: ct,
35877                 zindex: this.zIndex
35878             });
35879         }else{
35880             this.el = ct.createChild(dh);
35881         }
35882         Ext.menu.Menu.superclass.onRender.call(this, ct, position);
35883
35884         if(!this.keyNav){
35885             this.keyNav = new Ext.menu.MenuNav(this);
35886         }
35887         
35888         this.focusEl = this.el.child('a.x-menu-focus');
35889         this.ul = this.el.child('ul.x-menu-list');
35890         this.mon(this.ul, {
35891             scope: this,
35892             click: this.onClick,
35893             mouseover: this.onMouseOver,
35894             mouseout: this.onMouseOut
35895         });
35896         if(this.enableScrolling){
35897             this.mon(this.el, {
35898                 scope: this,
35899                 delegate: '.x-menu-scroller',
35900                 click: this.onScroll,
35901                 mouseover: this.deactivateActive
35902             });
35903         }
35904     },
35905
35906     
35907     findTargetItem : function(e){
35908         var t = e.getTarget('.x-menu-list-item', this.ul, true);
35909         if(t && t.menuItemId){
35910             return this.items.get(t.menuItemId);
35911         }
35912     },
35913
35914     
35915     onClick : function(e){
35916         var t = this.findTargetItem(e);
35917         if(t){
35918             if(t.isFormField){
35919                 this.setActiveItem(t);
35920             }else if(t instanceof Ext.menu.BaseItem){
35921                 if(t.menu && this.ignoreParentClicks){
35922                     t.expandMenu();
35923                     e.preventDefault();
35924                 }else if(t.onClick){
35925                     t.onClick(e);
35926                     this.fireEvent('click', this, t, e);
35927                 }
35928             }
35929         }
35930     },
35931
35932     
35933     setActiveItem : function(item, autoExpand){
35934         if(item != this.activeItem){
35935             this.deactivateActive();
35936             if((this.activeItem = item).isFormField){
35937                 item.focus();
35938             }else{
35939                 item.activate(autoExpand);
35940             }
35941         }else if(autoExpand){
35942             item.expandMenu();
35943         }
35944     },
35945
35946     deactivateActive : function(){
35947         var a = this.activeItem;
35948         if(a){
35949             if(a.isFormField){
35950                 
35951                 if(a.collapse){
35952                     a.collapse();
35953                 }
35954             }else{
35955                 a.deactivate();
35956             }
35957             delete this.activeItem;
35958         }
35959     },
35960
35961     
35962     tryActivate : function(start, step){
35963         var items = this.items;
35964         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
35965             var item = items.get(i);
35966             if(!item.disabled && (item.canActivate || item.isFormField)){
35967                 this.setActiveItem(item, false);
35968                 return item;
35969             }
35970         }
35971         return false;
35972     },
35973
35974     
35975     onMouseOver : function(e){
35976         var t = this.findTargetItem(e);
35977         if(t){
35978             if(t.canActivate && !t.disabled){
35979                 this.setActiveItem(t, true);
35980             }
35981         }
35982         this.over = true;
35983         this.fireEvent('mouseover', this, e, t);
35984     },
35985
35986     
35987     onMouseOut : function(e){
35988         var t = this.findTargetItem(e);
35989         if(t){
35990             if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
35991                 this.activeItem.deactivate();
35992                 delete this.activeItem;
35993             }
35994         }
35995         this.over = false;
35996         this.fireEvent('mouseout', this, e, t);
35997     },
35998
35999     
36000     onScroll : function(e, t){
36001         if(e){
36002             e.stopEvent();
36003         }
36004         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
36005         ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
36006         if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
36007            this.onScrollerOut(null, t);
36008         }
36009     },
36010
36011     
36012     onScrollerIn : function(e, t){
36013         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
36014         if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
36015             Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
36016         }
36017     },
36018
36019     
36020     onScrollerOut : function(e, t){
36021         Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
36022     },
36023
36024     
36025     show : function(el, pos, parentMenu){
36026         if(this.floating){
36027             this.parentMenu = parentMenu;
36028             if(!this.el){
36029                 this.render();
36030                 this.doLayout(false, true);
36031             }
36032             this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
36033         }else{
36034             Ext.menu.Menu.superclass.show.call(this);
36035         }
36036     },
36037
36038     
36039     showAt : function(xy, parentMenu){
36040         if(this.fireEvent('beforeshow', this) !== false){
36041             this.parentMenu = parentMenu;
36042             if(!this.el){
36043                 this.render();
36044             }
36045             if(this.enableScrolling){
36046                 
36047                 this.el.setXY(xy);
36048                 
36049                 xy[1] = this.constrainScroll(xy[1]);
36050                 xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
36051             }else{
36052                 
36053                 xy = this.el.adjustForConstraints(xy);
36054             }
36055             this.el.setXY(xy);
36056             this.el.show();
36057             Ext.menu.Menu.superclass.onShow.call(this);
36058             if(Ext.isIE){
36059                 
36060                 this.fireEvent('autosize', this);
36061                 if(!Ext.isIE8){
36062                     this.el.repaint();
36063                 }
36064             }
36065             this.hidden = false;
36066             this.focus();
36067             this.fireEvent('show', this);
36068         }
36069     },
36070
36071     constrainScroll : function(y){
36072         var max, full = this.ul.setHeight('auto').getHeight(),
36073             returnY = y, normalY, parentEl, scrollTop, viewHeight;
36074         if(this.floating){
36075             parentEl = Ext.fly(this.el.dom.parentNode);
36076             scrollTop = parentEl.getScroll().top;
36077             viewHeight = parentEl.getViewSize().height;
36078             
36079             
36080             normalY = y - scrollTop;
36081             max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
36082             if(full > viewHeight) {
36083                 max = viewHeight;
36084                 
36085                 returnY = y - normalY;
36086             } else if(max < full) {
36087                 returnY = y - (full - max);
36088                 max = full;
36089             }
36090         }else{
36091             max = this.getHeight();
36092         }
36093         
36094         if (this.maxHeight){
36095             max = Math.min(this.maxHeight, max);
36096         }
36097         if(full > max && max > 0){
36098             this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
36099             this.ul.setHeight(this.activeMax);
36100             this.createScrollers();
36101             this.el.select('.x-menu-scroller').setDisplayed('');
36102         }else{
36103             this.ul.setHeight(full);
36104             this.el.select('.x-menu-scroller').setDisplayed('none');
36105         }
36106         this.ul.dom.scrollTop = 0;
36107         return returnY;
36108     },
36109
36110     createScrollers : function(){
36111         if(!this.scroller){
36112             this.scroller = {
36113                 pos: 0,
36114                 top: this.el.insertFirst({
36115                     tag: 'div',
36116                     cls: 'x-menu-scroller x-menu-scroller-top',
36117                     html: '&#160;'
36118                 }),
36119                 bottom: this.el.createChild({
36120                     tag: 'div',
36121                     cls: 'x-menu-scroller x-menu-scroller-bottom',
36122                     html: '&#160;'
36123                 })
36124             };
36125             this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
36126             this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
36127                 listeners: {
36128                     click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
36129                 }
36130             });
36131             this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
36132             this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
36133                 listeners: {
36134                     click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
36135                 }
36136             });
36137         }
36138     },
36139
36140     onLayout : function(){
36141         if(this.isVisible()){
36142             if(this.enableScrolling){
36143                 this.constrainScroll(this.el.getTop());
36144             }
36145             if(this.floating){
36146                 this.el.sync();
36147             }
36148         }
36149     },
36150
36151     focus : function(){
36152         if(!this.hidden){
36153             this.doFocus.defer(50, this);
36154         }
36155     },
36156
36157     doFocus : function(){
36158         if(!this.hidden){
36159             this.focusEl.focus();
36160         }
36161     },
36162
36163     
36164     hide : function(deep){
36165         if (!this.isDestroyed) {
36166             this.deepHide = deep;
36167             Ext.menu.Menu.superclass.hide.call(this);
36168             delete this.deepHide;
36169         }
36170     },
36171
36172     
36173     onHide : function(){
36174         Ext.menu.Menu.superclass.onHide.call(this);
36175         this.deactivateActive();
36176         if(this.el && this.floating){
36177             this.el.hide();
36178         }
36179         var pm = this.parentMenu;
36180         if(this.deepHide === true && pm){
36181             if(pm.floating){
36182                 pm.hide(true);
36183             }else{
36184                 pm.deactivateActive();
36185             }
36186         }
36187     },
36188
36189     
36190     lookupComponent : function(c){
36191          if(Ext.isString(c)){
36192             c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
36193              this.applyDefaults(c);
36194          }else{
36195             if(Ext.isObject(c)){
36196                 c = this.getMenuItem(c);
36197             }else if(c.tagName || c.el){ 
36198                 c = new Ext.BoxComponent({
36199                     el: c
36200                 });
36201             }
36202          }
36203          return c;
36204     },
36205
36206     applyDefaults : function(c){
36207         if(!Ext.isString(c)){
36208             c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
36209             var d = this.internalDefaults;
36210             if(d){
36211                 if(c.events){
36212                     Ext.applyIf(c.initialConfig, d);
36213                     Ext.apply(c, d);
36214                 }else{
36215                     Ext.applyIf(c, d);
36216                 }
36217             }
36218         }
36219         return c;
36220     },
36221
36222     
36223     getMenuItem : function(config){
36224        if(!config.isXType){
36225             if(!config.xtype && Ext.isBoolean(config.checked)){
36226                 return new Ext.menu.CheckItem(config)
36227             }
36228             return Ext.create(config, this.defaultType);
36229         }
36230         return config;
36231     },
36232
36233     
36234     addSeparator : function(){
36235         return this.add(new Ext.menu.Separator());
36236     },
36237
36238     
36239     addElement : function(el){
36240         return this.add(new Ext.menu.BaseItem({
36241             el: el
36242         }));
36243     },
36244
36245     
36246     addItem : function(item){
36247         return this.add(item);
36248     },
36249
36250     
36251     addMenuItem : function(config){
36252         return this.add(this.getMenuItem(config));
36253     },
36254
36255     
36256     addText : function(text){
36257         return this.add(new Ext.menu.TextItem(text));
36258     },
36259
36260     
36261     onDestroy : function(){
36262         Ext.EventManager.removeResizeListener(this.hide, this);
36263         var pm = this.parentMenu;
36264         if(pm && pm.activeChild == this){
36265             delete pm.activeChild;
36266         }
36267         delete this.parentMenu;
36268         Ext.menu.Menu.superclass.onDestroy.call(this);
36269         Ext.menu.MenuMgr.unregister(this);
36270         if(this.keyNav) {
36271             this.keyNav.disable();
36272         }
36273         var s = this.scroller;
36274         if(s){
36275             Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
36276         }
36277         Ext.destroy(
36278             this.el,
36279             this.focusEl,
36280             this.ul
36281         );
36282     }
36283 });
36284
36285 Ext.reg('menu', Ext.menu.Menu);
36286
36287
36288 Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
36289     function up(e, m){
36290         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
36291             m.tryActivate(m.items.length-1, -1);
36292         }
36293     }
36294     function down(e, m){
36295         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
36296             m.tryActivate(0, 1);
36297         }
36298     }
36299     return {
36300         constructor : function(menu){
36301             Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
36302             this.scope = this.menu = menu;
36303         },
36304
36305         doRelay : function(e, h){
36306             var k = e.getKey();
36307
36308             if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
36309                 return false;
36310             }
36311             if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
36312                 this.menu.tryActivate(0, 1);
36313                 return false;
36314             }
36315             return h.call(this.scope || this, e, this.menu);
36316         },
36317
36318         tab: function(e, m) {
36319             e.stopEvent();
36320             if (e.shiftKey) {
36321                 up(e, m);
36322             } else {
36323                 down(e, m);
36324             }
36325         },
36326
36327         up : up,
36328
36329         down : down,
36330
36331         right : function(e, m){
36332             if(m.activeItem){
36333                 m.activeItem.expandMenu(true);
36334             }
36335         },
36336
36337         left : function(e, m){
36338             m.hide();
36339             if(m.parentMenu && m.parentMenu.activeItem){
36340                 m.parentMenu.activeItem.activate();
36341             }
36342         },
36343
36344         enter : function(e, m){
36345             if(m.activeItem){
36346                 e.stopPropagation();
36347                 m.activeItem.onClick(e);
36348                 m.fireEvent('click', this, m.activeItem);
36349                 return true;
36350             }
36351         }
36352     };
36353 }());
36354
36355 Ext.menu.MenuMgr = function(){
36356    var menus, active, groups = {}, attached = false, lastShow = new Date();
36357
36358    
36359    function init(){
36360        menus = {};
36361        active = new Ext.util.MixedCollection();
36362        Ext.getDoc().addKeyListener(27, function(){
36363            if(active.length > 0){
36364                hideAll();
36365            }
36366        });
36367    }
36368
36369    
36370    function hideAll(){
36371        if(active && active.length > 0){
36372            var c = active.clone();
36373            c.each(function(m){
36374                m.hide();
36375            });
36376            return true;
36377        }
36378        return false;
36379    }
36380
36381    
36382    function onHide(m){
36383        active.remove(m);
36384        if(active.length < 1){
36385            Ext.getDoc().un("mousedown", onMouseDown);
36386            attached = false;
36387        }
36388    }
36389
36390    
36391    function onShow(m){
36392        var last = active.last();
36393        lastShow = new Date();
36394        active.add(m);
36395        if(!attached){
36396            Ext.getDoc().on("mousedown", onMouseDown);
36397            attached = true;
36398        }
36399        if(m.parentMenu){
36400           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
36401           m.parentMenu.activeChild = m;
36402        }else if(last && !last.isDestroyed && last.isVisible()){
36403           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
36404        }
36405    }
36406
36407    
36408    function onBeforeHide(m){
36409        if(m.activeChild){
36410            m.activeChild.hide();
36411        }
36412        if(m.autoHideTimer){
36413            clearTimeout(m.autoHideTimer);
36414            delete m.autoHideTimer;
36415        }
36416    }
36417
36418    
36419    function onBeforeShow(m){
36420        var pm = m.parentMenu;
36421        if(!pm && !m.allowOtherMenus){
36422            hideAll();
36423        }else if(pm && pm.activeChild){
36424            pm.activeChild.hide();
36425        }
36426    }
36427
36428    
36429    function onMouseDown(e){
36430        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
36431            hideAll();
36432        }
36433    }
36434
36435    
36436    function onBeforeCheck(mi, state){
36437        if(state){
36438            var g = groups[mi.group];
36439            for(var i = 0, l = g.length; i < l; i++){
36440                if(g[i] != mi){
36441                    g[i].setChecked(false);
36442                }
36443            }
36444        }
36445    }
36446
36447    return {
36448
36449        
36450        hideAll : function(){
36451             return hideAll();
36452        },
36453
36454        
36455        register : function(menu){
36456            if(!menus){
36457                init();
36458            }
36459            menus[menu.id] = menu;
36460            menu.on({
36461                beforehide: onBeforeHide,
36462                hide: onHide,
36463                beforeshow: onBeforeShow,
36464                show: onShow
36465            });
36466        },
36467
36468         
36469        get : function(menu){
36470            if(typeof menu == "string"){ 
36471                if(!menus){  
36472                    return null;
36473                }
36474                return menus[menu];
36475            }else if(menu.events){  
36476                return menu;
36477            }else if(typeof menu.length == 'number'){ 
36478                return new Ext.menu.Menu({items:menu});
36479            }else{ 
36480                return Ext.create(menu, 'menu');
36481            }
36482        },
36483
36484        
36485        unregister : function(menu){
36486            delete menus[menu.id];
36487            menu.un("beforehide", onBeforeHide);
36488            menu.un("hide", onHide);
36489            menu.un("beforeshow", onBeforeShow);
36490            menu.un("show", onShow);
36491        },
36492
36493        
36494        registerCheckable : function(menuItem){
36495            var g = menuItem.group;
36496            if(g){
36497                if(!groups[g]){
36498                    groups[g] = [];
36499                }
36500                groups[g].push(menuItem);
36501                menuItem.on("beforecheckchange", onBeforeCheck);
36502            }
36503        },
36504
36505        
36506        unregisterCheckable : function(menuItem){
36507            var g = menuItem.group;
36508            if(g){
36509                groups[g].remove(menuItem);
36510                menuItem.un("beforecheckchange", onBeforeCheck);
36511            }
36512        },
36513
36514        getCheckedItem : function(groupId){
36515            var g = groups[groupId];
36516            if(g){
36517                for(var i = 0, l = g.length; i < l; i++){
36518                    if(g[i].checked){
36519                        return g[i];
36520                    }
36521                }
36522            }
36523            return null;
36524        },
36525
36526        setCheckedItem : function(groupId, itemId){
36527            var g = groups[groupId];
36528            if(g){
36529                for(var i = 0, l = g.length; i < l; i++){
36530                    if(g[i].id == itemId){
36531                        g[i].setChecked(true);
36532                    }
36533                }
36534            }
36535            return null;
36536        }
36537    };
36538 }();
36539
36540 Ext.menu.BaseItem = Ext.extend(Ext.Component, {
36541     
36542     
36543     
36544     
36545     canActivate : false,
36546     
36547     activeClass : "x-menu-item-active",
36548     
36549     hideOnClick : true,
36550     
36551     clickHideDelay : 1,
36552
36553     
36554     ctype : "Ext.menu.BaseItem",
36555
36556     
36557     actionMode : "container",
36558
36559     initComponent : function(){
36560         Ext.menu.BaseItem.superclass.initComponent.call(this);
36561         this.addEvents(
36562             
36563             'click',
36564             
36565             'activate',
36566             
36567             'deactivate'
36568         );
36569         if(this.handler){
36570             this.on("click", this.handler, this.scope);
36571         }
36572     },
36573
36574     
36575     onRender : function(container, position){
36576         Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
36577         if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
36578             this.parentMenu = this.ownerCt;
36579         }else{
36580             this.container.addClass('x-menu-list-item');
36581             this.mon(this.el, {
36582                 scope: this,
36583                 click: this.onClick,
36584                 mouseenter: this.activate,
36585                 mouseleave: this.deactivate
36586             });
36587         }
36588     },
36589
36590     
36591     setHandler : function(handler, scope){
36592         if(this.handler){
36593             this.un("click", this.handler, this.scope);
36594         }
36595         this.on("click", this.handler = handler, this.scope = scope);
36596     },
36597
36598     
36599     onClick : function(e){
36600         if(!this.disabled && this.fireEvent("click", this, e) !== false
36601                 && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
36602             this.handleClick(e);
36603         }else{
36604             e.stopEvent();
36605         }
36606     },
36607
36608     
36609     activate : function(){
36610         if(this.disabled){
36611             return false;
36612         }
36613         var li = this.container;
36614         li.addClass(this.activeClass);
36615         this.region = li.getRegion().adjust(2, 2, -2, -2);
36616         this.fireEvent("activate", this);
36617         return true;
36618     },
36619
36620     
36621     deactivate : function(){
36622         this.container.removeClass(this.activeClass);
36623         this.fireEvent("deactivate", this);
36624     },
36625
36626     
36627     shouldDeactivate : function(e){
36628         return !this.region || !this.region.contains(e.getPoint());
36629     },
36630
36631     
36632     handleClick : function(e){
36633         var pm = this.parentMenu;
36634         if(this.hideOnClick){
36635             if(pm.floating){
36636                 pm.hide.defer(this.clickHideDelay, pm, [true]);
36637             }else{
36638                 pm.deactivateActive();
36639             }
36640         }
36641     },
36642
36643     
36644     expandMenu : Ext.emptyFn,
36645
36646     
36647     hideMenu : Ext.emptyFn
36648 });
36649 Ext.reg('menubaseitem', Ext.menu.BaseItem);
36650 Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
36651     
36652     
36653     hideOnClick : false,
36654     
36655     itemCls : "x-menu-text",
36656     
36657     constructor : function(config){
36658         if(typeof config == 'string'){
36659             config = {text: config}
36660         }
36661         Ext.menu.TextItem.superclass.constructor.call(this, config);
36662     },
36663
36664     
36665     onRender : function(){
36666         var s = document.createElement("span");
36667         s.className = this.itemCls;
36668         s.innerHTML = this.text;
36669         this.el = s;
36670         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
36671     }
36672 });
36673 Ext.reg('menutextitem', Ext.menu.TextItem);
36674 Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
36675     
36676     itemCls : "x-menu-sep",
36677     
36678     hideOnClick : false,
36679     
36680     
36681     activeClass: '',
36682
36683     
36684     onRender : function(li){
36685         var s = document.createElement("span");
36686         s.className = this.itemCls;
36687         s.innerHTML = "&#160;";
36688         this.el = s;
36689         li.addClass("x-menu-sep-li");
36690         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
36691     }
36692 });
36693 Ext.reg('menuseparator', Ext.menu.Separator);
36694 Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
36695     
36696     
36697     
36698     
36699     
36700     
36701     
36702     
36703     itemCls : 'x-menu-item',
36704     
36705     canActivate : true,
36706     
36707     showDelay: 200,
36708     
36709     hideDelay: 200,
36710
36711     
36712     ctype: 'Ext.menu.Item',
36713
36714     initComponent : function(){
36715         Ext.menu.Item.superclass.initComponent.call(this);
36716         if(this.menu){
36717             this.menu = Ext.menu.MenuMgr.get(this.menu);
36718             this.menu.ownerCt = this;
36719         }
36720     },
36721
36722     
36723     onRender : function(container, position){
36724         if (!this.itemTpl) {
36725             this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
36726                 '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
36727                     '<tpl if="hrefTarget">',
36728                         ' target="{hrefTarget}"',
36729                     '</tpl>',
36730                  '>',
36731                      '<img src="{icon}" class="x-menu-item-icon {iconCls}"/>',
36732                      '<span class="x-menu-item-text">{text}</span>',
36733                  '</a>'
36734              );
36735         }
36736         var a = this.getTemplateArgs();
36737         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
36738         this.iconEl = this.el.child('img.x-menu-item-icon');
36739         this.textEl = this.el.child('.x-menu-item-text');
36740         if(!this.href) { 
36741             this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
36742         }
36743         Ext.menu.Item.superclass.onRender.call(this, container, position);
36744     },
36745
36746     getTemplateArgs: function() {
36747         return {
36748             id: this.id,
36749             cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
36750             href: this.href || '#',
36751             hrefTarget: this.hrefTarget,
36752             icon: this.icon || Ext.BLANK_IMAGE_URL,
36753             iconCls: this.iconCls || '',
36754             text: this.itemText||this.text||'&#160;'
36755         };
36756     },
36757
36758     
36759     setText : function(text){
36760         this.text = text||'&#160;';
36761         if(this.rendered){
36762             this.textEl.update(this.text);
36763             this.parentMenu.layout.doAutoSize();
36764         }
36765     },
36766
36767     
36768     setIconClass : function(cls){
36769         var oldCls = this.iconCls;
36770         this.iconCls = cls;
36771         if(this.rendered){
36772             this.iconEl.replaceClass(oldCls, this.iconCls);
36773         }
36774     },
36775
36776     
36777     beforeDestroy: function(){
36778         if (this.menu){
36779             delete this.menu.ownerCt;
36780             this.menu.destroy();
36781         }
36782         Ext.menu.Item.superclass.beforeDestroy.call(this);
36783     },
36784
36785     
36786     handleClick : function(e){
36787         if(!this.href){ 
36788             e.stopEvent();
36789         }
36790         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
36791     },
36792
36793     
36794     activate : function(autoExpand){
36795         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
36796             this.focus();
36797             if(autoExpand){
36798                 this.expandMenu();
36799             }
36800         }
36801         return true;
36802     },
36803
36804     
36805     shouldDeactivate : function(e){
36806         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
36807             if(this.menu && this.menu.isVisible()){
36808                 return !this.menu.getEl().getRegion().contains(e.getPoint());
36809             }
36810             return true;
36811         }
36812         return false;
36813     },
36814
36815     
36816     deactivate : function(){
36817         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
36818         this.hideMenu();
36819     },
36820
36821     
36822     expandMenu : function(autoActivate){
36823         if(!this.disabled && this.menu){
36824             clearTimeout(this.hideTimer);
36825             delete this.hideTimer;
36826             if(!this.menu.isVisible() && !this.showTimer){
36827                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
36828             }else if (this.menu.isVisible() && autoActivate){
36829                 this.menu.tryActivate(0, 1);
36830             }
36831         }
36832     },
36833
36834     
36835     deferExpand : function(autoActivate){
36836         delete this.showTimer;
36837         this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
36838         if(autoActivate){
36839             this.menu.tryActivate(0, 1);
36840         }
36841     },
36842
36843     
36844     hideMenu : function(){
36845         clearTimeout(this.showTimer);
36846         delete this.showTimer;
36847         if(!this.hideTimer && this.menu && this.menu.isVisible()){
36848             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
36849         }
36850     },
36851
36852     
36853     deferHide : function(){
36854         delete this.hideTimer;
36855         if(this.menu.over){
36856             this.parentMenu.setActiveItem(this, false);
36857         }else{
36858             this.menu.hide();
36859         }
36860     }
36861 });
36862 Ext.reg('menuitem', Ext.menu.Item);
36863 Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
36864     
36865     
36866     itemCls : "x-menu-item x-menu-check-item",
36867     
36868     groupClass : "x-menu-group-item",
36869
36870     
36871     checked: false,
36872
36873     
36874     ctype: "Ext.menu.CheckItem",
36875     
36876     initComponent : function(){
36877         Ext.menu.CheckItem.superclass.initComponent.call(this);
36878             this.addEvents(
36879                 
36880                 "beforecheckchange" ,
36881                 
36882                 "checkchange"
36883             );
36884             
36885             if(this.checkHandler){
36886                 this.on('checkchange', this.checkHandler, this.scope);
36887             }
36888             Ext.menu.MenuMgr.registerCheckable(this);
36889     },
36890
36891     
36892     onRender : function(c){
36893         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
36894         if(this.group){
36895             this.el.addClass(this.groupClass);
36896         }
36897         if(this.checked){
36898             this.checked = false;
36899             this.setChecked(true, true);
36900         }
36901     },
36902
36903     
36904     destroy : function(){
36905         Ext.menu.MenuMgr.unregisterCheckable(this);
36906         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
36907     },
36908
36909     
36910     setChecked : function(state, suppressEvent){
36911         var suppress = suppressEvent === true;
36912         if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
36913             if(this.container){
36914                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
36915             }
36916             this.checked = state;
36917             if(!suppress){
36918                 this.fireEvent("checkchange", this, state);
36919             }
36920         }
36921     },
36922
36923     
36924     handleClick : function(e){
36925        if(!this.disabled && !(this.checked && this.group)){
36926            this.setChecked(!this.checked);
36927        }
36928        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
36929     }
36930 });
36931 Ext.reg('menucheckitem', Ext.menu.CheckItem);
36932  Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
36933     
36934     enableScrolling : false,
36935     
36936         
36937     
36938     hideOnClick : true,
36939     
36940     
36941     pickerId : null,
36942     
36943     
36944     
36945     
36946     cls : 'x-date-menu',
36947     
36948     
36949     
36950     
36951
36952     initComponent : function(){
36953         this.on('beforeshow', this.onBeforeShow, this);
36954         if(this.strict = (Ext.isIE7 && Ext.isStrict)){
36955             this.on('show', this.onShow, this, {single: true, delay: 20});
36956         }
36957         Ext.apply(this, {
36958             plain: true,
36959             showSeparator: false,
36960             items: this.picker = new Ext.DatePicker(Ext.applyIf({
36961                 internalRender: this.strict || !Ext.isIE,
36962                 ctCls: 'x-menu-date-item',
36963                 id: this.pickerId
36964             }, this.initialConfig))
36965         });
36966         this.picker.purgeListeners();
36967         Ext.menu.DateMenu.superclass.initComponent.call(this);
36968         
36969         this.relayEvents(this.picker, ['select']);
36970         this.on('show', this.picker.focus, this.picker);
36971         this.on('select', this.menuHide, this);
36972         if(this.handler){
36973             this.on('select', this.handler, this.scope || this);
36974         }
36975     },
36976
36977     menuHide : function() {
36978         if(this.hideOnClick){
36979             this.hide(true);
36980         }
36981     },
36982
36983     onBeforeShow : function(){
36984         if(this.picker){
36985             this.picker.hideMonthPicker(true);
36986         }
36987     },
36988
36989     onShow : function(){
36990         var el = this.picker.getEl();
36991         el.setWidth(el.getWidth()); 
36992     }
36993  });
36994  Ext.reg('datemenu', Ext.menu.DateMenu);
36995  
36996  Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
36997     
36998     enableScrolling : false,
36999     
37000         
37001     
37002     
37003     hideOnClick : true,
37004     
37005     cls : 'x-color-menu',
37006     
37007     
37008     paletteId : null,
37009     
37010     
37011     
37012     
37013     
37014     
37015     
37016     
37017     
37018     
37019     initComponent : function(){
37020         Ext.apply(this, {
37021             plain: true,
37022             showSeparator: false,
37023             items: this.palette = new Ext.ColorPalette(Ext.applyIf({
37024                 id: this.paletteId
37025             }, this.initialConfig))
37026         });
37027         this.palette.purgeListeners();
37028         Ext.menu.ColorMenu.superclass.initComponent.call(this);
37029         
37030         this.relayEvents(this.palette, ['select']);
37031         this.on('select', this.menuHide, this);
37032         if(this.handler){
37033             this.on('select', this.handler, this.scope || this);
37034         }
37035     },
37036
37037     menuHide : function(){
37038         if(this.hideOnClick){
37039             this.hide(true);
37040         }
37041     }
37042 });
37043 Ext.reg('colormenu', Ext.menu.ColorMenu);
37044
37045 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
37046     
37047     
37048     
37049     
37050     
37051     
37052
37053     
37054     invalidClass : 'x-form-invalid',
37055     
37056     invalidText : 'The value in this field is invalid',
37057     
37058     focusClass : 'x-form-focus',
37059     
37060     
37061     validationEvent : 'keyup',
37062     
37063     validateOnBlur : true,
37064     
37065     validationDelay : 250,
37066     
37067     defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
37068     
37069     fieldClass : 'x-form-field',
37070     
37071     msgTarget : 'qtip',
37072     
37073     msgFx : 'normal',
37074     
37075     readOnly : false,
37076     
37077     disabled : false,
37078     
37079     submitValue: true,
37080
37081     
37082     isFormField : true,
37083
37084     
37085     msgDisplay: '',
37086
37087     
37088     hasFocus : false,
37089
37090     
37091     initComponent : function(){
37092         Ext.form.Field.superclass.initComponent.call(this);
37093         this.addEvents(
37094             
37095             'focus',
37096             
37097             'blur',
37098             
37099             'specialkey',
37100             
37101             'change',
37102             
37103             'invalid',
37104             
37105             'valid'
37106         );
37107     },
37108
37109     
37110     getName : function(){
37111         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
37112     },
37113
37114     
37115     onRender : function(ct, position){
37116         if(!this.el){
37117             var cfg = this.getAutoCreate();
37118
37119             if(!cfg.name){
37120                 cfg.name = this.name || this.id;
37121             }
37122             if(this.inputType){
37123                 cfg.type = this.inputType;
37124             }
37125             this.autoEl = cfg;
37126         }
37127         Ext.form.Field.superclass.onRender.call(this, ct, position);
37128         if(this.submitValue === false){
37129             this.el.dom.removeAttribute('name');
37130         }
37131         var type = this.el.dom.type;
37132         if(type){
37133             if(type == 'password'){
37134                 type = 'text';
37135             }
37136             this.el.addClass('x-form-'+type);
37137         }
37138         if(this.readOnly){
37139             this.setReadOnly(true);
37140         }
37141         if(this.tabIndex !== undefined){
37142             this.el.dom.setAttribute('tabIndex', this.tabIndex);
37143         }
37144
37145         this.el.addClass([this.fieldClass, this.cls]);
37146     },
37147
37148     
37149     getItemCt : function(){
37150         return this.itemCt;
37151     },
37152
37153     
37154     initValue : function(){
37155         if(this.value !== undefined){
37156             this.setValue(this.value);
37157         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
37158             this.setValue(this.el.dom.value);
37159         }
37160         
37161         this.originalValue = this.getValue();
37162     },
37163
37164     
37165     isDirty : function() {
37166         if(this.disabled || !this.rendered) {
37167             return false;
37168         }
37169         return String(this.getValue()) !== String(this.originalValue);
37170     },
37171
37172     
37173     setReadOnly : function(readOnly){
37174         if(this.rendered){
37175             this.el.dom.readOnly = readOnly;
37176         }
37177         this.readOnly = readOnly;
37178     },
37179
37180     
37181     afterRender : function(){
37182         Ext.form.Field.superclass.afterRender.call(this);
37183         this.initEvents();
37184         this.initValue();
37185     },
37186
37187     
37188     fireKey : function(e){
37189         if(e.isSpecialKey()){
37190             this.fireEvent('specialkey', this, e);
37191         }
37192     },
37193
37194     
37195     reset : function(){
37196         this.setValue(this.originalValue);
37197         this.clearInvalid();
37198     },
37199
37200     
37201     initEvents : function(){
37202         this.mon(this.el, Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.fireKey,  this);
37203         this.mon(this.el, 'focus', this.onFocus, this);
37204
37205         
37206         
37207         this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
37208     },
37209
37210     
37211     preFocus: Ext.emptyFn,
37212
37213     
37214     onFocus : function(){
37215         this.preFocus();
37216         if(this.focusClass){
37217             this.el.addClass(this.focusClass);
37218         }
37219         if(!this.hasFocus){
37220             this.hasFocus = true;
37221             
37222             this.startValue = this.getValue();
37223             this.fireEvent('focus', this);
37224         }
37225     },
37226
37227     
37228     beforeBlur : Ext.emptyFn,
37229
37230     
37231     onBlur : function(){
37232         this.beforeBlur();
37233         if(this.focusClass){
37234             this.el.removeClass(this.focusClass);
37235         }
37236         this.hasFocus = false;
37237         if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
37238             this.validate();
37239         }
37240         var v = this.getValue();
37241         if(String(v) !== String(this.startValue)){
37242             this.fireEvent('change', this, v, this.startValue);
37243         }
37244         this.fireEvent('blur', this);
37245         this.postBlur();
37246     },
37247
37248     
37249     postBlur : Ext.emptyFn,
37250
37251     
37252     isValid : function(preventMark){
37253         if(this.disabled){
37254             return true;
37255         }
37256         var restore = this.preventMark;
37257         this.preventMark = preventMark === true;
37258         var v = this.validateValue(this.processValue(this.getRawValue()));
37259         this.preventMark = restore;
37260         return v;
37261     },
37262
37263     
37264     validate : function(){
37265         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
37266             this.clearInvalid();
37267             return true;
37268         }
37269         return false;
37270     },
37271
37272     
37273     processValue : function(value){
37274         return value;
37275     },
37276
37277     
37278      validateValue : function(value) {
37279          
37280          var error = this.getErrors(value)[0];
37281
37282          if (error == undefined) {
37283              return true;
37284          } else {
37285              this.markInvalid(error);
37286              return false;
37287          }
37288      },
37289     
37290     
37291     getErrors: function() {
37292         return [];
37293     },
37294
37295     
37296     getActiveError : function(){
37297         return this.activeError || '';
37298     },
37299
37300     
37301     markInvalid : function(msg){
37302         
37303         if (this.rendered && !this.preventMark) {
37304             msg = msg || this.invalidText;
37305
37306             var mt = this.getMessageHandler();
37307             if(mt){
37308                 mt.mark(this, msg);
37309             }else if(this.msgTarget){
37310                 this.el.addClass(this.invalidClass);
37311                 var t = Ext.getDom(this.msgTarget);
37312                 if(t){
37313                     t.innerHTML = msg;
37314                     t.style.display = this.msgDisplay;
37315                 }
37316             }
37317         }
37318         
37319         this.setActiveError(msg);
37320     },
37321     
37322     
37323     clearInvalid : function(){
37324         
37325         if (this.rendered && !this.preventMark) {
37326             this.el.removeClass(this.invalidClass);
37327             var mt = this.getMessageHandler();
37328             if(mt){
37329                 mt.clear(this);
37330             }else if(this.msgTarget){
37331                 this.el.removeClass(this.invalidClass);
37332                 var t = Ext.getDom(this.msgTarget);
37333                 if(t){
37334                     t.innerHTML = '';
37335                     t.style.display = 'none';
37336                 }
37337             }
37338         }
37339         
37340         this.unsetActiveError();
37341     },
37342
37343     
37344     setActiveError: function(msg, suppressEvent) {
37345         this.activeError = msg;
37346         if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
37347     },
37348     
37349     
37350     unsetActiveError: function(suppressEvent) {
37351         delete this.activeError;
37352         if (suppressEvent !== true) this.fireEvent('valid', this);
37353     },
37354
37355     
37356     getMessageHandler : function(){
37357         return Ext.form.MessageTargets[this.msgTarget];
37358     },
37359
37360     
37361     getErrorCt : function(){
37362         return this.el.findParent('.x-form-element', 5, true) || 
37363             this.el.findParent('.x-form-field-wrap', 5, true);   
37364     },
37365
37366     
37367     alignErrorEl : function(){
37368         this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
37369     },
37370
37371     
37372     alignErrorIcon : function(){
37373         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
37374     },
37375
37376     
37377     getRawValue : function(){
37378         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
37379         if(v === this.emptyText){
37380             v = '';
37381         }
37382         return v;
37383     },
37384
37385     
37386     getValue : function(){
37387         if(!this.rendered) {
37388             return this.value;
37389         }
37390         var v = this.el.getValue();
37391         if(v === this.emptyText || v === undefined){
37392             v = '';
37393         }
37394         return v;
37395     },
37396
37397     
37398     setRawValue : function(v){
37399         return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
37400     },
37401
37402     
37403     setValue : function(v){
37404         this.value = v;
37405         if(this.rendered){
37406             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
37407             this.validate();
37408         }
37409         return this;
37410     },
37411
37412     
37413     append : function(v){
37414          this.setValue([this.getValue(), v].join(''));
37415     }
37416
37417     
37418     
37419
37420     
37421 });
37422
37423
37424 Ext.form.MessageTargets = {
37425     'qtip' : {
37426         mark: function(field, msg){
37427             field.el.addClass(field.invalidClass);
37428             field.el.dom.qtip = msg;
37429             field.el.dom.qclass = 'x-form-invalid-tip';
37430             if(Ext.QuickTips){ 
37431                 Ext.QuickTips.enable();
37432             }
37433         },
37434         clear: function(field){
37435             field.el.removeClass(field.invalidClass);
37436             field.el.dom.qtip = '';
37437         }
37438     },
37439     'title' : {
37440         mark: function(field, msg){
37441             field.el.addClass(field.invalidClass);
37442             field.el.dom.title = msg;
37443         },
37444         clear: function(field){
37445             field.el.dom.title = '';
37446         }
37447     },
37448     'under' : {
37449         mark: function(field, msg){
37450             field.el.addClass(field.invalidClass);
37451             if(!field.errorEl){
37452                 var elp = field.getErrorCt();
37453                 if(!elp){ 
37454                     field.el.dom.title = msg;
37455                     return;
37456                 }
37457                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
37458                 field.on('resize', field.alignErrorEl, field);
37459                 field.on('destroy', function(){
37460                     Ext.destroy(this.errorEl);
37461                 }, field);
37462             }
37463             field.alignErrorEl();
37464             field.errorEl.update(msg);
37465             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
37466         },
37467         clear: function(field){
37468             field.el.removeClass(field.invalidClass);
37469             if(field.errorEl){
37470                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
37471             }else{
37472                 field.el.dom.title = '';
37473             }
37474         }
37475     },
37476     'side' : {
37477         mark: function(field, msg){
37478             field.el.addClass(field.invalidClass);
37479             if(!field.errorIcon){
37480                 var elp = field.getErrorCt();
37481                 
37482                 if(!elp){
37483                     field.el.dom.title = msg;
37484                     return;
37485                 }
37486                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
37487                 if (field.ownerCt) {
37488                     field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
37489                     field.ownerCt.on('expand', field.alignErrorIcon, field);
37490                 }
37491                 field.on('resize', field.alignErrorIcon, field);
37492                 field.on('destroy', function(){
37493                     Ext.destroy(this.errorIcon);
37494                 }, field);
37495             }
37496             field.alignErrorIcon();
37497             field.errorIcon.dom.qtip = msg;
37498             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
37499             field.errorIcon.show();
37500         },
37501         clear: function(field){
37502             field.el.removeClass(field.invalidClass);
37503             if(field.errorIcon){
37504                 field.errorIcon.dom.qtip = '';
37505                 field.errorIcon.hide();
37506             }else{
37507                 field.el.dom.title = '';
37508             }
37509         }
37510     }
37511 };
37512
37513
37514 Ext.form.Field.msgFx = {
37515     normal : {
37516         show: function(msgEl, f){
37517             msgEl.setDisplayed('block');
37518         },
37519
37520         hide : function(msgEl, f){
37521             msgEl.setDisplayed(false).update('');
37522         }
37523     },
37524
37525     slide : {
37526         show: function(msgEl, f){
37527             msgEl.slideIn('t', {stopFx:true});
37528         },
37529
37530         hide : function(msgEl, f){
37531             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
37532         }
37533     },
37534
37535     slideRight : {
37536         show: function(msgEl, f){
37537             msgEl.fixDisplay();
37538             msgEl.alignTo(f.el, 'tl-tr');
37539             msgEl.slideIn('l', {stopFx:true});
37540         },
37541
37542         hide : function(msgEl, f){
37543             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
37544         }
37545     }
37546 };
37547 Ext.reg('field', Ext.form.Field);
37548
37549 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
37550     
37551     
37552     
37553     grow : false,
37554     
37555     growMin : 30,
37556     
37557     growMax : 800,
37558     
37559     vtype : null,
37560     
37561     maskRe : null,
37562     
37563     disableKeyFilter : false,
37564     
37565     allowBlank : true,
37566     
37567     minLength : 0,
37568     
37569     maxLength : Number.MAX_VALUE,
37570     
37571     minLengthText : 'The minimum length for this field is {0}',
37572     
37573     maxLengthText : 'The maximum length for this field is {0}',
37574     
37575     selectOnFocus : false,
37576     
37577     blankText : 'This field is required',
37578     
37579     validator : null,
37580     
37581     regex : null,
37582     
37583     regexText : '',
37584     
37585     emptyText : null,
37586     
37587     emptyClass : 'x-form-empty-field',
37588
37589     
37590
37591     initComponent : function(){
37592         Ext.form.TextField.superclass.initComponent.call(this);
37593         this.addEvents(
37594             
37595             'autosize',
37596
37597             
37598             'keydown',
37599             
37600             'keyup',
37601             
37602             'keypress'
37603         );
37604     },
37605
37606     
37607     initEvents : function(){
37608         Ext.form.TextField.superclass.initEvents.call(this);
37609         if(this.validationEvent == 'keyup'){
37610             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
37611             this.mon(this.el, 'keyup', this.filterValidation, this);
37612         }
37613         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
37614                 this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
37615         }
37616         if(this.selectOnFocus || this.emptyText){            
37617             this.mon(this.el, 'mousedown', this.onMouseDown, this);
37618             
37619             if(this.emptyText){
37620                 this.applyEmptyText();
37621             }
37622         }
37623         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
37624                 this.mon(this.el, 'keypress', this.filterKeys, this);
37625         }
37626         if(this.grow){
37627                 this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
37628                         this.mon(this.el, 'click', this.autoSize, this);
37629         }
37630         if(this.enableKeyEvents){
37631             this.mon(this.el, {
37632                 scope: this,
37633                 keyup: this.onKeyUp,
37634                 keydown: this.onKeyDown,
37635                 keypress: this.onKeyPress
37636             });
37637         }
37638     },
37639     
37640     onMouseDown: function(e){
37641         if(!this.hasFocus){
37642             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
37643         }
37644     },
37645
37646     processValue : function(value){
37647         if(this.stripCharsRe){
37648             var newValue = value.replace(this.stripCharsRe, '');
37649             if(newValue !== value){
37650                 this.setRawValue(newValue);
37651                 return newValue;
37652             }
37653         }
37654         return value;
37655     },
37656
37657     filterValidation : function(e){
37658         if(!e.isNavKeyPress()){
37659             this.validationTask.delay(this.validationDelay);
37660         }
37661     },
37662     
37663     
37664     onDisable: function(){
37665         Ext.form.TextField.superclass.onDisable.call(this);
37666         if(Ext.isIE){
37667             this.el.dom.unselectable = 'on';
37668         }
37669     },
37670     
37671     
37672     onEnable: function(){
37673         Ext.form.TextField.superclass.onEnable.call(this);
37674         if(Ext.isIE){
37675             this.el.dom.unselectable = '';
37676         }
37677     },
37678
37679     
37680     onKeyUpBuffered : function(e){
37681         if(this.doAutoSize(e)){
37682             this.autoSize();
37683         }
37684     },
37685     
37686     
37687     doAutoSize : function(e){
37688         return !e.isNavKeyPress();
37689     },
37690
37691     
37692     onKeyUp : function(e){
37693         this.fireEvent('keyup', this, e);
37694     },
37695
37696     
37697     onKeyDown : function(e){
37698         this.fireEvent('keydown', this, e);
37699     },
37700
37701     
37702     onKeyPress : function(e){
37703         this.fireEvent('keypress', this, e);
37704     },
37705
37706     
37707     reset : function(){
37708         Ext.form.TextField.superclass.reset.call(this);
37709         this.applyEmptyText();
37710     },
37711
37712     applyEmptyText : function(){
37713         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
37714             this.setRawValue(this.emptyText);
37715             this.el.addClass(this.emptyClass);
37716         }
37717     },
37718
37719     
37720     preFocus : function(){
37721         var el = this.el;
37722         if(this.emptyText){
37723             if(el.dom.value == this.emptyText){
37724                 this.setRawValue('');
37725             }
37726             el.removeClass(this.emptyClass);
37727         }
37728         if(this.selectOnFocus){
37729             el.dom.select();
37730         }
37731     },
37732
37733     
37734     postBlur : function(){
37735         this.applyEmptyText();
37736     },
37737
37738     
37739     filterKeys : function(e){
37740         if(e.ctrlKey){
37741             return;
37742         }
37743         var k = e.getKey();
37744         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
37745             return;
37746         }
37747         var cc = String.fromCharCode(e.getCharCode());
37748         if(!Ext.isGecko && e.isSpecialKey() && !cc){
37749             return;
37750         }
37751         if(!this.maskRe.test(cc)){
37752             e.stopEvent();
37753         }
37754     },
37755
37756     setValue : function(v){
37757         if(this.emptyText && this.el && !Ext.isEmpty(v)){
37758             this.el.removeClass(this.emptyClass);
37759         }
37760         Ext.form.TextField.superclass.setValue.apply(this, arguments);
37761         this.applyEmptyText();
37762         this.autoSize();
37763         return this;
37764     },
37765
37766     
37767     getErrors: function(value) {
37768         var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
37769         
37770         value = value || this.processValue(this.getRawValue());        
37771         
37772         if (Ext.isFunction(this.validator)) {
37773             var msg = this.validator(value);
37774             if (msg !== true) {
37775                 errors.push(msg);
37776             }
37777         }
37778         
37779         if (value.length < 1 || value === this.emptyText) {
37780             if (this.allowBlank) {
37781                 
37782                 return errors;
37783             } else {
37784                 errors.push(this.blankText);
37785             }
37786         }
37787         
37788         if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
37789             errors.push(this.blankText);
37790         }
37791         
37792         if (value.length < this.minLength) {
37793             errors.push(String.format(this.minLengthText, this.minLength));
37794         }
37795         
37796         if (value.length > this.maxLength) {
37797             errors.push(String.format(this.maxLengthText, this.maxLength));
37798         }
37799         
37800         if (this.vtype) {
37801             var vt = Ext.form.VTypes;
37802             if(!vt[this.vtype](value, this)){
37803                 errors.push(this.vtypeText || vt[this.vtype +'Text']);
37804             }
37805         }
37806         
37807         if (this.regex && !this.regex.test(value)) {
37808             errors.push(this.regexText);
37809         }
37810         
37811         return errors;
37812     },
37813
37814     
37815     selectText : function(start, end){
37816         var v = this.getRawValue();
37817         var doFocus = false;
37818         if(v.length > 0){
37819             start = start === undefined ? 0 : start;
37820             end = end === undefined ? v.length : end;
37821             var d = this.el.dom;
37822             if(d.setSelectionRange){
37823                 d.setSelectionRange(start, end);
37824             }else if(d.createTextRange){
37825                 var range = d.createTextRange();
37826                 range.moveStart('character', start);
37827                 range.moveEnd('character', end-v.length);
37828                 range.select();
37829             }
37830             doFocus = Ext.isGecko || Ext.isOpera;
37831         }else{
37832             doFocus = true;
37833         }
37834         if(doFocus){
37835             this.focus();
37836         }
37837     },
37838
37839     
37840     autoSize : function(){
37841         if(!this.grow || !this.rendered){
37842             return;
37843         }
37844         if(!this.metrics){
37845             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
37846         }
37847         var el = this.el;
37848         var v = el.dom.value;
37849         var d = document.createElement('div');
37850         d.appendChild(document.createTextNode(v));
37851         v = d.innerHTML;
37852         Ext.removeNode(d);
37853         d = null;
37854         v += '&#160;';
37855         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
37856         this.el.setWidth(w);
37857         this.fireEvent('autosize', this, w);
37858     },
37859         
37860         onDestroy: function(){
37861                 if(this.validationTask){
37862                         this.validationTask.cancel();
37863                         this.validationTask = null;
37864                 }
37865                 Ext.form.TextField.superclass.onDestroy.call(this);
37866         }
37867 });
37868 Ext.reg('textfield', Ext.form.TextField);
37869
37870 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
37871     
37872     
37873     
37874     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
37875     
37876     hideTrigger:false,
37877     
37878     editable: true,
37879     
37880     readOnly: false,
37881     
37882     wrapFocusClass: 'x-trigger-wrap-focus',
37883     
37884     autoSize: Ext.emptyFn,
37885     
37886     monitorTab : true,
37887     
37888     deferHeight : true,
37889     
37890     mimicing : false,
37891
37892     actionMode: 'wrap',
37893
37894     defaultTriggerWidth: 17,
37895
37896     
37897     onResize : function(w, h){
37898         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
37899         var tw = this.getTriggerWidth();
37900         if(Ext.isNumber(w)){
37901             this.el.setWidth(w - tw);
37902         }
37903         this.wrap.setWidth(this.el.getWidth() + tw);
37904     },
37905
37906     getTriggerWidth: function(){
37907         var tw = this.trigger.getWidth();
37908         if(!this.hideTrigger && !this.readOnly && tw === 0){
37909             tw = this.defaultTriggerWidth;
37910         }
37911         return tw;
37912     },
37913
37914     
37915     alignErrorIcon : function(){
37916         if(this.wrap){
37917             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
37918         }
37919     },
37920
37921     
37922     onRender : function(ct, position){
37923         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
37924         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
37925
37926         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
37927         this.trigger = this.wrap.createChild(this.triggerConfig ||
37928                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
37929         this.initTrigger();
37930         if(!this.width){
37931             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
37932         }
37933         this.resizeEl = this.positionEl = this.wrap;
37934     },
37935
37936     getWidth: function() {
37937         return(this.el.getWidth() + this.trigger.getWidth());
37938     },
37939
37940     updateEditState: function(){
37941         if(this.rendered){
37942             if (this.readOnly) {
37943                 this.el.dom.readOnly = true;
37944                 this.el.addClass('x-trigger-noedit');
37945                 this.mun(this.el, 'click', this.onTriggerClick, this);
37946                 this.trigger.setDisplayed(false);
37947             } else {
37948                 if (!this.editable) {
37949                     this.el.dom.readOnly = true;
37950                     this.el.addClass('x-trigger-noedit');
37951                     this.mon(this.el, 'click', this.onTriggerClick, this);
37952                 } else {
37953                     this.el.dom.readOnly = false;
37954                     this.el.removeClass('x-trigger-noedit');
37955                     this.mun(this.el, 'click', this.onTriggerClick, this);
37956                 }
37957                 this.trigger.setDisplayed(!this.hideTrigger);
37958             }
37959             this.onResize(this.width || this.wrap.getWidth());
37960         }
37961     },
37962
37963     setHideTrigger: function(hideTrigger){
37964         if(hideTrigger != this.hideTrigger){
37965             this.hideTrigger = hideTrigger;
37966             this.updateEditState();
37967         }
37968     },
37969
37970     
37971     setEditable: function(editable){
37972         if(editable != this.editable){
37973             this.editable = editable;
37974             this.updateEditState();
37975         }
37976     },
37977
37978     
37979     setReadOnly: function(readOnly){
37980         if(readOnly != this.readOnly){
37981             this.readOnly = readOnly;
37982             this.updateEditState();
37983         }
37984     },
37985
37986     afterRender : function(){
37987         Ext.form.TriggerField.superclass.afterRender.call(this);
37988         this.updateEditState();
37989     },
37990
37991     
37992     initTrigger : function(){
37993         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
37994         this.trigger.addClassOnOver('x-form-trigger-over');
37995         this.trigger.addClassOnClick('x-form-trigger-click');
37996     },
37997
37998     
37999     onDestroy : function(){
38000         Ext.destroy(this.trigger, this.wrap);
38001         if (this.mimicing){
38002             this.doc.un('mousedown', this.mimicBlur, this);
38003         }
38004         delete this.doc;
38005         Ext.form.TriggerField.superclass.onDestroy.call(this);
38006     },
38007
38008     
38009     onFocus : function(){
38010         Ext.form.TriggerField.superclass.onFocus.call(this);
38011         if(!this.mimicing){
38012             this.wrap.addClass(this.wrapFocusClass);
38013             this.mimicing = true;
38014             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
38015             if(this.monitorTab){
38016                 this.on('specialkey', this.checkTab, this);
38017             }
38018         }
38019     },
38020
38021     
38022     checkTab : function(me, e){
38023         if(e.getKey() == e.TAB){
38024             this.triggerBlur();
38025         }
38026     },
38027
38028     
38029     onBlur : Ext.emptyFn,
38030
38031     
38032     mimicBlur : function(e){
38033         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
38034             this.triggerBlur();
38035         }
38036     },
38037
38038     
38039     triggerBlur : function(){
38040         this.mimicing = false;
38041         this.doc.un('mousedown', this.mimicBlur, this);
38042         if(this.monitorTab && this.el){
38043             this.un('specialkey', this.checkTab, this);
38044         }
38045         Ext.form.TriggerField.superclass.onBlur.call(this);
38046         if(this.wrap){
38047             this.wrap.removeClass(this.wrapFocusClass);
38048         }
38049     },
38050
38051     beforeBlur : Ext.emptyFn,
38052
38053     
38054     
38055     validateBlur : function(e){
38056         return true;
38057     },
38058
38059     
38060     onTriggerClick : Ext.emptyFn
38061
38062     
38063     
38064     
38065 });
38066
38067
38068 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
38069     
38070     
38071     
38072
38073     initComponent : function(){
38074         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
38075
38076         this.triggerConfig = {
38077             tag:'span', cls:'x-form-twin-triggers', cn:[
38078             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
38079             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
38080         ]};
38081     },
38082
38083     getTrigger : function(index){
38084         return this.triggers[index];
38085     },
38086
38087     initTrigger : function(){
38088         var ts = this.trigger.select('.x-form-trigger', true);
38089         var triggerField = this;
38090         ts.each(function(t, all, index){
38091             var triggerIndex = 'Trigger'+(index+1);
38092             t.hide = function(){
38093                 var w = triggerField.wrap.getWidth();
38094                 this.dom.style.display = 'none';
38095                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
38096                 this['hidden' + triggerIndex] = true;
38097             };
38098             t.show = function(){
38099                 var w = triggerField.wrap.getWidth();
38100                 this.dom.style.display = '';
38101                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
38102                 this['hidden' + triggerIndex] = false;
38103             };
38104
38105             if(this['hide'+triggerIndex]){
38106                 t.dom.style.display = 'none';
38107                 this['hidden' + triggerIndex] = true;
38108             }
38109             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
38110             t.addClassOnOver('x-form-trigger-over');
38111             t.addClassOnClick('x-form-trigger-click');
38112         }, this);
38113         this.triggers = ts.elements;
38114     },
38115
38116     getTriggerWidth: function(){
38117         var tw = 0;
38118         Ext.each(this.triggers, function(t, index){
38119             var triggerIndex = 'Trigger' + (index + 1),
38120                 w = t.getWidth();
38121             if(w === 0 && !this['hidden' + triggerIndex]){
38122                 tw += this.defaultTriggerWidth;
38123             }else{
38124                 tw += w;
38125             }
38126         }, this);
38127         return tw;
38128     },
38129
38130     
38131     onDestroy : function() {
38132         Ext.destroy(this.triggers);
38133         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
38134     },
38135
38136     
38137     onTrigger1Click : Ext.emptyFn,
38138     
38139     onTrigger2Click : Ext.emptyFn
38140 });
38141 Ext.reg('trigger', Ext.form.TriggerField);
38142
38143 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
38144     
38145     growMin : 60,
38146     
38147     growMax: 1000,
38148     growAppend : '&#160;\n&#160;',
38149
38150     enterIsSpecial : false,
38151
38152     
38153     preventScrollbars: false,
38154     
38155
38156     
38157     onRender : function(ct, position){
38158         if(!this.el){
38159             this.defaultAutoCreate = {
38160                 tag: "textarea",
38161                 style:"width:100px;height:60px;",
38162                 autocomplete: "off"
38163             };
38164         }
38165         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
38166         if(this.grow){
38167             this.textSizeEl = Ext.DomHelper.append(document.body, {
38168                 tag: "pre", cls: "x-form-grow-sizer"
38169             });
38170             if(this.preventScrollbars){
38171                 this.el.setStyle("overflow", "hidden");
38172             }
38173             this.el.setHeight(this.growMin);
38174         }
38175     },
38176
38177     onDestroy : function(){
38178         Ext.removeNode(this.textSizeEl);
38179         Ext.form.TextArea.superclass.onDestroy.call(this);
38180     },
38181
38182     fireKey : function(e){
38183         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
38184             this.fireEvent("specialkey", this, e);
38185         }
38186     },
38187     
38188     
38189     doAutoSize : function(e){
38190         return !e.isNavKeyPress() || e.getKey() == e.ENTER;
38191     },
38192
38193     
38194     autoSize: function(){
38195         if(!this.grow || !this.textSizeEl){
38196             return;
38197         }
38198         var el = this.el,
38199             v = Ext.util.Format.htmlEncode(el.dom.value),
38200             ts = this.textSizeEl,
38201             h;
38202             
38203         Ext.fly(ts).setWidth(this.el.getWidth());
38204         if(v.length < 1){
38205             v = "&#160;&#160;";
38206         }else{
38207             v += this.growAppend;
38208             if(Ext.isIE){
38209                 v = v.replace(/\n/g, '&#160;<br />');
38210             }
38211         }
38212         ts.innerHTML = v;
38213         h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
38214         if(h != this.lastHeight){
38215             this.lastHeight = h;
38216             this.el.setHeight(h);
38217             this.fireEvent("autosize", this, h);
38218         }
38219     }
38220 });
38221 Ext.reg('textarea', Ext.form.TextArea);
38222 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
38223     
38224     
38225     
38226     fieldClass: "x-form-field x-form-num-field",
38227     
38228     allowDecimals : true,
38229     
38230     decimalSeparator : ".",
38231     
38232     decimalPrecision : 2,
38233     
38234     allowNegative : true,
38235     
38236     minValue : Number.NEGATIVE_INFINITY,
38237     
38238     maxValue : Number.MAX_VALUE,
38239     
38240     minText : "The minimum value for this field is {0}",
38241     
38242     maxText : "The maximum value for this field is {0}",
38243     
38244     nanText : "{0} is not a valid number",
38245     
38246     baseChars : "0123456789",
38247
38248     
38249     initEvents : function(){
38250         var allowed = this.baseChars + '';
38251         if (this.allowDecimals) {
38252             allowed += this.decimalSeparator;
38253         }
38254         if (this.allowNegative) {
38255             allowed += '-';
38256         }
38257         this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');
38258         Ext.form.NumberField.superclass.initEvents.call(this);
38259     },
38260     
38261     
38262     getErrors: function(value) {
38263         var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
38264         
38265         value = value || this.processValue(this.getRawValue());
38266         
38267         if (value.length < 1) { 
38268              return errors;
38269         }
38270         
38271         value = String(value).replace(this.decimalSeparator, ".");
38272         
38273         if(isNaN(value)){
38274             errors.push(String.format(this.nanText, value));
38275         }
38276         
38277         var num = this.parseValue(value);
38278         
38279         if(num < this.minValue){
38280             errors.push(String.format(this.minText, this.minValue));
38281         }
38282         
38283         if(num > this.maxValue){
38284             errors.push(String.format(this.maxText, this.maxValue));
38285         }
38286         
38287         return errors;
38288     },
38289
38290     getValue : function(){
38291         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
38292     },
38293
38294     setValue : function(v){
38295         v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
38296         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
38297         return Ext.form.NumberField.superclass.setValue.call(this, v);
38298     },
38299     
38300     
38301     setMinValue : function(value){
38302         this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
38303     },
38304     
38305     
38306     setMaxValue : function(value){
38307         this.maxValue = Ext.num(value, Number.MAX_VALUE);    
38308     },
38309
38310     
38311     parseValue : function(value){
38312         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
38313         return isNaN(value) ? '' : value;
38314     },
38315
38316     
38317     fixPrecision : function(value){
38318         var nan = isNaN(value);
38319         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
38320            return nan ? '' : value;
38321         }
38322         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
38323     },
38324
38325     beforeBlur : function(){
38326         var v = this.parseValue(this.getRawValue());
38327         if(!Ext.isEmpty(v)){
38328             this.setValue(this.fixPrecision(v));
38329         }
38330     }
38331 });
38332 Ext.reg('numberfield', Ext.form.NumberField);
38333 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
38334     
38335     format : "m/d/Y",
38336     
38337     altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",
38338     
38339     disabledDaysText : "Disabled",
38340     
38341     disabledDatesText : "Disabled",
38342     
38343     minText : "The date in this field must be equal to or after {0}",
38344     
38345     maxText : "The date in this field must be equal to or before {0}",
38346     
38347     invalidText : "{0} is not a valid date - it must be in the format {1}",
38348     
38349     triggerClass : 'x-form-date-trigger',
38350     
38351     showToday : true,
38352     
38353     
38354     
38355     
38356     
38357
38358     
38359     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
38360
38361     
38362     
38363     initTime: '12', 
38364
38365     initTimeFormat: 'H',
38366
38367     
38368     safeParse : function(value, format) {
38369         if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {
38370             
38371             return Date.parseDate(value, format);
38372         } else {
38373             
38374             var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
38375             
38376             if (parsedDate) return parsedDate.clearTime();
38377         }
38378     },
38379
38380     initComponent : function(){
38381         Ext.form.DateField.superclass.initComponent.call(this);
38382
38383         this.addEvents(
38384             
38385             'select'
38386         );
38387
38388         if(Ext.isString(this.minValue)){
38389             this.minValue = this.parseDate(this.minValue);
38390         }
38391         if(Ext.isString(this.maxValue)){
38392             this.maxValue = this.parseDate(this.maxValue);
38393         }
38394         this.disabledDatesRE = null;
38395         this.initDisabledDays();
38396     },
38397
38398     initEvents: function() {
38399         Ext.form.DateField.superclass.initEvents.call(this);
38400         this.keyNav = new Ext.KeyNav(this.el, {
38401             "down": function(e) {
38402                 this.onTriggerClick();
38403             },
38404             scope: this,
38405             forceKeyDown: true
38406         });
38407     },
38408
38409
38410     
38411     initDisabledDays : function(){
38412         if(this.disabledDates){
38413             var dd = this.disabledDates,
38414                 len = dd.length - 1,
38415                 re = "(?:";
38416
38417             Ext.each(dd, function(d, i){
38418                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
38419                 if(i != len){
38420                     re += '|';
38421                 }
38422             }, this);
38423             this.disabledDatesRE = new RegExp(re + ')');
38424         }
38425     },
38426
38427     
38428     setDisabledDates : function(dd){
38429         this.disabledDates = dd;
38430         this.initDisabledDays();
38431         if(this.menu){
38432             this.menu.picker.setDisabledDates(this.disabledDatesRE);
38433         }
38434     },
38435
38436     
38437     setDisabledDays : function(dd){
38438         this.disabledDays = dd;
38439         if(this.menu){
38440             this.menu.picker.setDisabledDays(dd);
38441         }
38442     },
38443
38444     
38445     setMinValue : function(dt){
38446         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
38447         if(this.menu){
38448             this.menu.picker.setMinDate(this.minValue);
38449         }
38450     },
38451
38452     
38453     setMaxValue : function(dt){
38454         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
38455         if(this.menu){
38456             this.menu.picker.setMaxDate(this.maxValue);
38457         }
38458     },
38459     
38460     
38461     getErrors: function(value) {
38462         var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
38463         
38464         value = this.formatDate(value || this.processValue(this.getRawValue()));
38465         
38466         if (value.length < 1) { 
38467              return errors;
38468         }
38469         
38470         var svalue = value;
38471         value = this.parseDate(value);
38472         if (!value) {
38473             errors.push(String.format(this.invalidText, svalue, this.format));
38474             return errors;
38475         }
38476         
38477         var time = value.getTime();
38478         if (this.minValue && time < this.minValue.getTime()) {
38479             errors.push(String.format(this.minText, this.formatDate(this.minValue)));
38480         }
38481         
38482         if (this.maxValue && time > this.maxValue.getTime()) {
38483             errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
38484         }
38485         
38486         if (this.disabledDays) {
38487             var day = value.getDay();
38488             
38489             for(var i = 0; i < this.disabledDays.length; i++) {
38490                 if (day === this.disabledDays[i]) {
38491                     errors.push(this.disabledDaysText);
38492                     break;
38493                 }
38494             }
38495         }
38496         
38497         var fvalue = this.formatDate(value);
38498         if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
38499             errors.push(String.format(this.disabledDatesText, fvalue));
38500         }
38501         
38502         return errors;
38503     },
38504
38505     
38506     
38507     validateBlur : function(){
38508         return !this.menu || !this.menu.isVisible();
38509     },
38510
38511     
38512     getValue : function(){
38513         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
38514     },
38515
38516     
38517     setValue : function(date){
38518         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
38519     },
38520
38521     
38522     parseDate : function(value) {
38523         if(!value || Ext.isDate(value)){
38524             return value;
38525         }
38526
38527         var v = this.safeParse(value, this.format),
38528             af = this.altFormats,
38529             afa = this.altFormatsArray;
38530
38531         if (!v && af) {
38532             afa = afa || af.split("|");
38533
38534             for (var i = 0, len = afa.length; i < len && !v; i++) {
38535                 v = this.safeParse(value, afa[i]);
38536             }
38537         }
38538         return v;
38539     },
38540
38541     
38542     onDestroy : function(){
38543         Ext.destroy(this.menu, this.keyNav);
38544         Ext.form.DateField.superclass.onDestroy.call(this);
38545     },
38546
38547     
38548     formatDate : function(date){
38549         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
38550     },
38551
38552     
38553     
38554     
38555     onTriggerClick : function(){
38556         if(this.disabled){
38557             return;
38558         }
38559         if(this.menu == null){
38560             this.menu = new Ext.menu.DateMenu({
38561                 hideOnClick: false,
38562                 focusOnSelect: false
38563             });
38564         }
38565         this.onFocus();
38566         Ext.apply(this.menu.picker,  {
38567             minDate : this.minValue,
38568             maxDate : this.maxValue,
38569             disabledDatesRE : this.disabledDatesRE,
38570             disabledDatesText : this.disabledDatesText,
38571             disabledDays : this.disabledDays,
38572             disabledDaysText : this.disabledDaysText,
38573             format : this.format,
38574             showToday : this.showToday,
38575             minText : String.format(this.minText, this.formatDate(this.minValue)),
38576             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
38577         });
38578         this.menu.picker.setValue(this.getValue() || new Date());
38579         this.menu.show(this.el, "tl-bl?");
38580         this.menuEvents('on');
38581     },
38582
38583     
38584     menuEvents: function(method){
38585         this.menu[method]('select', this.onSelect, this);
38586         this.menu[method]('hide', this.onMenuHide, this);
38587         this.menu[method]('show', this.onFocus, this);
38588     },
38589
38590     onSelect: function(m, d){
38591         this.setValue(d);
38592         this.fireEvent('select', this, d);
38593         this.menu.hide();
38594     },
38595
38596     onMenuHide: function(){
38597         this.focus(false, 60);
38598         this.menuEvents('un');
38599     },
38600
38601     
38602     beforeBlur : function(){
38603         var v = this.parseDate(this.getRawValue());
38604         if(v){
38605             this.setValue(v);
38606         }
38607     }
38608
38609     
38610     
38611     
38612     
38613 });
38614 Ext.reg('datefield', Ext.form.DateField);
38615 Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
38616     validationEvent : false,
38617     validateOnBlur : false,
38618     defaultAutoCreate : {tag: "div"},
38619     
38620     fieldClass : "x-form-display-field",
38621     
38622     htmlEncode: false,
38623
38624     
38625     initEvents : Ext.emptyFn,
38626
38627     isValid : function(){
38628         return true;
38629     },
38630
38631     validate : function(){
38632         return true;
38633     },
38634
38635     getRawValue : function(){
38636         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
38637         if(v === this.emptyText){
38638             v = '';
38639         }
38640         if(this.htmlEncode){
38641             v = Ext.util.Format.htmlDecode(v);
38642         }
38643         return v;
38644     },
38645
38646     getValue : function(){
38647         return this.getRawValue();
38648     },
38649     
38650     getName: function() {
38651         return this.name;
38652     },
38653
38654     setRawValue : function(v){
38655         if(this.htmlEncode){
38656             v = Ext.util.Format.htmlEncode(v);
38657         }
38658         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
38659     },
38660
38661     setValue : function(v){
38662         this.setRawValue(v);
38663         return this;
38664     }
38665     
38666     
38667     
38668     
38669     
38670     
38671 });
38672
38673 Ext.reg('displayfield', Ext.form.DisplayField);
38674
38675 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
38676     
38677     
38678     
38679     
38680     
38681
38682     
38683     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
38684     
38685     
38686     
38687     
38688     
38689     
38690     
38691     listClass : '',
38692     
38693     selectedClass : 'x-combo-selected',
38694     
38695     listEmptyText: '',
38696     
38697     triggerClass : 'x-form-arrow-trigger',
38698     
38699     shadow : 'sides',
38700     
38701     listAlign : 'tl-bl?',
38702     
38703     maxHeight : 300,
38704     
38705     minHeight : 90,
38706     
38707     triggerAction : 'query',
38708     
38709     minChars : 4,
38710     
38711     autoSelect : true,
38712     
38713     typeAhead : false,
38714     
38715     queryDelay : 500,
38716     
38717     pageSize : 0,
38718     
38719     selectOnFocus : false,
38720     
38721     queryParam : 'query',
38722     
38723     loadingText : 'Loading...',
38724     
38725     resizable : false,
38726     
38727     handleHeight : 8,
38728     
38729     allQuery: '',
38730     
38731     mode: 'remote',
38732     
38733     minListWidth : 70,
38734     
38735     forceSelection : false,
38736     
38737     typeAheadDelay : 250,
38738     
38739
38740     
38741     lazyInit : true,
38742
38743     
38744     clearFilterOnReset : true,
38745
38746     
38747     submitValue: undefined,
38748
38749     
38750
38751     
38752     initComponent : function(){
38753         Ext.form.ComboBox.superclass.initComponent.call(this);
38754         this.addEvents(
38755             
38756             'expand',
38757             
38758             'collapse',
38759
38760             
38761             'beforeselect',
38762             
38763             'select',
38764             
38765             'beforequery'
38766         );
38767         if(this.transform){
38768             var s = Ext.getDom(this.transform);
38769             if(!this.hiddenName){
38770                 this.hiddenName = s.name;
38771             }
38772             if(!this.store){
38773                 this.mode = 'local';
38774                 var d = [], opts = s.options;
38775                 for(var i = 0, len = opts.length;i < len; i++){
38776                     var o = opts[i],
38777                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
38778                     if(o.selected && Ext.isEmpty(this.value, true)) {
38779                         this.value = value;
38780                     }
38781                     d.push([value, o.text]);
38782                 }
38783                 this.store = new Ext.data.ArrayStore({
38784                     'id': 0,
38785                     fields: ['value', 'text'],
38786                     data : d,
38787                     autoDestroy: true
38788                 });
38789                 this.valueField = 'value';
38790                 this.displayField = 'text';
38791             }
38792             s.name = Ext.id(); 
38793             if(!this.lazyRender){
38794                 this.target = true;
38795                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
38796                 this.render(this.el.parentNode, s);
38797             }
38798             Ext.removeNode(s);
38799         }
38800         
38801         else if(this.store){
38802             this.store = Ext.StoreMgr.lookup(this.store);
38803             if(this.store.autoCreated){
38804                 this.displayField = this.valueField = 'field1';
38805                 if(!this.store.expandData){
38806                     this.displayField = 'field2';
38807                 }
38808                 this.mode = 'local';
38809             }
38810         }
38811
38812         this.selectedIndex = -1;
38813         if(this.mode == 'local'){
38814             if(!Ext.isDefined(this.initialConfig.queryDelay)){
38815                 this.queryDelay = 10;
38816             }
38817             if(!Ext.isDefined(this.initialConfig.minChars)){
38818                 this.minChars = 0;
38819             }
38820         }
38821     },
38822
38823     
38824     onRender : function(ct, position){
38825         if(this.hiddenName && !Ext.isDefined(this.submitValue)){
38826             this.submitValue = false;
38827         }
38828         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
38829         if(this.hiddenName){
38830             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
38831                     id: (this.hiddenId||this.hiddenName)}, 'before', true);
38832
38833         }
38834         if(Ext.isGecko){
38835             this.el.dom.setAttribute('autocomplete', 'off');
38836         }
38837
38838         if(!this.lazyInit){
38839             this.initList();
38840         }else{
38841             this.on('focus', this.initList, this, {single: true});
38842         }
38843     },
38844
38845     
38846     initValue : function(){
38847         Ext.form.ComboBox.superclass.initValue.call(this);
38848         if(this.hiddenField){
38849             this.hiddenField.value =
38850                 Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
38851         }
38852     },
38853
38854     getParentZIndex : function(){
38855         var zindex;
38856         if (this.ownerCt){
38857             this.findParentBy(function(ct){
38858                 zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
38859                 return !!zindex;
38860             });
38861         }
38862         return zindex;
38863     },
38864
38865     
38866     initList : function(){
38867         if(!this.list){
38868             var cls = 'x-combo-list',
38869                 listParent = Ext.getDom(this.getListParent() || Ext.getBody()),
38870                 zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
38871
38872             if (!zindex) {
38873                 zindex = this.getParentZIndex();
38874             }
38875
38876             this.list = new Ext.Layer({
38877                 parentEl: listParent,
38878                 shadow: this.shadow,
38879                 cls: [cls, this.listClass].join(' '),
38880                 constrain:false,
38881                 zindex: (zindex || 12000) + 5
38882             });
38883
38884             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
38885             this.list.setSize(lw, 0);
38886             this.list.swallowEvent('mousewheel');
38887             this.assetHeight = 0;
38888             if(this.syncFont !== false){
38889                 this.list.setStyle('font-size', this.el.getStyle('font-size'));
38890             }
38891             if(this.title){
38892                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
38893                 this.assetHeight += this.header.getHeight();
38894             }
38895
38896             this.innerList = this.list.createChild({cls:cls+'-inner'});
38897             this.mon(this.innerList, 'mouseover', this.onViewOver, this);
38898             this.mon(this.innerList, 'mousemove', this.onViewMove, this);
38899             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
38900
38901             if(this.pageSize){
38902                 this.footer = this.list.createChild({cls:cls+'-ft'});
38903                 this.pageTb = new Ext.PagingToolbar({
38904                     store: this.store,
38905                     pageSize: this.pageSize,
38906                     renderTo:this.footer
38907                 });
38908                 this.assetHeight += this.footer.getHeight();
38909             }
38910
38911             if(!this.tpl){
38912                 
38913                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
38914                 
38915             }
38916
38917             
38918             this.view = new Ext.DataView({
38919                 applyTo: this.innerList,
38920                 tpl: this.tpl,
38921                 singleSelect: true,
38922                 selectedClass: this.selectedClass,
38923                 itemSelector: this.itemSelector || '.' + cls + '-item',
38924                 emptyText: this.listEmptyText,
38925                 deferEmptyText: false
38926             });
38927
38928             this.mon(this.view, {
38929                 containerclick : this.onViewClick,
38930                 click : this.onViewClick,
38931                 scope :this
38932             });
38933
38934             this.bindStore(this.store, true);
38935
38936             if(this.resizable){
38937                 this.resizer = new Ext.Resizable(this.list,  {
38938                    pinned:true, handles:'se'
38939                 });
38940                 this.mon(this.resizer, 'resize', function(r, w, h){
38941                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
38942                     this.listWidth = w;
38943                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
38944                     this.restrictHeight();
38945                 }, this);
38946
38947                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
38948             }
38949         }
38950     },
38951
38952     
38953     getListParent : function() {
38954         return document.body;
38955     },
38956
38957     
38958     getStore : function(){
38959         return this.store;
38960     },
38961
38962     
38963     bindStore : function(store, initial){
38964         if(this.store && !initial){
38965             if(this.store !== store && this.store.autoDestroy){
38966                 this.store.destroy();
38967             }else{
38968                 this.store.un('beforeload', this.onBeforeLoad, this);
38969                 this.store.un('load', this.onLoad, this);
38970                 this.store.un('exception', this.collapse, this);
38971             }
38972             if(!store){
38973                 this.store = null;
38974                 if(this.view){
38975                     this.view.bindStore(null);
38976                 }
38977                 if(this.pageTb){
38978                     this.pageTb.bindStore(null);
38979                 }
38980             }
38981         }
38982         if(store){
38983             if(!initial) {
38984                 this.lastQuery = null;
38985                 if(this.pageTb) {
38986                     this.pageTb.bindStore(store);
38987                 }
38988             }
38989
38990             this.store = Ext.StoreMgr.lookup(store);
38991             this.store.on({
38992                 scope: this,
38993                 beforeload: this.onBeforeLoad,
38994                 load: this.onLoad,
38995                 exception: this.collapse
38996             });
38997
38998             if(this.view){
38999                 this.view.bindStore(store);
39000             }
39001         }
39002     },
39003
39004     reset : function(){
39005         Ext.form.ComboBox.superclass.reset.call(this);
39006         if(this.clearFilterOnReset && this.mode == 'local'){
39007             this.store.clearFilter();
39008         }
39009     },
39010
39011     
39012     initEvents : function(){
39013         Ext.form.ComboBox.superclass.initEvents.call(this);
39014
39015         
39016         this.keyNav = new Ext.KeyNav(this.el, {
39017             "up" : function(e){
39018                 this.inKeyMode = true;
39019                 this.selectPrev();
39020             },
39021
39022             "down" : function(e){
39023                 if(!this.isExpanded()){
39024                     this.onTriggerClick();
39025                 }else{
39026                     this.inKeyMode = true;
39027                     this.selectNext();
39028                 }
39029             },
39030
39031             "enter" : function(e){
39032                 this.onViewClick();
39033             },
39034
39035             "esc" : function(e){
39036                 this.collapse();
39037             },
39038
39039             "tab" : function(e){
39040                 if (this.forceSelection === true) {
39041                     this.collapse();
39042                 } else {
39043                     this.onViewClick(false);
39044                 }
39045                 return true;
39046             },
39047
39048             scope : this,
39049
39050             doRelay : function(e, h, hname){
39051                 if(hname == 'down' || this.scope.isExpanded()){
39052                     
39053                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
39054                     if(!Ext.isIE && Ext.EventManager.useKeydown){
39055                         
39056                         this.scope.fireKey(e);
39057                     }
39058                     return relay;
39059                 }
39060                 return true;
39061             },
39062
39063             forceKeyDown : true,
39064             defaultEventAction: 'stopEvent'
39065         });
39066         this.queryDelay = Math.max(this.queryDelay || 10,
39067                 this.mode == 'local' ? 10 : 250);
39068         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
39069         if(this.typeAhead){
39070             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
39071         }
39072         if(!this.enableKeyEvents){
39073             this.mon(this.el, 'keyup', this.onKeyUp, this);
39074         }
39075     },
39076
39077
39078     
39079     onDestroy : function(){
39080         if (this.dqTask){
39081             this.dqTask.cancel();
39082             this.dqTask = null;
39083         }
39084         this.bindStore(null);
39085         Ext.destroy(
39086             this.resizer,
39087             this.view,
39088             this.pageTb,
39089             this.list
39090         );
39091         Ext.destroyMembers(this, 'hiddenField');
39092         Ext.form.ComboBox.superclass.onDestroy.call(this);
39093     },
39094
39095     
39096     fireKey : function(e){
39097         if (!this.isExpanded()) {
39098             Ext.form.ComboBox.superclass.fireKey.call(this, e);
39099         }
39100     },
39101
39102     
39103     onResize : function(w, h){
39104         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
39105         if(!isNaN(w) && this.isVisible() && this.list){
39106             this.doResize(w);
39107         }else{
39108             this.bufferSize = w;
39109         }
39110     },
39111
39112     doResize: function(w){
39113         if(!Ext.isDefined(this.listWidth)){
39114             var lw = Math.max(w, this.minListWidth);
39115             this.list.setWidth(lw);
39116             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
39117         }
39118     },
39119
39120     
39121     onEnable : function(){
39122         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
39123         if(this.hiddenField){
39124             this.hiddenField.disabled = false;
39125         }
39126     },
39127
39128     
39129     onDisable : function(){
39130         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
39131         if(this.hiddenField){
39132             this.hiddenField.disabled = true;
39133         }
39134     },
39135
39136     
39137     onBeforeLoad : function(){
39138         if(!this.hasFocus){
39139             return;
39140         }
39141         this.innerList.update(this.loadingText ?
39142                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
39143         this.restrictHeight();
39144         this.selectedIndex = -1;
39145     },
39146
39147     
39148     onLoad : function(){
39149         if(!this.hasFocus){
39150             return;
39151         }
39152         if(this.store.getCount() > 0 || this.listEmptyText){
39153             this.expand();
39154             this.restrictHeight();
39155             if(this.lastQuery == this.allQuery){
39156                 if(this.editable){
39157                     this.el.dom.select();
39158                 }
39159
39160                 if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
39161                     this.select(0, true);
39162                 }
39163             }else{
39164                 if(this.autoSelect !== false){
39165                     this.selectNext();
39166                 }
39167                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
39168                     this.taTask.delay(this.typeAheadDelay);
39169                 }
39170             }
39171         }else{
39172             this.collapse();
39173         }
39174
39175     },
39176
39177     
39178     onTypeAhead : function(){
39179         if(this.store.getCount() > 0){
39180             var r = this.store.getAt(0);
39181             var newValue = r.data[this.displayField];
39182             var len = newValue.length;
39183             var selStart = this.getRawValue().length;
39184             if(selStart != len){
39185                 this.setRawValue(newValue);
39186                 this.selectText(selStart, newValue.length);
39187             }
39188         }
39189     },
39190
39191     
39192     assertValue  : function(){
39193         var val = this.getRawValue(),
39194             rec = this.findRecord(this.displayField, val);
39195
39196         if(!rec && this.forceSelection){
39197             if(val.length > 0 && val != this.emptyText){
39198                 this.el.dom.value = Ext.value(this.lastSelectionText, '');
39199                 this.applyEmptyText();
39200             }else{
39201                 this.clearValue();
39202             }
39203         }else{
39204             if(rec){
39205                 
39206                 
39207                 
39208                 if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
39209                     return;
39210                 }
39211                 val = rec.get(this.valueField || this.displayField);
39212             }
39213             this.setValue(val);
39214         }
39215     },
39216
39217     
39218     onSelect : function(record, index){
39219         if(this.fireEvent('beforeselect', this, record, index) !== false){
39220             this.setValue(record.data[this.valueField || this.displayField]);
39221             this.collapse();
39222             this.fireEvent('select', this, record, index);
39223         }
39224     },
39225
39226     
39227     getName: function(){
39228         var hf = this.hiddenField;
39229         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
39230     },
39231
39232     
39233     getValue : function(){
39234         if(this.valueField){
39235             return Ext.isDefined(this.value) ? this.value : '';
39236         }else{
39237             return Ext.form.ComboBox.superclass.getValue.call(this);
39238         }
39239     },
39240
39241     
39242     clearValue : function(){
39243         if(this.hiddenField){
39244             this.hiddenField.value = '';
39245         }
39246         this.setRawValue('');
39247         this.lastSelectionText = '';
39248         this.applyEmptyText();
39249         this.value = '';
39250     },
39251
39252     
39253     setValue : function(v){
39254         var text = v;
39255         if(this.valueField){
39256             var r = this.findRecord(this.valueField, v);
39257             if(r){
39258                 text = r.data[this.displayField];
39259             }else if(Ext.isDefined(this.valueNotFoundText)){
39260                 text = this.valueNotFoundText;
39261             }
39262         }
39263         this.lastSelectionText = text;
39264         if(this.hiddenField){
39265             this.hiddenField.value = Ext.value(v, '');
39266         }
39267         Ext.form.ComboBox.superclass.setValue.call(this, text);
39268         this.value = v;
39269         return this;
39270     },
39271
39272     
39273     findRecord : function(prop, value){
39274         var record;
39275         if(this.store.getCount() > 0){
39276             this.store.each(function(r){
39277                 if(r.data[prop] == value){
39278                     record = r;
39279                     return false;
39280                 }
39281             });
39282         }
39283         return record;
39284     },
39285
39286     
39287     onViewMove : function(e, t){
39288         this.inKeyMode = false;
39289     },
39290
39291     
39292     onViewOver : function(e, t){
39293         if(this.inKeyMode){ 
39294             return;
39295         }
39296         var item = this.view.findItemFromChild(t);
39297         if(item){
39298             var index = this.view.indexOf(item);
39299             this.select(index, false);
39300         }
39301     },
39302
39303     
39304     onViewClick : function(doFocus){
39305         var index = this.view.getSelectedIndexes()[0],
39306             s = this.store,
39307             r = s.getAt(index);
39308         if(r){
39309             this.onSelect(r, index);
39310         }else {
39311             this.collapse();
39312         }
39313         if(doFocus !== false){
39314             this.el.focus();
39315         }
39316     },
39317
39318
39319     
39320     restrictHeight : function(){
39321         this.innerList.dom.style.height = '';
39322         var inner = this.innerList.dom,
39323             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
39324             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
39325             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
39326             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
39327             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
39328
39329         h = Math.min(h, space, this.maxHeight);
39330
39331         this.innerList.setHeight(h);
39332         this.list.beginUpdate();
39333         this.list.setHeight(h+pad);
39334         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
39335         this.list.endUpdate();
39336     },
39337
39338     
39339     isExpanded : function(){
39340         return this.list && this.list.isVisible();
39341     },
39342
39343     
39344     selectByValue : function(v, scrollIntoView){
39345         if(!Ext.isEmpty(v, true)){
39346             var r = this.findRecord(this.valueField || this.displayField, v);
39347             if(r){
39348                 this.select(this.store.indexOf(r), scrollIntoView);
39349                 return true;
39350             }
39351         }
39352         return false;
39353     },
39354
39355     
39356     select : function(index, scrollIntoView){
39357         this.selectedIndex = index;
39358         this.view.select(index);
39359         if(scrollIntoView !== false){
39360             var el = this.view.getNode(index);
39361             if(el){
39362                 this.innerList.scrollChildIntoView(el, false);
39363             }
39364         }
39365
39366     },
39367
39368     
39369     selectNext : function(){
39370         var ct = this.store.getCount();
39371         if(ct > 0){
39372             if(this.selectedIndex == -1){
39373                 this.select(0);
39374             }else if(this.selectedIndex < ct-1){
39375                 this.select(this.selectedIndex+1);
39376             }
39377         }
39378     },
39379
39380     
39381     selectPrev : function(){
39382         var ct = this.store.getCount();
39383         if(ct > 0){
39384             if(this.selectedIndex == -1){
39385                 this.select(0);
39386             }else if(this.selectedIndex !== 0){
39387                 this.select(this.selectedIndex-1);
39388             }
39389         }
39390     },
39391
39392     
39393     onKeyUp : function(e){
39394         var k = e.getKey();
39395         if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
39396
39397             this.lastKey = k;
39398             this.dqTask.delay(this.queryDelay);
39399         }
39400         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
39401     },
39402
39403     
39404     validateBlur : function(){
39405         return !this.list || !this.list.isVisible();
39406     },
39407
39408     
39409     initQuery : function(){
39410         this.doQuery(this.getRawValue());
39411     },
39412
39413     
39414     beforeBlur : function(){
39415         this.assertValue();
39416     },
39417
39418     
39419     postBlur  : function(){
39420         Ext.form.ComboBox.superclass.postBlur.call(this);
39421         this.collapse();
39422         this.inKeyMode = false;
39423     },
39424
39425     
39426     doQuery : function(q, forceAll){
39427         q = Ext.isEmpty(q) ? '' : q;
39428         var qe = {
39429             query: q,
39430             forceAll: forceAll,
39431             combo: this,
39432             cancel:false
39433         };
39434         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
39435             return false;
39436         }
39437         q = qe.query;
39438         forceAll = qe.forceAll;
39439         if(forceAll === true || (q.length >= this.minChars)){
39440             if(this.lastQuery !== q){
39441                 this.lastQuery = q;
39442                 if(this.mode == 'local'){
39443                     this.selectedIndex = -1;
39444                     if(forceAll){
39445                         this.store.clearFilter();
39446                     }else{
39447                         this.store.filter(this.displayField, q);
39448                     }
39449                     this.onLoad();
39450                 }else{
39451                     this.store.baseParams[this.queryParam] = q;
39452                     this.store.load({
39453                         params: this.getParams(q)
39454                     });
39455                     this.expand();
39456                 }
39457             }else{
39458                 this.selectedIndex = -1;
39459                 this.onLoad();
39460             }
39461         }
39462     },
39463
39464     
39465     getParams : function(q){
39466         var p = {};
39467         
39468         if(this.pageSize){
39469             p.start = 0;
39470             p.limit = this.pageSize;
39471         }
39472         return p;
39473     },
39474
39475     
39476     collapse : function(){
39477         if(!this.isExpanded()){
39478             return;
39479         }
39480         this.list.hide();
39481         Ext.getDoc().un('mousewheel', this.collapseIf, this);
39482         Ext.getDoc().un('mousedown', this.collapseIf, this);
39483         this.fireEvent('collapse', this);
39484     },
39485
39486     
39487     collapseIf : function(e){
39488         if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
39489             this.collapse();
39490         }
39491     },
39492
39493     
39494     expand : function(){
39495         if(this.isExpanded() || !this.hasFocus){
39496             return;
39497         }
39498
39499         if(this.title || this.pageSize){
39500             this.assetHeight = 0;
39501             if(this.title){
39502                 this.assetHeight += this.header.getHeight();
39503             }
39504             if(this.pageSize){
39505                 this.assetHeight += this.footer.getHeight();
39506             }
39507         }
39508
39509         if(this.bufferSize){
39510             this.doResize(this.bufferSize);
39511             delete this.bufferSize;
39512         }
39513         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
39514
39515         
39516         var listParent = Ext.getDom(this.getListParent() || Ext.getBody()),
39517             zindex = parseInt(Ext.fly(listParent).getStyle('z-index') ,10);
39518         if (!zindex){
39519             zindex = this.getParentZIndex();
39520         }
39521         if (zindex) {
39522             this.list.setZIndex(zindex + 5);
39523         }
39524         this.list.show();
39525         if(Ext.isGecko2){
39526             this.innerList.setOverflow('auto'); 
39527         }
39528         this.mon(Ext.getDoc(), {
39529             scope: this,
39530             mousewheel: this.collapseIf,
39531             mousedown: this.collapseIf
39532         });
39533         this.fireEvent('expand', this);
39534     },
39535
39536     
39537     
39538     
39539     onTriggerClick : function(){
39540         if(this.readOnly || this.disabled){
39541             return;
39542         }
39543         if(this.isExpanded()){
39544             this.collapse();
39545             this.el.focus();
39546         }else {
39547             this.onFocus({});
39548             if(this.triggerAction == 'all') {
39549                 this.doQuery(this.allQuery, true);
39550             } else {
39551                 this.doQuery(this.getRawValue());
39552             }
39553             this.el.focus();
39554         }
39555     }
39556
39557     
39558     
39559     
39560     
39561
39562 });
39563 Ext.reg('combo', Ext.form.ComboBox);
39564
39565 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
39566     
39567     focusClass : undefined,
39568     
39569     fieldClass : 'x-form-field',
39570     
39571     checked : false,
39572     
39573     boxLabel: '&#160;',
39574     
39575     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
39576     
39577     
39578     
39579     
39580
39581     
39582     actionMode : 'wrap',
39583
39584         
39585     initComponent : function(){
39586         Ext.form.Checkbox.superclass.initComponent.call(this);
39587         this.addEvents(
39588             
39589             'check'
39590         );
39591     },
39592
39593     
39594     onResize : function(){
39595         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
39596         if(!this.boxLabel && !this.fieldLabel){
39597             this.el.alignTo(this.wrap, 'c-c');
39598         }
39599     },
39600
39601     
39602     initEvents : function(){
39603         Ext.form.Checkbox.superclass.initEvents.call(this);
39604         this.mon(this.el, {
39605             scope: this,
39606             click: this.onClick,
39607             change: this.onClick
39608         });
39609     },
39610
39611     
39612     markInvalid : Ext.emptyFn,
39613     
39614     clearInvalid : Ext.emptyFn,
39615
39616     
39617     onRender : function(ct, position){
39618         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
39619         if(this.inputValue !== undefined){
39620             this.el.dom.value = this.inputValue;
39621         }
39622         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
39623         if(this.boxLabel){
39624             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
39625         }
39626         if(this.checked){
39627             this.setValue(true);
39628         }else{
39629             this.checked = this.el.dom.checked;
39630         }
39631         
39632         if(Ext.isIE){
39633             this.wrap.repaint();
39634         }
39635         this.resizeEl = this.positionEl = this.wrap;
39636     },
39637
39638     
39639     onDestroy : function(){
39640         Ext.destroy(this.wrap);
39641         Ext.form.Checkbox.superclass.onDestroy.call(this);
39642     },
39643
39644     
39645     initValue : function() {
39646         this.originalValue = this.getValue();
39647     },
39648
39649     
39650     getValue : function(){
39651         if(this.rendered){
39652             return this.el.dom.checked;
39653         }
39654         return this.checked;
39655     },
39656
39657         
39658     onClick : function(){
39659         if(this.el.dom.checked != this.checked){
39660             this.setValue(this.el.dom.checked);
39661         }
39662     },
39663
39664     
39665     setValue : function(v){
39666         var checked = this.checked ;
39667         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
39668         if(this.rendered){
39669             this.el.dom.checked = this.checked;
39670             this.el.dom.defaultChecked = this.checked;
39671         }
39672         if(checked != this.checked){
39673             this.fireEvent('check', this, this.checked);
39674             if(this.handler){
39675                 this.handler.call(this.scope || this, this, this.checked);
39676             }
39677         }
39678         return this;
39679     }
39680 });
39681 Ext.reg('checkbox', Ext.form.Checkbox);
39682
39683 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
39684     
39685     
39686     columns : 'auto',
39687     
39688     vertical : false,
39689     
39690     allowBlank : true,
39691     
39692     blankText : "You must select at least one item in this group",
39693
39694     
39695     defaultType : 'checkbox',
39696
39697     
39698     groupCls : 'x-form-check-group',
39699
39700     
39701     initComponent: function(){
39702         this.addEvents(
39703             
39704             'change'
39705         );
39706         this.on('change', this.validate, this);
39707         Ext.form.CheckboxGroup.superclass.initComponent.call(this);
39708     },
39709
39710     
39711     onRender : function(ct, position){
39712         if(!this.el){
39713             var panelCfg = {
39714                 autoEl: {
39715                     id: this.id
39716                 },
39717                 cls: this.groupCls,
39718                 layout: 'column',
39719                 renderTo: ct,
39720                 bufferResize: false 
39721             };
39722             var colCfg = {
39723                 xtype: 'container',
39724                 defaultType: this.defaultType,
39725                 layout: 'form',
39726                 defaults: {
39727                     hideLabel: true,
39728                     anchor: '100%'
39729                 }
39730             };
39731
39732             if(this.items[0].items){
39733
39734                 
39735
39736                 Ext.apply(panelCfg, {
39737                     layoutConfig: {columns: this.items.length},
39738                     defaults: this.defaults,
39739                     items: this.items
39740                 });
39741                 for(var i=0, len=this.items.length; i<len; i++){
39742                     Ext.applyIf(this.items[i], colCfg);
39743                 }
39744
39745             }else{
39746
39747                 
39748                 
39749
39750                 var numCols, cols = [];
39751
39752                 if(typeof this.columns == 'string'){ 
39753                     this.columns = this.items.length;
39754                 }
39755                 if(!Ext.isArray(this.columns)){
39756                     var cs = [];
39757                     for(var i=0; i<this.columns; i++){
39758                         cs.push((100/this.columns)*.01); 
39759                     }
39760                     this.columns = cs;
39761                 }
39762
39763                 numCols = this.columns.length;
39764
39765                 
39766                 for(var i=0; i<numCols; i++){
39767                     var cc = Ext.apply({items:[]}, colCfg);
39768                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
39769                     if(this.defaults){
39770                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
39771                     }
39772                     cols.push(cc);
39773                 };
39774
39775                 
39776                 if(this.vertical){
39777                     var rows = Math.ceil(this.items.length / numCols), ri = 0;
39778                     for(var i=0, len=this.items.length; i<len; i++){
39779                         if(i>0 && i%rows==0){
39780                             ri++;
39781                         }
39782                         if(this.items[i].fieldLabel){
39783                             this.items[i].hideLabel = false;
39784                         }
39785                         cols[ri].items.push(this.items[i]);
39786                     };
39787                 }else{
39788                     for(var i=0, len=this.items.length; i<len; i++){
39789                         var ci = i % numCols;
39790                         if(this.items[i].fieldLabel){
39791                             this.items[i].hideLabel = false;
39792                         }
39793                         cols[ci].items.push(this.items[i]);
39794                     };
39795                 }
39796
39797                 Ext.apply(panelCfg, {
39798                     layoutConfig: {columns: numCols},
39799                     items: cols
39800                 });
39801             }
39802
39803             this.panel = new Ext.Container(panelCfg);
39804             this.panel.ownerCt = this;
39805             this.el = this.panel.getEl();
39806
39807             if(this.forId && this.itemCls){
39808                 var l = this.el.up(this.itemCls).child('label', true);
39809                 if(l){
39810                     l.setAttribute('htmlFor', this.forId);
39811                 }
39812             }
39813
39814             var fields = this.panel.findBy(function(c){
39815                 return c.isFormField;
39816             }, this);
39817
39818             this.items = new Ext.util.MixedCollection();
39819             this.items.addAll(fields);
39820         }
39821         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
39822     },
39823
39824     initValue : function(){
39825         if(this.value){
39826             this.setValue.apply(this, this.buffered ? this.value : [this.value]);
39827             delete this.buffered;
39828             delete this.value;
39829         }
39830     },
39831
39832     afterRender : function(){
39833         Ext.form.CheckboxGroup.superclass.afterRender.call(this);
39834         this.eachItem(function(item){
39835             item.on('check', this.fireChecked, this);
39836             item.inGroup = true;
39837         });
39838     },
39839
39840     
39841     doLayout: function(){
39842         
39843         if(this.rendered){
39844             this.panel.forceLayout = this.ownerCt.forceLayout;
39845             this.panel.doLayout();
39846         }
39847     },
39848
39849     
39850     fireChecked: function(){
39851         var arr = [];
39852         this.eachItem(function(item){
39853             if(item.checked){
39854                 arr.push(item);
39855             }
39856         });
39857         this.fireEvent('change', this, arr);
39858     },
39859     
39860     
39861     getErrors: function() {
39862         var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
39863         
39864         if (!this.allowBlank) {
39865             var blank = true;
39866             
39867             this.eachItem(function(f){
39868                 if (f.checked) {
39869                     return (blank = false);
39870                 }
39871             });
39872             
39873             if (blank) errors.push(this.blankText);
39874         }
39875         
39876         return errors;
39877     },
39878
39879     
39880     isDirty: function(){
39881         
39882         if (this.disabled || !this.rendered) {
39883             return false;
39884         }
39885
39886         var dirty = false;
39887         
39888         this.eachItem(function(item){
39889             if(item.isDirty()){
39890                 dirty = true;
39891                 return false;
39892             }
39893         });
39894         
39895         return dirty;
39896     },
39897
39898     
39899     setReadOnly : function(readOnly){
39900         if(this.rendered){
39901             this.eachItem(function(item){
39902                 item.setReadOnly(readOnly);
39903             });
39904         }
39905         this.readOnly = readOnly;
39906     },
39907
39908     
39909     onDisable : function(){
39910         this.eachItem(function(item){
39911             item.disable();
39912         });
39913     },
39914
39915     
39916     onEnable : function(){
39917         this.eachItem(function(item){
39918             item.enable();
39919         });
39920     },
39921
39922     
39923     onResize : function(w, h){
39924         this.panel.setSize(w, h);
39925         this.panel.doLayout();
39926     },
39927
39928     
39929     reset : function(){
39930         if (this.originalValue) {
39931             
39932             this.eachItem(function(c){
39933                 if(c.setValue){
39934                     c.setValue(false);
39935                     c.originalValue = c.getValue();
39936                 }
39937             });
39938             
39939             
39940             this.resetOriginal = true;
39941             this.setValue(this.originalValue);
39942             delete this.resetOriginal;
39943         } else {
39944             this.eachItem(function(c){
39945                 if(c.reset){
39946                     c.reset();
39947                 }
39948             });
39949         }
39950         
39951         
39952         (function() {
39953             this.clearInvalid();
39954         }).defer(50, this);
39955     },
39956
39957     
39958     setValue: function(){
39959         if(this.rendered){
39960             this.onSetValue.apply(this, arguments);
39961         }else{
39962             this.buffered = true;
39963             this.value = arguments;
39964         }
39965         return this;
39966     },
39967
39968     
39969     onSetValue: function(id, value){
39970         if(arguments.length == 1){
39971             if(Ext.isArray(id)){
39972                 Ext.each(id, function(val, idx){
39973                     if (Ext.isObject(val) && val.setValue){ 
39974                         val.setValue(true);
39975                         if (this.resetOriginal === true) {
39976                             val.originalValue = val.getValue();
39977                         }
39978                     } else { 
39979                         var item = this.items.itemAt(idx);
39980                         if(item){
39981                             item.setValue(val);
39982                         }
39983                     }
39984                 }, this);
39985             }else if(Ext.isObject(id)){
39986                 
39987                 for(var i in id){
39988                     var f = this.getBox(i);
39989                     if(f){
39990                         f.setValue(id[i]);
39991                     }
39992                 }
39993             }else{
39994                 this.setValueForItem(id);
39995             }
39996         }else{
39997             var f = this.getBox(id);
39998             if(f){
39999                 f.setValue(value);
40000             }
40001         }
40002     },
40003
40004     
40005     beforeDestroy: function(){
40006         Ext.destroy(this.panel);
40007         Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
40008
40009     },
40010
40011     setValueForItem : function(val){
40012         val = String(val).split(',');
40013         this.eachItem(function(item){
40014             if(val.indexOf(item.inputValue)> -1){
40015                 item.setValue(true);
40016             }
40017         });
40018     },
40019
40020     
40021     getBox : function(id){
40022         var box = null;
40023         this.eachItem(function(f){
40024             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
40025                 box = f;
40026                 return false;
40027             }
40028         });
40029         return box;
40030     },
40031
40032     
40033     getValue : function(){
40034         var out = [];
40035         this.eachItem(function(item){
40036             if(item.checked){
40037                 out.push(item);
40038             }
40039         });
40040         return out;
40041     },
40042
40043     
40044     eachItem: function(fn, scope) {
40045         if(this.items && this.items.each){
40046             this.items.each(fn, scope || this);
40047         }
40048     },
40049
40050     
40051
40052     
40053     getRawValue : Ext.emptyFn,
40054
40055     
40056     setRawValue : Ext.emptyFn
40057
40058 });
40059
40060 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
40061
40062 Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
40063
40064     
40065     defaultMargins: '0 5 0 0',
40066
40067     
40068     skipLastItemMargin: true,
40069
40070     
40071     isComposite: true,
40072
40073     
40074     combineErrors: true,
40075
40076     
40077     
40078     initComponent: function() {
40079         var labels = [],
40080             items  = this.items,
40081             item;
40082
40083         for (var i=0, j = items.length; i < j; i++) {
40084             item = items[i];
40085
40086             labels.push(item.fieldLabel);
40087
40088             
40089             Ext.apply(item, this.defaults);
40090
40091             
40092             if (!(i == j - 1 && this.skipLastItemMargin)) {
40093                 Ext.applyIf(item, {margins: this.defaultMargins});
40094             }
40095         }
40096
40097         this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
40098
40099         
40100         this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
40101             return item.field;
40102         });
40103
40104         this.fieldErrors.on({
40105             scope  : this,
40106             add    : this.updateInvalidMark,
40107             remove : this.updateInvalidMark,
40108             replace: this.updateInvalidMark
40109         });
40110
40111         Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
40112     },
40113
40114     
40115     onRender: function(ct, position) {
40116         if (!this.el) {
40117             
40118             var innerCt = this.innerCt = new Ext.Container({
40119                 layout  : 'hbox',
40120                 renderTo: ct,
40121                 items   : this.items,
40122                 cls     : 'x-form-composite',
40123                 defaultMargins: '0 3 0 0'
40124             });
40125
40126             this.el = innerCt.getEl();
40127
40128             var fields = innerCt.findBy(function(c) {
40129                 return c.isFormField;
40130             }, this);
40131
40132             
40133             this.items = new Ext.util.MixedCollection();
40134             this.items.addAll(fields);
40135
40136             
40137             
40138             if (this.combineErrors) {
40139                 this.eachItem(function(field) {
40140                     Ext.apply(field, {
40141                         markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
40142                         clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
40143                     });
40144                 });
40145             }
40146
40147             
40148             var l = this.el.parent().parent().child('label', true);
40149             if (l) {
40150                 l.setAttribute('for', this.items.items[0].id);
40151             }
40152         }
40153
40154         Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
40155     },
40156
40157     
40158     onFieldMarkInvalid: function(field, message) {
40159         var name  = field.getName(),
40160             error = {field: name, error: message};
40161
40162         this.fieldErrors.replace(name, error);
40163
40164         field.el.addClass(field.invalidClass);
40165     },
40166
40167     
40168     onFieldClearInvalid: function(field) {
40169         this.fieldErrors.removeKey(field.getName());
40170
40171         field.el.removeClass(field.invalidClass);
40172     },
40173
40174     
40175     updateInvalidMark: function() {
40176         var ieStrict = Ext.isIE6 && Ext.isStrict;
40177
40178         if (this.fieldErrors.length == 0) {
40179             this.clearInvalid();
40180
40181             
40182             if (ieStrict) {
40183                 this.clearInvalid.defer(50, this);
40184             }
40185         } else {
40186             var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
40187
40188             this.sortErrors();
40189             this.markInvalid(message);
40190
40191             
40192             if (ieStrict) {
40193                 this.markInvalid(message);
40194             }
40195         }
40196     },
40197
40198     
40199     validateValue: function() {
40200         var valid = true;
40201
40202         this.eachItem(function(field) {
40203             if (!field.isValid()) valid = false;
40204         });
40205
40206         return valid;
40207     },
40208
40209     
40210     buildCombinedErrorMessage: function(errors) {
40211         var combined = [],
40212             error;
40213
40214         for (var i = 0, j = errors.length; i < j; i++) {
40215             error = errors[i];
40216
40217             combined.push(String.format("{0}: {1}", error.field, error.error));
40218         }
40219
40220         return combined.join("<br />");
40221     },
40222
40223     
40224     sortErrors: function() {
40225         var fields = this.items;
40226
40227         this.fieldErrors.sort("ASC", function(a, b) {
40228             var findByName = function(key) {
40229                 return function(field) {
40230                     return field.getName() == key;
40231                 };
40232             };
40233
40234             var aIndex = fields.findIndexBy(findByName(a.field)),
40235                 bIndex = fields.findIndexBy(findByName(b.field));
40236
40237             return aIndex < bIndex ? -1 : 1;
40238         });
40239     },
40240
40241     
40242     reset: function() {
40243         this.eachItem(function(item) {
40244             item.reset();
40245         });
40246
40247         
40248         
40249         (function() {
40250             this.clearInvalid();
40251         }).defer(50, this);
40252     },
40253     
40254     
40255     clearInvalidChildren: function() {
40256         this.eachItem(function(item) {
40257             item.clearInvalid();
40258         });
40259     },
40260
40261     
40262     buildLabel: function(segments) {
40263         return segments.join(", ");
40264     },
40265
40266     
40267     isDirty: function(){
40268         
40269         if (this.disabled || !this.rendered) {
40270             return false;
40271         }
40272
40273         var dirty = false;
40274         this.eachItem(function(item){
40275             if(item.isDirty()){
40276                 dirty = true;
40277                 return false;
40278             }
40279         });
40280         return dirty;
40281     },
40282
40283     
40284     eachItem: function(fn, scope) {
40285         if(this.items && this.items.each){
40286             this.items.each(fn, scope || this);
40287         }
40288     },
40289
40290     
40291     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
40292         var innerCt = this.innerCt;
40293
40294         if (this.rendered && innerCt.rendered) {
40295             innerCt.setSize(adjWidth, adjHeight);
40296         }
40297
40298         Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
40299     },
40300
40301     
40302     doLayout: function(shallow, force) {
40303         if (this.rendered) {
40304             var innerCt = this.innerCt;
40305
40306             innerCt.forceLayout = this.ownerCt.forceLayout;
40307             innerCt.doLayout(shallow, force);
40308         }
40309     },
40310
40311     
40312     beforeDestroy: function(){
40313         Ext.destroy(this.innerCt);
40314
40315         Ext.form.CompositeField.superclass.beforeDestroy.call(this);
40316     },
40317
40318     
40319     setReadOnly : function(readOnly) {
40320         readOnly = readOnly || true;
40321
40322         if(this.rendered){
40323             this.eachItem(function(item){
40324                 item.setReadOnly(readOnly);
40325             });
40326         }
40327         this.readOnly = readOnly;
40328     },
40329
40330     onShow : function() {
40331         Ext.form.CompositeField.superclass.onShow.call(this);
40332         this.doLayout();
40333     },
40334
40335     
40336     onDisable : function(){
40337         this.eachItem(function(item){
40338             item.disable();
40339         });
40340     },
40341
40342     
40343     onEnable : function(){
40344         this.eachItem(function(item){
40345             item.enable();
40346         });
40347     }
40348 });
40349
40350 Ext.reg('compositefield', Ext.form.CompositeField);
40351
40352 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
40353     inputType: 'radio',
40354
40355     
40356     markInvalid : Ext.emptyFn,
40357     
40358     clearInvalid : Ext.emptyFn,
40359
40360     
40361     getGroupValue : function(){
40362         var p = this.el.up('form') || Ext.getBody();
40363         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
40364         return c ? c.value : null;
40365     },
40366
40367     
40368     onClick : function(){
40369         if(this.el.dom.checked != this.checked){
40370                         var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
40371                         els.each(function(el){
40372                                 if(el.dom.id == this.id){
40373                                         this.setValue(true);
40374                                 }else{
40375                                         Ext.getCmp(el.dom.id).setValue(false);
40376                                 }
40377                         }, this);
40378                 }
40379     },
40380
40381     
40382     setValue : function(v){
40383         if (typeof v == 'boolean') {
40384             Ext.form.Radio.superclass.setValue.call(this, v);
40385         } else if (this.rendered) {
40386             var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
40387             if(r){
40388                 Ext.getCmp(r.id).setValue(true);
40389             }
40390         }
40391         return this;
40392     },
40393
40394     
40395     getCheckEl: function(){
40396         if(this.inGroup){
40397             return this.el.up('.x-form-radio-group')
40398         }
40399         return this.el.up('form') || Ext.getBody();
40400     }
40401 });
40402 Ext.reg('radio', Ext.form.Radio);
40403
40404 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
40405     
40406     
40407     allowBlank : true,
40408     
40409     blankText : 'You must select one item in this group',
40410     
40411     
40412     defaultType : 'radio',
40413     
40414     
40415     groupCls : 'x-form-radio-group',
40416     
40417     
40418     
40419     
40420     getValue : function(){
40421         var out = null;
40422         this.eachItem(function(item){
40423             if(item.checked){
40424                 out = item;
40425                 return false;
40426             }
40427         });
40428         return out;
40429     },
40430     
40431     
40432     onSetValue : function(id, value){
40433         if(arguments.length > 1){
40434             var f = this.getBox(id);
40435             if(f){
40436                 f.setValue(value);
40437                 if(f.checked){
40438                     this.eachItem(function(item){
40439                         if (item !== f){
40440                             item.setValue(false);
40441                         }
40442                     });
40443                 }
40444             }
40445         }else{
40446             this.setValueForItem(id);
40447         }
40448     },
40449     
40450     setValueForItem : function(val){
40451         val = String(val).split(',')[0];
40452         this.eachItem(function(item){
40453             item.setValue(val == item.inputValue);
40454         });
40455     },
40456     
40457     
40458     fireChecked : function(){
40459         if(!this.checkTask){
40460             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
40461         }
40462         this.checkTask.delay(10);
40463     },
40464     
40465     
40466     bufferChecked : function(){
40467         var out = null;
40468         this.eachItem(function(item){
40469             if(item.checked){
40470                 out = item;
40471                 return false;
40472             }
40473         });
40474         this.fireEvent('change', this, out);
40475     },
40476     
40477     onDestroy : function(){
40478         if(this.checkTask){
40479             this.checkTask.cancel();
40480             this.checkTask = null;
40481         }
40482         Ext.form.RadioGroup.superclass.onDestroy.call(this);
40483     }
40484
40485 });
40486
40487 Ext.reg('radiogroup', Ext.form.RadioGroup);
40488
40489 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
40490     
40491     inputType : 'hidden',
40492
40493     
40494     onRender : function(){
40495         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
40496     },
40497
40498     
40499     initEvents : function(){
40500         this.originalValue = this.getValue();
40501     },
40502
40503     
40504     setSize : Ext.emptyFn,
40505     setWidth : Ext.emptyFn,
40506     setHeight : Ext.emptyFn,
40507     setPosition : Ext.emptyFn,
40508     setPagePosition : Ext.emptyFn,
40509     markInvalid : Ext.emptyFn,
40510     clearInvalid : Ext.emptyFn
40511 });
40512 Ext.reg('hidden', Ext.form.Hidden);
40513 Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
40514
40515     constructor: function(el, config){
40516         Ext.apply(this, config);
40517         if(Ext.isString(this.paramOrder)){
40518             this.paramOrder = this.paramOrder.split(/[\s,|]/);
40519         }
40520         
40521         this.items = new Ext.util.MixedCollection(false, function(o){
40522             return o.getItemId();
40523         });
40524         this.addEvents(
40525             
40526             'beforeaction',
40527             
40528             'actionfailed',
40529             
40530             'actioncomplete'
40531         );
40532
40533         if(el){
40534             this.initEl(el);
40535         }
40536         Ext.form.BasicForm.superclass.constructor.call(this);
40537     },
40538
40539     
40540     
40541     
40542     
40543     
40544     
40545     
40546     timeout: 30,
40547
40548     
40549
40550     
40551     paramOrder: undefined,
40552
40553     
40554     paramsAsHash: false,
40555
40556     
40557     waitTitle: 'Please Wait...',
40558
40559     
40560     activeAction : null,
40561
40562     
40563     trackResetOnLoad : false,
40564
40565     
40566     
40567
40568     
40569     initEl : function(el){
40570         this.el = Ext.get(el);
40571         this.id = this.el.id || Ext.id();
40572         if(!this.standardSubmit){
40573             this.el.on('submit', this.onSubmit, this);
40574         }
40575         this.el.addClass('x-form');
40576     },
40577
40578     
40579     getEl: function(){
40580         return this.el;
40581     },
40582
40583     
40584     onSubmit : function(e){
40585         e.stopEvent();
40586     },
40587
40588     
40589     destroy: function(bound){
40590         if(bound !== true){
40591             this.items.each(function(f){
40592                 Ext.destroy(f);
40593             });
40594             Ext.destroy(this.el);
40595         }
40596         this.items.clear();
40597         this.purgeListeners();
40598     },
40599
40600     
40601     isValid : function(){
40602         var valid = true;
40603         this.items.each(function(f){
40604            if(!f.validate()){
40605                valid = false;
40606            }
40607         });
40608         return valid;
40609     },
40610
40611     
40612     isDirty : function(){
40613         var dirty = false;
40614         this.items.each(function(f){
40615            if(f.isDirty()){
40616                dirty = true;
40617                return false;
40618            }
40619         });
40620         return dirty;
40621     },
40622
40623     
40624     doAction : function(action, options){
40625         if(Ext.isString(action)){
40626             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
40627         }
40628         if(this.fireEvent('beforeaction', this, action) !== false){
40629             this.beforeAction(action);
40630             action.run.defer(100, action);
40631         }
40632         return this;
40633     },
40634
40635     
40636     submit : function(options){
40637         options = options || {};
40638         if(this.standardSubmit){
40639             var v = options.clientValidation === false || this.isValid();
40640             if(v){
40641                 var el = this.el.dom;
40642                 if(this.url && Ext.isEmpty(el.action)){
40643                     el.action = this.url;
40644                 }
40645                 el.submit();
40646             }
40647             return v;
40648         }
40649         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
40650         this.doAction(submitAction, options);
40651         return this;
40652     },
40653
40654     
40655     load : function(options){
40656         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
40657         this.doAction(loadAction, options);
40658         return this;
40659     },
40660
40661     
40662     updateRecord : function(record){
40663         record.beginEdit();
40664         var fs = record.fields;
40665         fs.each(function(f){
40666             var field = this.findField(f.name);
40667             if(field){
40668                 record.set(f.name, field.getValue());
40669             }
40670         }, this);
40671         record.endEdit();
40672         return this;
40673     },
40674
40675     
40676     loadRecord : function(record){
40677         this.setValues(record.data);
40678         return this;
40679     },
40680
40681     
40682     beforeAction : function(action){
40683         
40684         this.items.each(function(f){
40685             if(f.isFormField && f.syncValue){
40686                 f.syncValue();
40687             }
40688         });
40689         var o = action.options;
40690         if(o.waitMsg){
40691             if(this.waitMsgTarget === true){
40692                 this.el.mask(o.waitMsg, 'x-mask-loading');
40693             }else if(this.waitMsgTarget){
40694                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
40695                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
40696             }else{
40697                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
40698             }
40699         }
40700     },
40701
40702     
40703     afterAction : function(action, success){
40704         this.activeAction = null;
40705         var o = action.options;
40706         if(o.waitMsg){
40707             if(this.waitMsgTarget === true){
40708                 this.el.unmask();
40709             }else if(this.waitMsgTarget){
40710                 this.waitMsgTarget.unmask();
40711             }else{
40712                 Ext.MessageBox.updateProgress(1);
40713                 Ext.MessageBox.hide();
40714             }
40715         }
40716         if(success){
40717             if(o.reset){
40718                 this.reset();
40719             }
40720             Ext.callback(o.success, o.scope, [this, action]);
40721             this.fireEvent('actioncomplete', this, action);
40722         }else{
40723             Ext.callback(o.failure, o.scope, [this, action]);
40724             this.fireEvent('actionfailed', this, action);
40725         }
40726     },
40727
40728     
40729     findField : function(id) {
40730         var field = this.items.get(id);
40731
40732         if (!Ext.isObject(field)) {
40733             
40734             var findMatchingField = function(f) {
40735                 if (f.isFormField) {
40736                     if (f.dataIndex == id || f.id == id || f.getName() == id) {
40737                         field = f;
40738                         return false;
40739                     } else if (f.isComposite && f.rendered) {
40740                         return f.items.each(findMatchingField);
40741                     }
40742                 }
40743             };
40744
40745             this.items.each(findMatchingField);
40746         }
40747         return field || null;
40748     },
40749
40750
40751     
40752     markInvalid : function(errors){
40753         if (Ext.isArray(errors)) {
40754             for(var i = 0, len = errors.length; i < len; i++){
40755                 var fieldError = errors[i];
40756                 var f = this.findField(fieldError.id);
40757                 if(f){
40758                     f.markInvalid(fieldError.msg);
40759                 }
40760             }
40761         } else {
40762             var field, id;
40763             for(id in errors){
40764                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
40765                     field.markInvalid(errors[id]);
40766                 }
40767             }
40768         }
40769
40770         return this;
40771     },
40772
40773     
40774     setValues : function(values){
40775         if(Ext.isArray(values)){ 
40776             for(var i = 0, len = values.length; i < len; i++){
40777                 var v = values[i];
40778                 var f = this.findField(v.id);
40779                 if(f){
40780                     f.setValue(v.value);
40781                     if(this.trackResetOnLoad){
40782                         f.originalValue = f.getValue();
40783                     }
40784                 }
40785             }
40786         }else{ 
40787             var field, id;
40788             for(id in values){
40789                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
40790                     field.setValue(values[id]);
40791                     if(this.trackResetOnLoad){
40792                         field.originalValue = field.getValue();
40793                     }
40794                 }
40795             }
40796         }
40797         return this;
40798     },
40799
40800     
40801     getValues : function(asString){
40802         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
40803         if(asString === true){
40804             return fs;
40805         }
40806         return Ext.urlDecode(fs);
40807     },
40808
40809     
40810     getFieldValues : function(dirtyOnly){
40811         var o = {},
40812             n,
40813             key,
40814             val;
40815         this.items.each(function(f) {
40816             if (dirtyOnly !== true || f.isDirty()) {
40817                 n = f.getName();
40818                 key = o[n];
40819                 val = f.getValue();
40820
40821                 if(Ext.isDefined(key)){
40822                     if(Ext.isArray(key)){
40823                         o[n].push(val);
40824                     }else{
40825                         o[n] = [key, val];
40826                     }
40827                 }else{
40828                     o[n] = val;
40829                 }
40830             }
40831         });
40832         return o;
40833     },
40834
40835     
40836     clearInvalid : function(){
40837         this.items.each(function(f){
40838            f.clearInvalid();
40839         });
40840         return this;
40841     },
40842
40843     
40844     reset : function(){
40845         this.items.each(function(f){
40846             f.reset();
40847         });
40848         return this;
40849     },
40850
40851     
40852     add : function(){
40853         this.items.addAll(Array.prototype.slice.call(arguments, 0));
40854         return this;
40855     },
40856
40857     
40858     remove : function(field){
40859         this.items.remove(field);
40860         return this;
40861     },
40862
40863     
40864     cleanDestroyed : function() {
40865         this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
40866     },
40867
40868     
40869     render : function(){
40870         this.items.each(function(f){
40871             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
40872                 f.applyToMarkup(f.id);
40873             }
40874         });
40875         return this;
40876     },
40877
40878     
40879     applyToFields : function(o){
40880         this.items.each(function(f){
40881            Ext.apply(f, o);
40882         });
40883         return this;
40884     },
40885
40886     
40887     applyIfToFields : function(o){
40888         this.items.each(function(f){
40889            Ext.applyIf(f, o);
40890         });
40891         return this;
40892     },
40893
40894     callFieldMethod : function(fnName, args){
40895         args = args || [];
40896         this.items.each(function(f){
40897             if(Ext.isFunction(f[fnName])){
40898                 f[fnName].apply(f, args);
40899             }
40900         });
40901         return this;
40902     }
40903 });
40904
40905
40906 Ext.BasicForm = Ext.form.BasicForm;
40907
40908 Ext.FormPanel = Ext.extend(Ext.Panel, {
40909     
40910     
40911     
40912     
40913     
40914     
40915     
40916
40917
40918     
40919     minButtonWidth : 75,
40920
40921     
40922     labelAlign : 'left',
40923
40924     
40925     monitorValid : false,
40926
40927     
40928     monitorPoll : 200,
40929
40930     
40931     layout : 'form',
40932
40933     
40934     initComponent : function(){
40935         this.form = this.createForm();
40936         Ext.FormPanel.superclass.initComponent.call(this);
40937
40938         this.bodyCfg = {
40939             tag: 'form',
40940             cls: this.baseCls + '-body',
40941             method : this.method || 'POST',
40942             id : this.formId || Ext.id()
40943         };
40944         if(this.fileUpload) {
40945             this.bodyCfg.enctype = 'multipart/form-data';
40946         }
40947         this.initItems();
40948
40949         this.addEvents(
40950             
40951             'clientvalidation'
40952         );
40953
40954         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
40955     },
40956
40957     
40958     createForm : function(){
40959         var config = Ext.applyIf({listeners: {}}, this.initialConfig);
40960         return new Ext.form.BasicForm(null, config);
40961     },
40962
40963     
40964     initFields : function(){
40965         var f = this.form;
40966         var formPanel = this;
40967         var fn = function(c){
40968             if(formPanel.isField(c)){
40969                 f.add(c);
40970             }else if(c.findBy && c != formPanel){
40971                 formPanel.applySettings(c);
40972                 
40973                 if(c.items && c.items.each){
40974                     c.items.each(fn, this);
40975                 }
40976             }
40977         };
40978         this.items.each(fn, this);
40979     },
40980
40981     
40982     applySettings: function(c){
40983         var ct = c.ownerCt;
40984         Ext.applyIf(c, {
40985             labelAlign: ct.labelAlign,
40986             labelWidth: ct.labelWidth,
40987             itemCls: ct.itemCls
40988         });
40989     },
40990
40991     
40992     getLayoutTarget : function(){
40993         return this.form.el;
40994     },
40995
40996     
40997     getForm : function(){
40998         return this.form;
40999     },
41000
41001     
41002     onRender : function(ct, position){
41003         this.initFields();
41004         Ext.FormPanel.superclass.onRender.call(this, ct, position);
41005         this.form.initEl(this.body);
41006     },
41007
41008     
41009     beforeDestroy : function(){
41010         this.stopMonitoring();
41011         this.form.destroy(true);
41012         Ext.FormPanel.superclass.beforeDestroy.call(this);
41013     },
41014
41015     
41016     isField : function(c) {
41017         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
41018     },
41019
41020     
41021     initEvents : function(){
41022         Ext.FormPanel.superclass.initEvents.call(this);
41023         
41024         this.on({
41025             scope: this,
41026             add: this.onAddEvent,
41027             remove: this.onRemoveEvent
41028         });
41029         if(this.monitorValid){ 
41030             this.startMonitoring();
41031         }
41032     },
41033
41034     
41035     onAdd: function(c){
41036         Ext.FormPanel.superclass.onAdd.call(this, c);
41037         this.processAdd(c);
41038     },
41039
41040     
41041     onAddEvent: function(ct, c){
41042         if(ct !== this){
41043             this.processAdd(c);
41044         }
41045     },
41046
41047     
41048     processAdd : function(c){
41049         
41050         if(this.isField(c)){
41051             this.form.add(c);
41052         
41053         }else if(c.findBy){
41054             this.applySettings(c);
41055             this.form.add.apply(this.form, c.findBy(this.isField));
41056         }
41057     },
41058
41059     
41060     onRemove: function(c){
41061         Ext.FormPanel.superclass.onRemove.call(this, c);
41062         this.processRemove(c);
41063     },
41064
41065     onRemoveEvent: function(ct, c){
41066         if(ct !== this){
41067             this.processRemove(c);
41068         }
41069     },
41070
41071     
41072     processRemove: function(c){
41073         if(!this.destroying){
41074             
41075             if(this.isField(c)){
41076                 this.form.remove(c);
41077             
41078             }else if (c.findBy){
41079                 Ext.each(c.findBy(this.isField), this.form.remove, this.form);
41080                 if (c.isDestroyed) {
41081                     this.form.cleanDestroyed();
41082                 }
41083             }
41084         }
41085     },
41086
41087     
41088     startMonitoring : function(){
41089         if(!this.validTask){
41090             this.validTask = new Ext.util.TaskRunner();
41091             this.validTask.start({
41092                 run : this.bindHandler,
41093                 interval : this.monitorPoll || 200,
41094                 scope: this
41095             });
41096         }
41097     },
41098
41099     
41100     stopMonitoring : function(){
41101         if(this.validTask){
41102             this.validTask.stopAll();
41103             this.validTask = null;
41104         }
41105     },
41106
41107     
41108     load : function(){
41109         this.form.load.apply(this.form, arguments);
41110     },
41111
41112     
41113     onDisable : function(){
41114         Ext.FormPanel.superclass.onDisable.call(this);
41115         if(this.form){
41116             this.form.items.each(function(){
41117                  this.disable();
41118             });
41119         }
41120     },
41121
41122     
41123     onEnable : function(){
41124         Ext.FormPanel.superclass.onEnable.call(this);
41125         if(this.form){
41126             this.form.items.each(function(){
41127                  this.enable();
41128             });
41129         }
41130     },
41131
41132     
41133     bindHandler : function(){
41134         var valid = true;
41135         this.form.items.each(function(f){
41136             if(!f.isValid(true)){
41137                 valid = false;
41138                 return false;
41139             }
41140         });
41141         if(this.fbar){
41142             var fitems = this.fbar.items.items;
41143             for(var i = 0, len = fitems.length; i < len; i++){
41144                 var btn = fitems[i];
41145                 if(btn.formBind === true && btn.disabled === valid){
41146                     btn.setDisabled(!valid);
41147                 }
41148             }
41149         }
41150         this.fireEvent('clientvalidation', this, valid);
41151     }
41152 });
41153 Ext.reg('form', Ext.FormPanel);
41154
41155 Ext.form.FormPanel = Ext.FormPanel;
41156
41157 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
41158     
41159     
41160     
41161     
41162     
41163     
41164     baseCls : 'x-fieldset',
41165     
41166     layout : 'form',
41167     
41168     animCollapse : false,
41169
41170     
41171     onRender : function(ct, position){
41172         if(!this.el){
41173             this.el = document.createElement('fieldset');
41174             this.el.id = this.id;
41175             if (this.title || this.header || this.checkboxToggle) {
41176                 this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
41177             }
41178         }
41179
41180         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
41181
41182         if(this.checkboxToggle){
41183             var o = typeof this.checkboxToggle == 'object' ?
41184                     this.checkboxToggle :
41185                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
41186             this.checkbox = this.header.insertFirst(o);
41187             this.checkbox.dom.checked = !this.collapsed;
41188             this.mon(this.checkbox, 'click', this.onCheckClick, this);
41189         }
41190     },
41191
41192     
41193     onCollapse : function(doAnim, animArg){
41194         if(this.checkbox){
41195             this.checkbox.dom.checked = false;
41196         }
41197         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
41198
41199     },
41200
41201     
41202     onExpand : function(doAnim, animArg){
41203         if(this.checkbox){
41204             this.checkbox.dom.checked = true;
41205         }
41206         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
41207     },
41208
41209     
41210     onCheckClick : function(){
41211         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
41212     }
41213
41214     
41215     
41216     
41217     
41218     
41219     
41220     
41221     
41222     
41223     
41224     
41225     
41226     
41227     
41228     
41229     
41230     
41231     
41232     
41233     
41234     
41235     
41236     
41237     
41238     
41239     
41240     
41241     
41242     
41243     
41244     
41245     
41246     
41247     
41248 });
41249 Ext.reg('fieldset', Ext.form.FieldSet);
41250
41251 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
41252     
41253     enableFormat : true,
41254     
41255     enableFontSize : true,
41256     
41257     enableColors : true,
41258     
41259     enableAlignments : true,
41260     
41261     enableLists : true,
41262     
41263     enableSourceEdit : true,
41264     
41265     enableLinks : true,
41266     
41267     enableFont : true,
41268     
41269     createLinkText : 'Please enter the URL for the link:',
41270     
41271     defaultLinkValue : 'http:/'+'/',
41272     
41273     fontFamilies : [
41274         'Arial',
41275         'Courier New',
41276         'Tahoma',
41277         'Times New Roman',
41278         'Verdana'
41279     ],
41280     defaultFont: 'tahoma',
41281     
41282     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
41283
41284     
41285     actionMode: 'wrap',
41286     validationEvent : false,
41287     deferHeight: true,
41288     initialized : false,
41289     activated : false,
41290     sourceEditMode : false,
41291     onFocus : Ext.emptyFn,
41292     iframePad:3,
41293     hideMode:'offsets',
41294     defaultAutoCreate : {
41295         tag: "textarea",
41296         style:"width:500px;height:300px;",
41297         autocomplete: "off"
41298     },
41299
41300     
41301     initComponent : function(){
41302         this.addEvents(
41303             
41304             'initialize',
41305             
41306             'activate',
41307              
41308             'beforesync',
41309              
41310             'beforepush',
41311              
41312             'sync',
41313              
41314             'push',
41315              
41316             'editmodechange'
41317         );
41318     },
41319
41320     
41321     createFontOptions : function(){
41322         var buf = [], fs = this.fontFamilies, ff, lc;
41323         for(var i = 0, len = fs.length; i< len; i++){
41324             ff = fs[i];
41325             lc = ff.toLowerCase();
41326             buf.push(
41327                 '<option value="',lc,'" style="font-family:',ff,';"',
41328                     (this.defaultFont == lc ? ' selected="true">' : '>'),
41329                     ff,
41330                 '</option>'
41331             );
41332         }
41333         return buf.join('');
41334     },
41335
41336     
41337     createToolbar : function(editor){
41338         var items = [];
41339         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
41340
41341
41342         function btn(id, toggle, handler){
41343             return {
41344                 itemId : id,
41345                 cls : 'x-btn-icon',
41346                 iconCls: 'x-edit-'+id,
41347                 enableToggle:toggle !== false,
41348                 scope: editor,
41349                 handler:handler||editor.relayBtnCmd,
41350                 clickEvent:'mousedown',
41351                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
41352                 overflowText: editor.buttonTips[id].title || undefined,
41353                 tabIndex:-1
41354             };
41355         }
41356
41357
41358         if(this.enableFont && !Ext.isSafari2){
41359             var fontSelectItem = new Ext.Toolbar.Item({
41360                autoEl: {
41361                     tag:'select',
41362                     cls:'x-font-select',
41363                     html: this.createFontOptions()
41364                }
41365             });
41366
41367             items.push(
41368                 fontSelectItem,
41369                 '-'
41370             );
41371         }
41372
41373         if(this.enableFormat){
41374             items.push(
41375                 btn('bold'),
41376                 btn('italic'),
41377                 btn('underline')
41378             );
41379         }
41380
41381         if(this.enableFontSize){
41382             items.push(
41383                 '-',
41384                 btn('increasefontsize', false, this.adjustFont),
41385                 btn('decreasefontsize', false, this.adjustFont)
41386             );
41387         }
41388
41389         if(this.enableColors){
41390             items.push(
41391                 '-', {
41392                     itemId:'forecolor',
41393                     cls:'x-btn-icon',
41394                     iconCls: 'x-edit-forecolor',
41395                     clickEvent:'mousedown',
41396                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
41397                     tabIndex:-1,
41398                     menu : new Ext.menu.ColorMenu({
41399                         allowReselect: true,
41400                         focus: Ext.emptyFn,
41401                         value:'000000',
41402                         plain:true,
41403                         listeners: {
41404                             scope: this,
41405                             select: function(cp, color){
41406                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
41407                                 this.deferFocus();
41408                             }
41409                         },
41410                         clickEvent:'mousedown'
41411                     })
41412                 }, {
41413                     itemId:'backcolor',
41414                     cls:'x-btn-icon',
41415                     iconCls: 'x-edit-backcolor',
41416                     clickEvent:'mousedown',
41417                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
41418                     tabIndex:-1,
41419                     menu : new Ext.menu.ColorMenu({
41420                         focus: Ext.emptyFn,
41421                         value:'FFFFFF',
41422                         plain:true,
41423                         allowReselect: true,
41424                         listeners: {
41425                             scope: this,
41426                             select: function(cp, color){
41427                                 if(Ext.isGecko){
41428                                     this.execCmd('useCSS', false);
41429                                     this.execCmd('hilitecolor', color);
41430                                     this.execCmd('useCSS', true);
41431                                     this.deferFocus();
41432                                 }else{
41433                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
41434                                     this.deferFocus();
41435                                 }
41436                             }
41437                         },
41438                         clickEvent:'mousedown'
41439                     })
41440                 }
41441             );
41442         }
41443
41444         if(this.enableAlignments){
41445             items.push(
41446                 '-',
41447                 btn('justifyleft'),
41448                 btn('justifycenter'),
41449                 btn('justifyright')
41450             );
41451         }
41452
41453         if(!Ext.isSafari2){
41454             if(this.enableLinks){
41455                 items.push(
41456                     '-',
41457                     btn('createlink', false, this.createLink)
41458                 );
41459             }
41460
41461             if(this.enableLists){
41462                 items.push(
41463                     '-',
41464                     btn('insertorderedlist'),
41465                     btn('insertunorderedlist')
41466                 );
41467             }
41468             if(this.enableSourceEdit){
41469                 items.push(
41470                     '-',
41471                     btn('sourceedit', true, function(btn){
41472                         this.toggleSourceEdit(!this.sourceEditMode);
41473                     })
41474                 );
41475             }
41476         }
41477
41478         
41479         var tb = new Ext.Toolbar({
41480             renderTo: this.wrap.dom.firstChild,
41481             items: items
41482         });
41483
41484         if (fontSelectItem) {
41485             this.fontSelect = fontSelectItem.el;
41486
41487             this.mon(this.fontSelect, 'change', function(){
41488                 var font = this.fontSelect.dom.value;
41489                 this.relayCmd('fontname', font);
41490                 this.deferFocus();
41491             }, this);
41492         }
41493
41494         
41495         this.mon(tb.el, 'click', function(e){
41496             e.preventDefault();
41497         });
41498
41499         this.tb = tb;
41500         this.tb.doLayout();
41501     },
41502
41503     onDisable: function(){
41504         this.wrap.mask();
41505         Ext.form.HtmlEditor.superclass.onDisable.call(this);
41506     },
41507
41508     onEnable: function(){
41509         this.wrap.unmask();
41510         Ext.form.HtmlEditor.superclass.onEnable.call(this);
41511     },
41512
41513     setReadOnly: function(readOnly){
41514
41515         Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
41516         if(this.initialized){
41517             if(Ext.isIE){
41518                 this.getEditorBody().contentEditable = !readOnly;
41519             }else{
41520                 this.setDesignMode(!readOnly);
41521             }
41522             var bd = this.getEditorBody();
41523             if(bd){
41524                 bd.style.cursor = this.readOnly ? 'default' : 'text';
41525             }
41526             this.disableItems(readOnly);
41527         }
41528     },
41529
41530     
41531     getDocMarkup : function(){
41532         var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
41533         return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, h);
41534     },
41535
41536     
41537     getEditorBody : function(){
41538         var doc = this.getDoc();
41539         return doc.body || doc.documentElement;
41540     },
41541
41542     
41543     getDoc : function(){
41544         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
41545     },
41546
41547     
41548     getWin : function(){
41549         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
41550     },
41551
41552     
41553     onRender : function(ct, position){
41554         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
41555         this.el.dom.style.border = '0 none';
41556         this.el.dom.setAttribute('tabIndex', -1);
41557         this.el.addClass('x-hidden');
41558         if(Ext.isIE){ 
41559             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
41560         }
41561         this.wrap = this.el.wrap({
41562             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
41563         });
41564
41565         this.createToolbar(this);
41566
41567         this.disableItems(true);
41568
41569         this.tb.doLayout();
41570
41571         this.createIFrame();
41572
41573         if(!this.width){
41574             var sz = this.el.getSize();
41575             this.setSize(sz.width, this.height || sz.height);
41576         }
41577         this.resizeEl = this.positionEl = this.wrap;
41578     },
41579
41580     createIFrame: function(){
41581         var iframe = document.createElement('iframe');
41582         iframe.name = Ext.id();
41583         iframe.frameBorder = '0';
41584         iframe.style.overflow = 'auto';
41585
41586         this.wrap.dom.appendChild(iframe);
41587         this.iframe = iframe;
41588
41589         this.monitorTask = Ext.TaskMgr.start({
41590             run: this.checkDesignMode,
41591             scope: this,
41592             interval:100
41593         });
41594     },
41595
41596     initFrame : function(){
41597         Ext.TaskMgr.stop(this.monitorTask);
41598         var doc = this.getDoc();
41599         this.win = this.getWin();
41600
41601         doc.open();
41602         doc.write(this.getDocMarkup());
41603         doc.close();
41604
41605         var task = { 
41606             run : function(){
41607                 var doc = this.getDoc();
41608                 if(doc.body || doc.readyState == 'complete'){
41609                     Ext.TaskMgr.stop(task);
41610                     this.setDesignMode(true);
41611                     this.initEditor.defer(10, this);
41612                 }
41613             },
41614             interval : 10,
41615             duration:10000,
41616             scope: this
41617         };
41618         Ext.TaskMgr.start(task);
41619     },
41620
41621
41622     checkDesignMode : function(){
41623         if(this.wrap && this.wrap.dom.offsetWidth){
41624             var doc = this.getDoc();
41625             if(!doc){
41626                 return;
41627             }
41628             if(!doc.editorInitialized || this.getDesignMode() != 'on'){
41629                 this.initFrame();
41630             }
41631         }
41632     },
41633
41634     
41635     setDesignMode : function(mode){
41636         var doc ;
41637         if(doc = this.getDoc()){
41638             if(this.readOnly){
41639                 mode = false;
41640             }
41641             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
41642         }
41643
41644     },
41645
41646     
41647     getDesignMode : function(){
41648         var doc = this.getDoc();
41649         if(!doc){ return ''; }
41650         return String(doc.designMode).toLowerCase();
41651
41652     },
41653
41654     disableItems: function(disabled){
41655         if(this.fontSelect){
41656             this.fontSelect.dom.disabled = disabled;
41657         }
41658         this.tb.items.each(function(item){
41659             if(item.getItemId() != 'sourceedit'){
41660                 item.setDisabled(disabled);
41661             }
41662         });
41663     },
41664
41665     
41666     onResize : function(w, h){
41667         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
41668         if(this.el && this.iframe){
41669             if(Ext.isNumber(w)){
41670                 var aw = w - this.wrap.getFrameWidth('lr');
41671                 this.el.setWidth(aw);
41672                 this.tb.setWidth(aw);
41673                 this.iframe.style.width = Math.max(aw, 0) + 'px';
41674             }
41675             if(Ext.isNumber(h)){
41676                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
41677                 this.el.setHeight(ah);
41678                 this.iframe.style.height = Math.max(ah, 0) + 'px';
41679                 var bd = this.getEditorBody();
41680                 if(bd){
41681                     bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
41682                 }
41683             }
41684         }
41685     },
41686
41687     
41688     toggleSourceEdit : function(sourceEditMode){
41689         var iframeHeight,
41690             elHeight,
41691             ls;
41692
41693         if (sourceEditMode === undefined) {
41694             sourceEditMode = !this.sourceEditMode;
41695         }
41696         this.sourceEditMode = sourceEditMode === true;
41697         var btn = this.tb.getComponent('sourceedit');
41698
41699         if (btn.pressed !== this.sourceEditMode) {
41700             btn.toggle(this.sourceEditMode);
41701             if (!btn.xtbHidden) {
41702                 return;
41703             }
41704         }
41705         if (this.sourceEditMode) {
41706             
41707             ls = this.getSize();
41708
41709             iframeHeight = Ext.get(this.iframe).getHeight();
41710
41711             this.disableItems(true);
41712             this.syncValue();
41713             this.iframe.className = 'x-hidden';
41714             this.el.removeClass('x-hidden');
41715             this.el.dom.removeAttribute('tabIndex');
41716             this.el.focus();
41717             this.el.dom.style.height = iframeHeight + 'px';
41718         }
41719         else {
41720             elHeight = parseInt(this.el.dom.style.height, 10);
41721             if (this.initialized) {
41722                 this.disableItems(this.readOnly);
41723             }
41724             this.pushValue();
41725             this.iframe.className = '';
41726             this.el.addClass('x-hidden');
41727             this.el.dom.setAttribute('tabIndex', -1);
41728             this.deferFocus();
41729
41730             this.setSize(ls);
41731             this.iframe.style.height = elHeight + 'px';
41732         }
41733         this.fireEvent('editmodechange', this, this.sourceEditMode);
41734     },
41735
41736     
41737     createLink : function() {
41738         var url = prompt(this.createLinkText, this.defaultLinkValue);
41739         if(url && url != 'http:/'+'/'){
41740             this.relayCmd('createlink', url);
41741         }
41742     },
41743
41744     
41745     initEvents : function(){
41746         this.originalValue = this.getValue();
41747     },
41748
41749     
41750     markInvalid : Ext.emptyFn,
41751
41752     
41753     clearInvalid : Ext.emptyFn,
41754
41755     
41756     setValue : function(v){
41757         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
41758         this.pushValue();
41759         return this;
41760     },
41761
41762     
41763     cleanHtml: function(html) {
41764         html = String(html);
41765         if(Ext.isWebKit){ 
41766             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
41767         }
41768
41769         
41770         if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
41771             html = html.substring(1);
41772         }
41773         return html;
41774     },
41775
41776     
41777     syncValue : function(){
41778         if(this.initialized){
41779             var bd = this.getEditorBody();
41780             var html = bd.innerHTML;
41781             if(Ext.isWebKit){
41782                 var bs = bd.getAttribute('style'); 
41783                 var m = bs.match(/text-align:(.*?);/i);
41784                 if(m && m[1]){
41785                     html = '<div style="'+m[0]+'">' + html + '</div>';
41786                 }
41787             }
41788             html = this.cleanHtml(html);
41789             if(this.fireEvent('beforesync', this, html) !== false){
41790                 this.el.dom.value = html;
41791                 this.fireEvent('sync', this, html);
41792             }
41793         }
41794     },
41795
41796     
41797     getValue : function() {
41798         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
41799         return Ext.form.HtmlEditor.superclass.getValue.call(this);
41800     },
41801
41802     
41803     pushValue : function(){
41804         if(this.initialized){
41805             var v = this.el.dom.value;
41806             if(!this.activated && v.length < 1){
41807                 v = this.defaultValue;
41808             }
41809             if(this.fireEvent('beforepush', this, v) !== false){
41810                 this.getEditorBody().innerHTML = v;
41811                 if(Ext.isGecko){
41812                     
41813                     this.setDesignMode(false);  
41814                     this.setDesignMode(true);
41815                 }
41816                 this.fireEvent('push', this, v);
41817             }
41818
41819         }
41820     },
41821
41822     
41823     deferFocus : function(){
41824         this.focus.defer(10, this);
41825     },
41826
41827     
41828     focus : function(){
41829         if(this.win && !this.sourceEditMode){
41830             this.win.focus();
41831         }else{
41832             this.el.focus();
41833         }
41834     },
41835
41836     
41837     initEditor : function(){
41838         
41839         try{
41840             var dbody = this.getEditorBody(),
41841                 ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
41842                 doc,
41843                 fn;
41844
41845             ss['background-attachment'] = 'fixed'; 
41846             dbody.bgProperties = 'fixed'; 
41847
41848             Ext.DomHelper.applyStyles(dbody, ss);
41849
41850             doc = this.getDoc();
41851
41852             if(doc){
41853                 try{
41854                     Ext.EventManager.removeAll(doc);
41855                 }catch(e){}
41856             }
41857
41858             
41859             fn = this.onEditorEvent.createDelegate(this);
41860             Ext.EventManager.on(doc, {
41861                 mousedown: fn,
41862                 dblclick: fn,
41863                 click: fn,
41864                 keyup: fn,
41865                 buffer:100
41866             });
41867
41868             if(Ext.isGecko){
41869                 Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
41870             }
41871             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
41872                 Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
41873             }
41874             doc.editorInitialized = true;
41875             this.initialized = true;
41876             this.pushValue();
41877             this.setReadOnly(this.readOnly);
41878             this.fireEvent('initialize', this);
41879         }catch(e){}
41880     },
41881
41882     
41883     onDestroy : function(){
41884         if(this.monitorTask){
41885             Ext.TaskMgr.stop(this.monitorTask);
41886         }
41887         if(this.rendered){
41888             Ext.destroy(this.tb);
41889             var doc = this.getDoc();
41890             if(doc){
41891                 try{
41892                     Ext.EventManager.removeAll(doc);
41893                     for (var prop in doc){
41894                         delete doc[prop];
41895                     }
41896                 }catch(e){}
41897             }
41898             if(this.wrap){
41899                 this.wrap.dom.innerHTML = '';
41900                 this.wrap.remove();
41901             }
41902         }
41903
41904         if(this.el){
41905             this.el.removeAllListeners();
41906             this.el.remove();
41907         }
41908         this.purgeListeners();
41909     },
41910
41911     
41912     onFirstFocus : function(){
41913         this.activated = true;
41914         this.disableItems(this.readOnly);
41915         if(Ext.isGecko){ 
41916             this.win.focus();
41917             var s = this.win.getSelection();
41918             if(!s.focusNode || s.focusNode.nodeType != 3){
41919                 var r = s.getRangeAt(0);
41920                 r.selectNodeContents(this.getEditorBody());
41921                 r.collapse(true);
41922                 this.deferFocus();
41923             }
41924             try{
41925                 this.execCmd('useCSS', true);
41926                 this.execCmd('styleWithCSS', false);
41927             }catch(e){}
41928         }
41929         this.fireEvent('activate', this);
41930     },
41931
41932     
41933     adjustFont: function(btn){
41934         var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
41935             doc = this.getDoc(),
41936             v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
41937         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
41938             
41939             
41940             if(v <= 10){
41941                 v = 1 + adjust;
41942             }else if(v <= 13){
41943                 v = 2 + adjust;
41944             }else if(v <= 16){
41945                 v = 3 + adjust;
41946             }else if(v <= 18){
41947                 v = 4 + adjust;
41948             }else if(v <= 24){
41949                 v = 5 + adjust;
41950             }else {
41951                 v = 6 + adjust;
41952             }
41953             v = v.constrain(1, 6);
41954         }else{
41955             if(Ext.isSafari){ 
41956                 adjust *= 2;
41957             }
41958             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
41959         }
41960         this.execCmd('FontSize', v);
41961     },
41962
41963     
41964     onEditorEvent : function(e){
41965         this.updateToolbar();
41966     },
41967
41968
41969     
41970     updateToolbar: function(){
41971
41972         if(this.readOnly){
41973             return;
41974         }
41975
41976         if(!this.activated){
41977             this.onFirstFocus();
41978             return;
41979         }
41980
41981         var btns = this.tb.items.map,
41982             doc = this.getDoc();
41983
41984         if(this.enableFont && !Ext.isSafari2){
41985             var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
41986             if(name != this.fontSelect.dom.value){
41987                 this.fontSelect.dom.value = name;
41988             }
41989         }
41990         if(this.enableFormat){
41991             btns.bold.toggle(doc.queryCommandState('bold'));
41992             btns.italic.toggle(doc.queryCommandState('italic'));
41993             btns.underline.toggle(doc.queryCommandState('underline'));
41994         }
41995         if(this.enableAlignments){
41996             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
41997             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
41998             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
41999         }
42000         if(!Ext.isSafari2 && this.enableLists){
42001             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
42002             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
42003         }
42004
42005         Ext.menu.MenuMgr.hideAll();
42006
42007         this.syncValue();
42008     },
42009
42010     
42011     relayBtnCmd : function(btn){
42012         this.relayCmd(btn.getItemId());
42013     },
42014
42015     
42016     relayCmd : function(cmd, value){
42017         (function(){
42018             this.focus();
42019             this.execCmd(cmd, value);
42020             this.updateToolbar();
42021         }).defer(10, this);
42022     },
42023
42024     
42025     execCmd : function(cmd, value){
42026         var doc = this.getDoc();
42027         doc.execCommand(cmd, false, value === undefined ? null : value);
42028         this.syncValue();
42029     },
42030
42031     
42032     applyCommand : function(e){
42033         if(e.ctrlKey){
42034             var c = e.getCharCode(), cmd;
42035             if(c > 0){
42036                 c = String.fromCharCode(c);
42037                 switch(c){
42038                     case 'b':
42039                         cmd = 'bold';
42040                     break;
42041                     case 'i':
42042                         cmd = 'italic';
42043                     break;
42044                     case 'u':
42045                         cmd = 'underline';
42046                     break;
42047                 }
42048                 if(cmd){
42049                     this.win.focus();
42050                     this.execCmd(cmd);
42051                     this.deferFocus();
42052                     e.preventDefault();
42053                 }
42054             }
42055         }
42056     },
42057
42058     
42059     insertAtCursor : function(text){
42060         if(!this.activated){
42061             return;
42062         }
42063         if(Ext.isIE){
42064             this.win.focus();
42065             var doc = this.getDoc(),
42066                 r = doc.selection.createRange();
42067             if(r){
42068                 r.pasteHTML(text);
42069                 this.syncValue();
42070                 this.deferFocus();
42071             }
42072         }else{
42073             this.win.focus();
42074             this.execCmd('InsertHTML', text);
42075             this.deferFocus();
42076         }
42077     },
42078
42079     
42080     fixKeys : function(){ 
42081         if(Ext.isIE){
42082             return function(e){
42083                 var k = e.getKey(),
42084                     doc = this.getDoc(),
42085                         r;
42086                 if(k == e.TAB){
42087                     e.stopEvent();
42088                     r = doc.selection.createRange();
42089                     if(r){
42090                         r.collapse(true);
42091                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
42092                         this.deferFocus();
42093                     }
42094                 }else if(k == e.ENTER){
42095                     r = doc.selection.createRange();
42096                     if(r){
42097                         var target = r.parentElement();
42098                         if(!target || target.tagName.toLowerCase() != 'li'){
42099                             e.stopEvent();
42100                             r.pasteHTML('<br />');
42101                             r.collapse(false);
42102                             r.select();
42103                         }
42104                     }
42105                 }
42106             };
42107         }else if(Ext.isOpera){
42108             return function(e){
42109                 var k = e.getKey();
42110                 if(k == e.TAB){
42111                     e.stopEvent();
42112                     this.win.focus();
42113                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
42114                     this.deferFocus();
42115                 }
42116             };
42117         }else if(Ext.isWebKit){
42118             return function(e){
42119                 var k = e.getKey();
42120                 if(k == e.TAB){
42121                     e.stopEvent();
42122                     this.execCmd('InsertText','\t');
42123                     this.deferFocus();
42124                 }else if(k == e.ENTER){
42125                     e.stopEvent();
42126                     this.execCmd('InsertHtml','<br /><br />');
42127                     this.deferFocus();
42128                 }
42129              };
42130         }
42131     }(),
42132
42133     
42134     getToolbar : function(){
42135         return this.tb;
42136     },
42137
42138     
42139     buttonTips : {
42140         bold : {
42141             title: 'Bold (Ctrl+B)',
42142             text: 'Make the selected text bold.',
42143             cls: 'x-html-editor-tip'
42144         },
42145         italic : {
42146             title: 'Italic (Ctrl+I)',
42147             text: 'Make the selected text italic.',
42148             cls: 'x-html-editor-tip'
42149         },
42150         underline : {
42151             title: 'Underline (Ctrl+U)',
42152             text: 'Underline the selected text.',
42153             cls: 'x-html-editor-tip'
42154         },
42155         increasefontsize : {
42156             title: 'Grow Text',
42157             text: 'Increase the font size.',
42158             cls: 'x-html-editor-tip'
42159         },
42160         decreasefontsize : {
42161             title: 'Shrink Text',
42162             text: 'Decrease the font size.',
42163             cls: 'x-html-editor-tip'
42164         },
42165         backcolor : {
42166             title: 'Text Highlight Color',
42167             text: 'Change the background color of the selected text.',
42168             cls: 'x-html-editor-tip'
42169         },
42170         forecolor : {
42171             title: 'Font Color',
42172             text: 'Change the color of the selected text.',
42173             cls: 'x-html-editor-tip'
42174         },
42175         justifyleft : {
42176             title: 'Align Text Left',
42177             text: 'Align text to the left.',
42178             cls: 'x-html-editor-tip'
42179         },
42180         justifycenter : {
42181             title: 'Center Text',
42182             text: 'Center text in the editor.',
42183             cls: 'x-html-editor-tip'
42184         },
42185         justifyright : {
42186             title: 'Align Text Right',
42187             text: 'Align text to the right.',
42188             cls: 'x-html-editor-tip'
42189         },
42190         insertunorderedlist : {
42191             title: 'Bullet List',
42192             text: 'Start a bulleted list.',
42193             cls: 'x-html-editor-tip'
42194         },
42195         insertorderedlist : {
42196             title: 'Numbered List',
42197             text: 'Start a numbered list.',
42198             cls: 'x-html-editor-tip'
42199         },
42200         createlink : {
42201             title: 'Hyperlink',
42202             text: 'Make the selected text a hyperlink.',
42203             cls: 'x-html-editor-tip'
42204         },
42205         sourceedit : {
42206             title: 'Source Edit',
42207             text: 'Switch to source editing mode.',
42208             cls: 'x-html-editor-tip'
42209         }
42210     }
42211
42212     
42213     
42214     
42215     
42216     
42217     
42218     
42219     
42220     
42221     
42222     
42223     
42224     
42225     
42226     
42227     
42228     
42229     
42230     
42231     
42232     
42233     
42234     
42235     
42236     
42237     
42238     
42239     
42240     
42241     
42242     
42243     
42244     
42245     
42246 });
42247 Ext.reg('htmleditor', Ext.form.HtmlEditor);
42248
42249 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
42250     
42251     minValue : undefined,
42252     
42253     maxValue : undefined,
42254     
42255     minText : "The time in this field must be equal to or after {0}",
42256     
42257     maxText : "The time in this field must be equal to or before {0}",
42258     
42259     invalidText : "{0} is not a valid time",
42260     
42261     format : "g:i A",
42262     
42263     altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
42264     
42265     increment: 15,
42266
42267     
42268     mode: 'local',
42269     
42270     triggerAction: 'all',
42271     
42272     typeAhead: false,
42273
42274     
42275     
42276     
42277     initDate: '1/1/2008',
42278
42279     initDateFormat: 'j/n/Y',
42280
42281     
42282     initComponent : function(){
42283         if(Ext.isDefined(this.minValue)){
42284             this.setMinValue(this.minValue, true);
42285         }
42286         if(Ext.isDefined(this.maxValue)){
42287             this.setMaxValue(this.maxValue, true);
42288         }
42289         if(!this.store){
42290             this.generateStore(true);
42291         }
42292         Ext.form.TimeField.superclass.initComponent.call(this);
42293     },
42294
42295     
42296     setMinValue: function(value,  initial){
42297         this.setLimit(value, true, initial);
42298         return this;
42299     },
42300
42301     
42302     setMaxValue: function(value,  initial){
42303         this.setLimit(value, false, initial);
42304         return this;
42305     },
42306
42307     
42308     generateStore: function(initial){
42309         var min = this.minValue || new Date(this.initDate).clearTime(),
42310             max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
42311             times = [];
42312
42313         while(min <= max){
42314             times.push(min.dateFormat(this.format));
42315             min = min.add('mi', this.increment);
42316         }
42317         this.bindStore(times, initial);
42318     },
42319
42320     
42321     setLimit: function(value, isMin, initial){
42322         var d;
42323         if(Ext.isString(value)){
42324             d = this.parseDate(value);
42325         }else if(Ext.isDate(value)){
42326             d = value;
42327         }
42328         if(d){
42329             var val = new Date(this.initDate).clearTime();
42330             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
42331             this[isMin ? 'minValue' : 'maxValue'] = val;
42332             if(!initial){
42333                 this.generateStore();
42334             }
42335         }
42336     },
42337
42338     
42339     getValue : function(){
42340         var v = Ext.form.TimeField.superclass.getValue.call(this);
42341         return this.formatDate(this.parseDate(v)) || '';
42342     },
42343
42344     
42345     setValue : function(value){
42346         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
42347     },
42348
42349     
42350     validateValue : Ext.form.DateField.prototype.validateValue,
42351
42352     formatDate : Ext.form.DateField.prototype.formatDate,
42353
42354     parseDate: function(value) {
42355         if (!value || Ext.isDate(value)) {
42356             return value;
42357         }
42358
42359         var id = this.initDate + ' ',
42360             idf = this.initDateFormat + ' ',
42361             v = Date.parseDate(id + value, idf + this.format), 
42362             af = this.altFormats;
42363
42364         if (!v && af) {
42365             if (!this.altFormatsArray) {
42366                 this.altFormatsArray = af.split("|");
42367             }
42368             for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
42369                 v = Date.parseDate(id + value, idf + afa[i]);
42370             }
42371         }
42372
42373         return v;
42374     }
42375 });
42376 Ext.reg('timefield', Ext.form.TimeField);
42377 Ext.form.SliderField = Ext.extend(Ext.form.Field, {
42378     
42379     
42380     useTips : true,
42381     
42382     
42383     tipText : null,
42384     
42385     
42386     actionMode: 'wrap',
42387     
42388     
42389     initComponent : function() {
42390         var cfg = Ext.copyTo({
42391             id: this.id + '-slider'
42392         }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
42393         
42394         
42395         if (this.useTips) {
42396             var plug = this.tipText ? {getText: this.tipText} : {};
42397             cfg.plugins = [new Ext.slider.Tip(plug)];
42398         }
42399         this.slider = new Ext.Slider(cfg);
42400         Ext.form.SliderField.superclass.initComponent.call(this);
42401     },    
42402     
42403     
42404     onRender : function(ct, position){
42405         this.autoCreate = {
42406             id: this.id,
42407             name: this.name,
42408             type: 'hidden',
42409             tag: 'input'    
42410         };
42411         Ext.form.SliderField.superclass.onRender.call(this, ct, position);
42412         this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
42413         this.resizeEl = this.positionEl = this.wrap;
42414         this.slider.render(this.wrap);
42415     },
42416     
42417     
42418     onResize : function(w, h, aw, ah){
42419         Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
42420         this.slider.setSize(w, h);    
42421     },
42422     
42423     
42424     initEvents : function(){
42425         Ext.form.SliderField.superclass.initEvents.call(this);
42426         this.slider.on('change', this.onChange, this);   
42427     },
42428     
42429     
42430     onChange : function(slider, v){
42431         this.setValue(v, undefined, true);
42432     },
42433     
42434     
42435     onEnable : function(){
42436         Ext.form.SliderField.superclass.onEnable.call(this);
42437         this.slider.enable();
42438     },
42439     
42440     
42441     onDisable : function(){
42442         Ext.form.SliderField.superclass.onDisable.call(this);
42443         this.slider.disable();    
42444     },
42445     
42446     
42447     beforeDestroy : function(){
42448         Ext.destroy(this.slider);
42449         Ext.form.SliderField.superclass.beforeDestroy.call(this);
42450     },
42451     
42452     
42453     alignErrorIcon : function(){
42454         this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
42455     },
42456     
42457     
42458     setMinValue : function(v){
42459         this.slider.setMinValue(v);
42460         return this;    
42461     },
42462     
42463     
42464     setMaxValue : function(v){
42465         this.slider.setMaxValue(v);
42466         return this;    
42467     },
42468     
42469     
42470     setValue : function(v, animate,  silent){
42471         
42472         
42473         if(!silent){
42474             this.slider.setValue(v, animate);
42475         }
42476         return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
42477     },
42478     
42479     
42480     getValue : function(){
42481         return this.slider.getValue();    
42482     }
42483 });
42484
42485 Ext.reg('sliderfield', Ext.form.SliderField);
42486 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
42487     
42488     
42489     
42490
42491     
42492     onRender : function(ct, position){
42493         if(!this.el){
42494             this.el = document.createElement('label');
42495             this.el.id = this.getId();
42496             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
42497             if(this.forId){
42498                 this.el.setAttribute('for', this.forId);
42499             }
42500         }
42501         Ext.form.Label.superclass.onRender.call(this, ct, position);
42502     },
42503
42504     
42505     setText : function(t, encode){
42506         var e = encode === false;
42507         this[!e ? 'text' : 'html'] = t;
42508         delete this[e ? 'text' : 'html'];
42509         if(this.rendered){
42510             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
42511         }
42512         return this;
42513     }
42514 });
42515
42516 Ext.reg('label', Ext.form.Label);
42517 Ext.form.Action = function(form, options){
42518     this.form = form;
42519     this.options = options || {};
42520 };
42521
42522
42523 Ext.form.Action.CLIENT_INVALID = 'client';
42524
42525 Ext.form.Action.SERVER_INVALID = 'server';
42526
42527 Ext.form.Action.CONNECT_FAILURE = 'connect';
42528
42529 Ext.form.Action.LOAD_FAILURE = 'load';
42530
42531 Ext.form.Action.prototype = {
42532
42533
42534
42535
42536
42537
42538
42539
42540
42541
42542
42543
42544
42545
42546     type : 'default',
42547
42548  
42549  
42550
42551     
42552     run : function(options){
42553
42554     },
42555
42556     
42557     success : function(response){
42558
42559     },
42560
42561     
42562     handleResponse : function(response){
42563
42564     },
42565
42566     
42567     failure : function(response){
42568         this.response = response;
42569         this.failureType = Ext.form.Action.CONNECT_FAILURE;
42570         this.form.afterAction(this, false);
42571     },
42572
42573     
42574     
42575     
42576     processResponse : function(response){
42577         this.response = response;
42578         if(!response.responseText && !response.responseXML){
42579             return true;
42580         }
42581         this.result = this.handleResponse(response);
42582         return this.result;
42583     },
42584
42585     
42586     getUrl : function(appendParams){
42587         var url = this.options.url || this.form.url || this.form.el.dom.action;
42588         if(appendParams){
42589             var p = this.getParams();
42590             if(p){
42591                 url = Ext.urlAppend(url, p);
42592             }
42593         }
42594         return url;
42595     },
42596
42597     
42598     getMethod : function(){
42599         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
42600     },
42601
42602     
42603     getParams : function(){
42604         var bp = this.form.baseParams;
42605         var p = this.options.params;
42606         if(p){
42607             if(typeof p == "object"){
42608                 p = Ext.urlEncode(Ext.applyIf(p, bp));
42609             }else if(typeof p == 'string' && bp){
42610                 p += '&' + Ext.urlEncode(bp);
42611             }
42612         }else if(bp){
42613             p = Ext.urlEncode(bp);
42614         }
42615         return p;
42616     },
42617
42618     
42619     createCallback : function(opts){
42620         var opts = opts || {};
42621         return {
42622             success: this.success,
42623             failure: this.failure,
42624             scope: this,
42625             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
42626             upload: this.form.fileUpload ? this.success : undefined
42627         };
42628     }
42629 };
42630
42631
42632 Ext.form.Action.Submit = function(form, options){
42633     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
42634 };
42635
42636 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
42637     
42638     
42639     type : 'submit',
42640
42641     
42642     run : function(){
42643         var o = this.options,
42644             method = this.getMethod(),
42645             isGet = method == 'GET';
42646         if(o.clientValidation === false || this.form.isValid()){
42647             if (o.submitEmptyText === false) {
42648                 var fields = this.form.items,
42649                     emptyFields = [];
42650                 fields.each(function(f) {
42651                     if (f.el.getValue() == f.emptyText) {
42652                         emptyFields.push(f);
42653                         f.el.dom.value = "";
42654                     }
42655                 });
42656             }
42657             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
42658                 form:this.form.el.dom,
42659                 url:this.getUrl(isGet),
42660                 method: method,
42661                 headers: o.headers,
42662                 params:!isGet ? this.getParams() : null,
42663                 isUpload: this.form.fileUpload
42664             }));
42665             if (o.submitEmptyText === false) {
42666                 Ext.each(emptyFields, function(f) {
42667                     if (f.applyEmptyText) {
42668                         f.applyEmptyText();
42669                     }
42670                 });
42671             }
42672         }else if (o.clientValidation !== false){ 
42673             this.failureType = Ext.form.Action.CLIENT_INVALID;
42674             this.form.afterAction(this, false);
42675         }
42676     },
42677
42678     
42679     success : function(response){
42680         var result = this.processResponse(response);
42681         if(result === true || result.success){
42682             this.form.afterAction(this, true);
42683             return;
42684         }
42685         if(result.errors){
42686             this.form.markInvalid(result.errors);
42687         }
42688         this.failureType = Ext.form.Action.SERVER_INVALID;
42689         this.form.afterAction(this, false);
42690     },
42691
42692     
42693     handleResponse : function(response){
42694         if(this.form.errorReader){
42695             var rs = this.form.errorReader.read(response);
42696             var errors = [];
42697             if(rs.records){
42698                 for(var i = 0, len = rs.records.length; i < len; i++) {
42699                     var r = rs.records[i];
42700                     errors[i] = r.data;
42701                 }
42702             }
42703             if(errors.length < 1){
42704                 errors = null;
42705             }
42706             return {
42707                 success : rs.success,
42708                 errors : errors
42709             };
42710         }
42711         return Ext.decode(response.responseText);
42712     }
42713 });
42714
42715
42716
42717 Ext.form.Action.Load = function(form, options){
42718     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
42719     this.reader = this.form.reader;
42720 };
42721
42722 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
42723     
42724     type : 'load',
42725
42726     
42727     run : function(){
42728         Ext.Ajax.request(Ext.apply(
42729                 this.createCallback(this.options), {
42730                     method:this.getMethod(),
42731                     url:this.getUrl(false),
42732                     headers: this.options.headers,
42733                     params:this.getParams()
42734         }));
42735     },
42736
42737     
42738     success : function(response){
42739         var result = this.processResponse(response);
42740         if(result === true || !result.success || !result.data){
42741             this.failureType = Ext.form.Action.LOAD_FAILURE;
42742             this.form.afterAction(this, false);
42743             return;
42744         }
42745         this.form.clearInvalid();
42746         this.form.setValues(result.data);
42747         this.form.afterAction(this, true);
42748     },
42749
42750     
42751     handleResponse : function(response){
42752         if(this.form.reader){
42753             var rs = this.form.reader.read(response);
42754             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
42755             return {
42756                 success : rs.success,
42757                 data : data
42758             };
42759         }
42760         return Ext.decode(response.responseText);
42761     }
42762 });
42763
42764
42765
42766
42767 Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
42768     constructor: function(form, opts) {
42769         Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
42770     },
42771     type : 'directload',
42772
42773     run : function(){
42774         var args = this.getParams();
42775         args.push(this.success, this);
42776         this.form.api.load.apply(window, args);
42777     },
42778
42779     getParams : function() {
42780         var buf = [], o = {};
42781         var bp = this.form.baseParams;
42782         var p = this.options.params;
42783         Ext.apply(o, p, bp);
42784         var paramOrder = this.form.paramOrder;
42785         if(paramOrder){
42786             for(var i = 0, len = paramOrder.length; i < len; i++){
42787                 buf.push(o[paramOrder[i]]);
42788             }
42789         }else if(this.form.paramsAsHash){
42790             buf.push(o);
42791         }
42792         return buf;
42793     },
42794     
42795     
42796     
42797     processResponse : function(result) {
42798         this.result = result;
42799         return result;
42800     },
42801
42802     success : function(response, trans){
42803         if(trans.type == Ext.Direct.exceptions.SERVER){
42804             response = {};
42805         }
42806         Ext.form.Action.DirectLoad.superclass.success.call(this, response);
42807     }
42808 });
42809
42810
42811 Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
42812     constructor : function(form, opts) {
42813         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
42814     },
42815     type : 'directsubmit',
42816     
42817     run : function(){
42818         var o = this.options;
42819         if(o.clientValidation === false || this.form.isValid()){
42820             
42821             
42822             this.success.params = this.getParams();
42823             this.form.api.submit(this.form.el.dom, this.success, this);
42824         }else if (o.clientValidation !== false){ 
42825             this.failureType = Ext.form.Action.CLIENT_INVALID;
42826             this.form.afterAction(this, false);
42827         }
42828     },
42829
42830     getParams : function() {
42831         var o = {};
42832         var bp = this.form.baseParams;
42833         var p = this.options.params;
42834         Ext.apply(o, p, bp);
42835         return o;
42836     },
42837     
42838     
42839     
42840     processResponse : function(result) {
42841         this.result = result;
42842         return result;
42843     },
42844
42845     success : function(response, trans){
42846         if(trans.type == Ext.Direct.exceptions.SERVER){
42847             response = {};
42848         }
42849         Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
42850     }
42851 });
42852
42853 Ext.form.Action.ACTION_TYPES = {
42854     'load' : Ext.form.Action.Load,
42855     'submit' : Ext.form.Action.Submit,
42856     'directload' : Ext.form.Action.DirectLoad,
42857     'directsubmit' : Ext.form.Action.DirectSubmit
42858 };
42859
42860 Ext.form.VTypes = function(){
42861     
42862     var alpha = /^[a-zA-Z_]+$/,
42863         alphanum = /^[a-zA-Z0-9_]+$/,
42864         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
42865         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
42866
42867     
42868     return {
42869         
42870         'email' : function(v){
42871             return email.test(v);
42872         },
42873         
42874         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
42875         
42876         'emailMask' : /[a-z0-9_\.\-@\+]/i,
42877
42878         
42879         'url' : function(v){
42880             return url.test(v);
42881         },
42882         
42883         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
42884
42885         
42886         'alpha' : function(v){
42887             return alpha.test(v);
42888         },
42889         
42890         'alphaText' : 'This field should only contain letters and _',
42891         
42892         'alphaMask' : /[a-z_]/i,
42893
42894         
42895         'alphanum' : function(v){
42896             return alphanum.test(v);
42897         },
42898         
42899         'alphanumText' : 'This field should only contain letters, numbers and _',
42900         
42901         'alphanumMask' : /[a-z0-9_]/i
42902     };
42903 }();
42904
42905 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
42906     
42907     autoExpandColumn : false,
42908     
42909     autoExpandMax : 1000,
42910     
42911     autoExpandMin : 50,
42912     
42913     columnLines : false,
42914     
42915     
42916     
42917     
42918     
42919     ddText : '{0} selected row{1}',
42920     
42921     deferRowRender : true,
42922     
42923     
42924     
42925     enableColumnHide : true,
42926     
42927     enableColumnMove : true,
42928     
42929     enableDragDrop : false,
42930     
42931     enableHdMenu : true,
42932     
42933     
42934     loadMask : false,
42935     
42936     
42937     minColumnWidth : 25,
42938     
42939     
42940     
42941     
42942     stripeRows : false,
42943     
42944     trackMouseOver : true,
42945     
42946     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
42947     
42948     view : null,
42949
42950     
42951     bubbleEvents: [],
42952
42953     
42954
42955     
42956     rendered : false,
42957     
42958     viewReady : false,
42959
42960     
42961     initComponent : function(){
42962         Ext.grid.GridPanel.superclass.initComponent.call(this);
42963
42964         if(this.columnLines){
42965             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
42966         }
42967         
42968         
42969         this.autoScroll = false;
42970         this.autoWidth = false;
42971
42972         if(Ext.isArray(this.columns)){
42973             this.colModel = new Ext.grid.ColumnModel(this.columns);
42974             delete this.columns;
42975         }
42976
42977         
42978         if(this.ds){
42979             this.store = this.ds;
42980             delete this.ds;
42981         }
42982         if(this.cm){
42983             this.colModel = this.cm;
42984             delete this.cm;
42985         }
42986         if(this.sm){
42987             this.selModel = this.sm;
42988             delete this.sm;
42989         }
42990         this.store = Ext.StoreMgr.lookup(this.store);
42991
42992         this.addEvents(
42993             
42994             
42995             'click',
42996             
42997             'dblclick',
42998             
42999             'contextmenu',
43000             
43001             'mousedown',
43002             
43003             'mouseup',
43004             
43005             'mouseover',
43006             
43007             'mouseout',
43008             
43009             'keypress',
43010             
43011             'keydown',
43012
43013             
43014             
43015             'cellmousedown',
43016             
43017             'rowmousedown',
43018             
43019             'headermousedown',
43020
43021             
43022             'groupmousedown',
43023
43024             
43025             'rowbodymousedown',
43026
43027             
43028             'containermousedown',
43029
43030             
43031             'cellclick',
43032             
43033             'celldblclick',
43034             
43035             'rowclick',
43036             
43037             'rowdblclick',
43038             
43039             'headerclick',
43040             
43041             'headerdblclick',
43042             
43043             'groupclick',
43044             
43045             'groupdblclick',
43046             
43047             'containerclick',
43048             
43049             'containerdblclick',
43050
43051             
43052             'rowbodyclick',
43053             
43054             'rowbodydblclick',
43055
43056             
43057             'rowcontextmenu',
43058             
43059             'cellcontextmenu',
43060             
43061             'headercontextmenu',
43062             
43063             'groupcontextmenu',
43064             
43065             'containercontextmenu',
43066             
43067             'rowbodycontextmenu',
43068             
43069             'bodyscroll',
43070             
43071             'columnresize',
43072             
43073             'columnmove',
43074             
43075             'sortchange',
43076             
43077             'groupchange',
43078             
43079             'reconfigure',
43080             
43081             'viewready'
43082         );
43083     },
43084
43085     
43086     onRender : function(ct, position){
43087         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
43088
43089         var c = this.getGridEl();
43090
43091         this.el.addClass('x-grid-panel');
43092
43093         this.mon(c, {
43094             scope: this,
43095             mousedown: this.onMouseDown,
43096             click: this.onClick,
43097             dblclick: this.onDblClick,
43098             contextmenu: this.onContextMenu
43099         });
43100
43101         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
43102
43103         var view = this.getView();
43104         view.init(this);
43105         view.render();
43106         this.getSelectionModel().init(this);
43107     },
43108
43109     
43110     initEvents : function(){
43111         Ext.grid.GridPanel.superclass.initEvents.call(this);
43112
43113         if(this.loadMask){
43114             this.loadMask = new Ext.LoadMask(this.bwrap,
43115                     Ext.apply({store:this.store}, this.loadMask));
43116         }
43117     },
43118
43119     initStateEvents : function(){
43120         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
43121         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
43122     },
43123
43124     applyState : function(state){
43125         var cm = this.colModel,
43126             cs = state.columns,
43127             store = this.store,
43128             s,
43129             c,
43130             oldIndex;
43131
43132         if(cs){
43133             for(var i = 0, len = cs.length; i < len; i++){
43134                 s = cs[i];
43135                 c = cm.getColumnById(s.id);
43136                 if(c){
43137                     c.hidden = s.hidden;
43138                     c.width = s.width;
43139                     oldIndex = cm.getIndexById(s.id);
43140                     if(oldIndex != i){
43141                         cm.moveColumn(oldIndex, i);
43142                     }
43143                 }
43144             }
43145         }
43146         if(store){
43147             s = state.sort;
43148             if(s){
43149                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
43150             }
43151             s = state.group;
43152             if(store.groupBy){
43153                 if(s){
43154                     store.groupBy(s);
43155                 }else{
43156                     store.clearGrouping();
43157                 }
43158             }
43159
43160         }
43161         var o = Ext.apply({}, state);
43162         delete o.columns;
43163         delete o.sort;
43164         Ext.grid.GridPanel.superclass.applyState.call(this, o);
43165     },
43166
43167     getState : function(){
43168         var o = {columns: []},
43169             store = this.store,
43170             ss,
43171             gs;
43172
43173         for(var i = 0, c; (c = this.colModel.config[i]); i++){
43174             o.columns[i] = {
43175                 id: c.id,
43176                 width: c.width
43177             };
43178             if(c.hidden){
43179                 o.columns[i].hidden = true;
43180             }
43181         }
43182         if(store){
43183             ss = store.getSortState();
43184             if(ss){
43185                 o.sort = ss;
43186             }
43187             if(store.getGroupState){
43188                 gs = store.getGroupState();
43189                 if(gs){
43190                     o.group = gs;
43191                 }
43192             }
43193         }
43194         return o;
43195     },
43196
43197     
43198     afterRender : function(){
43199         Ext.grid.GridPanel.superclass.afterRender.call(this);
43200         var v = this.view;
43201         this.on('bodyresize', v.layout, v);
43202         v.layout();
43203         if(this.deferRowRender){
43204             if (!this.deferRowRenderTask){
43205                 this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
43206             }
43207             this.deferRowRenderTask.delay(10);
43208         }else{
43209             v.afterRender();
43210         }
43211         this.viewReady = true;
43212     },
43213
43214     
43215     reconfigure : function(store, colModel){
43216         var rendered = this.rendered;
43217         if(rendered){
43218             if(this.loadMask){
43219                 this.loadMask.destroy();
43220                 this.loadMask = new Ext.LoadMask(this.bwrap,
43221                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
43222             }
43223         }
43224         if(this.view){
43225             this.view.initData(store, colModel);
43226         }
43227         this.store = store;
43228         this.colModel = colModel;
43229         if(rendered){
43230             this.view.refresh(true);
43231         }
43232         this.fireEvent('reconfigure', this, store, colModel);
43233     },
43234
43235     
43236     onDestroy : function(){
43237         if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
43238             this.deferRowRenderTask.cancel();
43239         }
43240         if(this.rendered){
43241             Ext.destroy(this.view, this.loadMask);
43242         }else if(this.store && this.store.autoDestroy){
43243             this.store.destroy();
43244         }
43245         Ext.destroy(this.colModel, this.selModel);
43246         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
43247         Ext.grid.GridPanel.superclass.onDestroy.call(this);
43248     },
43249
43250     
43251     processEvent : function(name, e){
43252         this.view.processEvent(name, e);
43253     },
43254
43255     
43256     onClick : function(e){
43257         this.processEvent('click', e);
43258     },
43259
43260     
43261     onMouseDown : function(e){
43262         this.processEvent('mousedown', e);
43263     },
43264
43265     
43266     onContextMenu : function(e, t){
43267         this.processEvent('contextmenu', e);
43268     },
43269
43270     
43271     onDblClick : function(e){
43272         this.processEvent('dblclick', e);
43273     },
43274
43275     
43276     walkCells : function(row, col, step, fn, scope){
43277         var cm    = this.colModel,
43278             clen  = cm.getColumnCount(),
43279             ds    = this.store,
43280             rlen  = ds.getCount(),
43281             first = true;
43282
43283         if(step < 0){
43284             if(col < 0){
43285                 row--;
43286                 first = false;
43287             }
43288             while(row >= 0){
43289                 if(!first){
43290                     col = clen-1;
43291                 }
43292                 first = false;
43293                 while(col >= 0){
43294                     if(fn.call(scope || this, row, col, cm) === true){
43295                         return [row, col];
43296                     }
43297                     col--;
43298                 }
43299                 row--;
43300             }
43301         } else {
43302             if(col >= clen){
43303                 row++;
43304                 first = false;
43305             }
43306             while(row < rlen){
43307                 if(!first){
43308                     col = 0;
43309                 }
43310                 first = false;
43311                 while(col < clen){
43312                     if(fn.call(scope || this, row, col, cm) === true){
43313                         return [row, col];
43314                     }
43315                     col++;
43316                 }
43317                 row++;
43318             }
43319         }
43320         return null;
43321     },
43322
43323     
43324     getGridEl : function(){
43325         return this.body;
43326     },
43327
43328     
43329     stopEditing : Ext.emptyFn,
43330
43331     
43332     getSelectionModel : function(){
43333         if(!this.selModel){
43334             this.selModel = new Ext.grid.RowSelectionModel(
43335                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
43336         }
43337         return this.selModel;
43338     },
43339
43340     
43341     getStore : function(){
43342         return this.store;
43343     },
43344
43345     
43346     getColumnModel : function(){
43347         return this.colModel;
43348     },
43349
43350     
43351     getView : function(){
43352         if(!this.view){
43353             this.view = new Ext.grid.GridView(this.viewConfig);
43354         }
43355         return this.view;
43356     },
43357     
43358     getDragDropText : function(){
43359         var count = this.selModel.getCount();
43360         return String.format(this.ddText, count, count == 1 ? '' : 's');
43361     }
43362
43363     
43364     
43365     
43366     
43367     
43368     
43369     
43370     
43371     
43372     
43373     
43374     
43375     
43376     
43377     
43378     
43379     
43380     
43381     
43382     
43383     
43384     
43385     
43386     
43387     
43388     
43389     
43390     
43391     
43392     
43393     
43394
43395
43396
43397     
43398     
43399     
43400     
43401     
43402     
43403     
43404     
43405     
43406     
43407     
43408     
43409     
43410     
43411     
43412     
43413 });
43414 Ext.reg('grid', Ext.grid.GridPanel);
43415 Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
43416     
43417
43418     
43419
43420     
43421
43422     
43423
43424     
43425
43426     
43427     deferEmptyText : true,
43428
43429     
43430     scrollOffset : undefined,
43431
43432     
43433     autoFill : false,
43434
43435     
43436     forceFit : false,
43437
43438     
43439     sortClasses : ['sort-asc', 'sort-desc'],
43440
43441     
43442     sortAscText : 'Sort Ascending',
43443
43444     
43445     sortDescText : 'Sort Descending',
43446
43447     
43448     columnsText : 'Columns',
43449
43450     
43451     selectedRowClass : 'x-grid3-row-selected',
43452
43453     
43454     borderWidth : 2,
43455     tdClass : 'x-grid3-cell',
43456     hdCls : 'x-grid3-hd',
43457     markDirty : true,
43458
43459     
43460     cellSelectorDepth : 4,
43461     
43462     rowSelectorDepth : 10,
43463
43464     
43465     rowBodySelectorDepth : 10,
43466
43467     
43468     cellSelector : 'td.x-grid3-cell',
43469     
43470     rowSelector : 'div.x-grid3-row',
43471
43472     
43473     rowBodySelector : 'div.x-grid3-row-body',
43474
43475     
43476     firstRowCls: 'x-grid3-row-first',
43477     lastRowCls: 'x-grid3-row-last',
43478     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
43479
43480     constructor : function(config){
43481         Ext.apply(this, config);
43482         
43483         this.addEvents(
43484             
43485             'beforerowremoved',
43486             
43487             'beforerowsinserted',
43488             
43489             'beforerefresh',
43490             
43491             'rowremoved',
43492             
43493             'rowsinserted',
43494             
43495             'rowupdated',
43496             
43497             'refresh'
43498         );
43499         Ext.grid.GridView.superclass.constructor.call(this);
43500     },
43501
43502     
43503
43504     
43505     initTemplates : function(){
43506         var ts = this.templates || {};
43507         if(!ts.master){
43508             ts.master = new Ext.Template(
43509                 '<div class="x-grid3" hidefocus="true">',
43510                     '<div class="x-grid3-viewport">',
43511                         '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
43512                         '<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
43513                     '</div>',
43514                     '<div class="x-grid3-resize-marker">&#160;</div>',
43515                     '<div class="x-grid3-resize-proxy">&#160;</div>',
43516                 '</div>'
43517             );
43518         }
43519
43520         if(!ts.header){
43521             ts.header = new Ext.Template(
43522                 '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
43523                 '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
43524                 '</table>'
43525             );
43526         }
43527
43528         if(!ts.hcell){
43529             ts.hcell = new Ext.Template(
43530                 '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
43531                 '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
43532                 '</div></td>'
43533             );
43534         }
43535
43536         if(!ts.body){
43537             ts.body = new Ext.Template('{rows}');
43538         }
43539
43540         if(!ts.row){
43541             ts.row = new Ext.Template(
43542                 '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
43543                 '<tbody><tr>{cells}</tr>',
43544                 (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
43545                 '</tbody></table></div>'
43546             );
43547         }
43548
43549         if(!ts.cell){
43550             ts.cell = new Ext.Template(
43551                     '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
43552                     '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
43553                     '</td>'
43554                     );
43555         }
43556
43557         for(var k in ts){
43558             var t = ts[k];
43559             if(t && Ext.isFunction(t.compile) && !t.compiled){
43560                 t.disableFormats = true;
43561                 t.compile();
43562             }
43563         }
43564
43565         this.templates = ts;
43566         this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
43567     },
43568
43569     
43570     fly : function(el){
43571         if(!this._flyweight){
43572             this._flyweight = new Ext.Element.Flyweight(document.body);
43573         }
43574         this._flyweight.dom = el;
43575         return this._flyweight;
43576     },
43577
43578     
43579     getEditorParent : function(){
43580         return this.scroller.dom;
43581     },
43582
43583     
43584     initElements : function(){
43585         var E = Ext.Element;
43586
43587         var el = this.grid.getGridEl().dom.firstChild;
43588         var cs = el.childNodes;
43589
43590         this.el = new E(el);
43591
43592         this.mainWrap = new E(cs[0]);
43593         this.mainHd = new E(this.mainWrap.dom.firstChild);
43594
43595         if(this.grid.hideHeaders){
43596             this.mainHd.setDisplayed(false);
43597         }
43598
43599         this.innerHd = this.mainHd.dom.firstChild;
43600         this.scroller = new E(this.mainWrap.dom.childNodes[1]);
43601         if(this.forceFit){
43602             this.scroller.setStyle('overflow-x', 'hidden');
43603         }
43604         
43605         this.mainBody = new E(this.scroller.dom.firstChild);
43606
43607         this.focusEl = new E(this.scroller.dom.childNodes[1]);
43608         this.focusEl.swallowEvent('click', true);
43609
43610         this.resizeMarker = new E(cs[1]);
43611         this.resizeProxy = new E(cs[2]);
43612     },
43613
43614     
43615     getRows : function(){
43616         return this.hasRows() ? this.mainBody.dom.childNodes : [];
43617     },
43618
43619     
43620
43621     
43622     findCell : function(el){
43623         if(!el){
43624             return false;
43625         }
43626         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
43627     },
43628
43629     
43630     findCellIndex : function(el, requiredCls){
43631         var cell = this.findCell(el);
43632         if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
43633             return this.getCellIndex(cell);
43634         }
43635         return false;
43636     },
43637
43638     
43639     getCellIndex : function(el){
43640         if(el){
43641             var m = el.className.match(this.colRe);
43642             if(m && m[1]){
43643                 return this.cm.getIndexById(m[1]);
43644             }
43645         }
43646         return false;
43647     },
43648
43649     
43650     findHeaderCell : function(el){
43651         var cell = this.findCell(el);
43652         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
43653     },
43654
43655     
43656     findHeaderIndex : function(el){
43657         return this.findCellIndex(el, this.hdCls);
43658     },
43659
43660     
43661     findRow : function(el){
43662         if(!el){
43663             return false;
43664         }
43665         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
43666     },
43667
43668     
43669     findRowIndex : function(el){
43670         var r = this.findRow(el);
43671         return r ? r.rowIndex : false;
43672     },
43673
43674     
43675     findRowBody : function(el){
43676         if(!el){
43677             return false;
43678         }
43679         return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
43680     },
43681
43682     
43683
43684     
43685     getRow : function(row){
43686         return this.getRows()[row];
43687     },
43688
43689     
43690     getCell : function(row, col){
43691         return this.getRow(row).getElementsByTagName('td')[col];
43692     },
43693
43694     
43695     getHeaderCell : function(index){
43696         return this.mainHd.dom.getElementsByTagName('td')[index];
43697     },
43698
43699     
43700
43701     
43702     addRowClass : function(row, cls){
43703         var r = this.getRow(row);
43704         if(r){
43705             this.fly(r).addClass(cls);
43706         }
43707     },
43708
43709     
43710     removeRowClass : function(row, cls){
43711         var r = this.getRow(row);
43712         if(r){
43713             this.fly(r).removeClass(cls);
43714         }
43715     },
43716
43717     
43718     removeRow : function(row){
43719         Ext.removeNode(this.getRow(row));
43720         this.syncFocusEl(row);
43721     },
43722
43723     
43724     removeRows : function(firstRow, lastRow){
43725         var bd = this.mainBody.dom;
43726         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
43727             Ext.removeNode(bd.childNodes[firstRow]);
43728         }
43729         this.syncFocusEl(firstRow);
43730     },
43731
43732     
43733
43734     
43735     getScrollState : function(){
43736         var sb = this.scroller.dom;
43737         return {left: sb.scrollLeft, top: sb.scrollTop};
43738     },
43739
43740     
43741     restoreScroll : function(state){
43742         var sb = this.scroller.dom;
43743         sb.scrollLeft = state.left;
43744         sb.scrollTop = state.top;
43745     },
43746
43747     
43748     scrollToTop : function(){
43749         this.scroller.dom.scrollTop = 0;
43750         this.scroller.dom.scrollLeft = 0;
43751     },
43752
43753     
43754     syncScroll : function(){
43755         this.syncHeaderScroll();
43756         var mb = this.scroller.dom;
43757         this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
43758     },
43759
43760     
43761     syncHeaderScroll : function(){
43762         var mb = this.scroller.dom;
43763         this.innerHd.scrollLeft = mb.scrollLeft;
43764         this.innerHd.scrollLeft = mb.scrollLeft; 
43765     },
43766
43767     
43768     updateSortIcon : function(col, dir){
43769         var sc = this.sortClasses;
43770         var hds = this.mainHd.select('td').removeClass(sc);
43771         hds.item(col).addClass(sc[dir == 'DESC' ? 1 : 0]);
43772     },
43773
43774     
43775     updateAllColumnWidths : function(){
43776         var tw   = this.getTotalWidth(),
43777             clen = this.cm.getColumnCount(),
43778             ws   = [],
43779             len,
43780             i;
43781
43782         for(i = 0; i < clen; i++){
43783             ws[i] = this.getColumnWidth(i);
43784         }
43785
43786         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43787         this.innerHd.firstChild.firstChild.style.width = tw;
43788         this.mainBody.dom.style.width = tw;
43789
43790         for(i = 0; i < clen; i++){
43791             var hd = this.getHeaderCell(i);
43792             hd.style.width = ws[i];
43793         }
43794
43795         var ns = this.getRows(), row, trow;
43796         for(i = 0, len = ns.length; i < len; i++){
43797             row = ns[i];
43798             row.style.width = tw;
43799             if(row.firstChild){
43800                 row.firstChild.style.width = tw;
43801                 trow = row.firstChild.rows[0];
43802                 for (var j = 0; j < clen; j++) {
43803                    trow.childNodes[j].style.width = ws[j];
43804                 }
43805             }
43806         }
43807
43808         this.onAllColumnWidthsUpdated(ws, tw);
43809     },
43810
43811     
43812     updateColumnWidth : function(col, width){
43813         var w = this.getColumnWidth(col);
43814         var tw = this.getTotalWidth();
43815         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43816         this.innerHd.firstChild.firstChild.style.width = tw;
43817         this.mainBody.dom.style.width = tw;
43818         var hd = this.getHeaderCell(col);
43819         hd.style.width = w;
43820
43821         var ns = this.getRows(), row;
43822         for(var i = 0, len = ns.length; i < len; i++){
43823             row = ns[i];
43824             row.style.width = tw;
43825             if(row.firstChild){
43826                 row.firstChild.style.width = tw;
43827                 row.firstChild.rows[0].childNodes[col].style.width = w;
43828             }
43829         }
43830
43831         this.onColumnWidthUpdated(col, w, tw);
43832     },
43833
43834     
43835     updateColumnHidden : function(col, hidden){
43836         var tw = this.getTotalWidth();
43837         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43838         this.innerHd.firstChild.firstChild.style.width = tw;
43839         this.mainBody.dom.style.width = tw;
43840         var display = hidden ? 'none' : '';
43841
43842         var hd = this.getHeaderCell(col);
43843         hd.style.display = display;
43844
43845         var ns = this.getRows(), row;
43846         for(var i = 0, len = ns.length; i < len; i++){
43847             row = ns[i];
43848             row.style.width = tw;
43849             if(row.firstChild){
43850                 row.firstChild.style.width = tw;
43851                 row.firstChild.rows[0].childNodes[col].style.display = display;
43852             }
43853         }
43854
43855         this.onColumnHiddenUpdated(col, hidden, tw);
43856         delete this.lastViewWidth; 
43857         this.layout();
43858     },
43859
43860     
43861     doRender : function(columns, records, store, startRow, colCount, stripe) {
43862         var templates    = this.templates,
43863             cellTemplate = templates.cell,
43864             rowTemplate  = templates.row,
43865             last         = colCount - 1;
43866
43867         var tstyle = 'width:' + this.getTotalWidth() + ';';
43868
43869         
43870         var rowBuffer = [],
43871             colBuffer = [],
43872             rowParams = {tstyle: tstyle},
43873             meta      = {},
43874             column,
43875             record;
43876
43877         
43878         for (var j = 0, len = records.length; j < len; j++) {
43879             record    = records[j];
43880             colBuffer = [];
43881
43882             var rowIndex = j + startRow;
43883
43884             
43885             for (var i = 0; i < colCount; i++) {
43886                 column = columns[i];
43887
43888                 meta.id    = column.id;
43889                 meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
43890                 meta.attr  = meta.cellAttr = '';
43891                 meta.style = column.style;
43892                 meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
43893
43894                 if (Ext.isEmpty(meta.value)) {
43895                     meta.value = '&#160;';
43896                 }
43897
43898                 if (this.markDirty && record.dirty && Ext.isDefined(record.modified[column.name])) {
43899                     meta.css += ' x-grid3-dirty-cell';
43900                 }
43901
43902                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
43903             }
43904
43905             
43906             var alt = [];
43907
43908             if (stripe && ((rowIndex + 1) % 2 === 0)) {
43909                 alt[0] = 'x-grid3-row-alt';
43910             }
43911
43912             if (record.dirty) {
43913                 alt[1] = ' x-grid3-dirty-row';
43914             }
43915
43916             rowParams.cols = colCount;
43917
43918             if (this.getRowClass) {
43919                 alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
43920             }
43921
43922             rowParams.alt   = alt.join(' ');
43923             rowParams.cells = colBuffer.join('');
43924
43925             rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
43926         }
43927
43928         return rowBuffer.join('');
43929     },
43930
43931     
43932     processRows : function(startRow, skipStripe) {
43933         if (!this.ds || this.ds.getCount() < 1) {
43934             return;
43935         }
43936
43937         var rows = this.getRows(),
43938             len  = rows.length,
43939             i, r;
43940
43941         skipStripe = skipStripe || !this.grid.stripeRows;
43942         startRow   = startRow   || 0;
43943
43944         for (i = 0; i<len; i++) {
43945             r = rows[i];
43946             if (r) {
43947                 r.rowIndex = i;
43948                 if (!skipStripe) {
43949                     r.className = r.className.replace(this.rowClsRe, ' ');
43950                     if ((i + 1) % 2 === 0){
43951                         r.className += ' x-grid3-row-alt';
43952                     }
43953                 }
43954             }
43955         }
43956
43957         
43958         if (startRow === 0) {
43959             Ext.fly(rows[0]).addClass(this.firstRowCls);
43960         }
43961
43962         Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
43963     },
43964
43965     afterRender : function(){
43966         if(!this.ds || !this.cm){
43967             return;
43968         }
43969         this.mainBody.dom.innerHTML = this.renderRows() || '&#160;';
43970         this.processRows(0, true);
43971
43972         if(this.deferEmptyText !== true){
43973             this.applyEmptyText();
43974         }
43975         this.grid.fireEvent('viewready', this.grid);
43976     },
43977
43978     
43979     renderUI : function() {
43980         var templates = this.templates,
43981             header    = this.renderHeaders(),
43982             body      = templates.body.apply({rows:'&#160;'});
43983
43984         var html = templates.master.apply({
43985             body  : body,
43986             header: header,
43987             ostyle: 'width:' + this.getOffsetWidth() + ';',
43988             bstyle: 'width:' + this.getTotalWidth()  + ';'
43989         });
43990
43991         var g = this.grid;
43992
43993         g.getGridEl().dom.innerHTML = html;
43994
43995         this.initElements();
43996
43997         
43998         Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
43999
44000         this.mainHd.on({
44001             scope    : this,
44002             mouseover: this.handleHdOver,
44003             mouseout : this.handleHdOut,
44004             mousemove: this.handleHdMove
44005         });
44006
44007         this.scroller.on('scroll', this.syncScroll,  this);
44008         if (g.enableColumnResize !== false) {
44009             this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
44010         }
44011
44012         if (g.enableColumnMove) {
44013             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
44014             this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
44015         }
44016
44017         if (g.enableHdMenu !== false) {
44018             this.hmenu = new Ext.menu.Menu({id: g.id + '-hctx'});
44019             this.hmenu.add(
44020                 {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
44021                 {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
44022             );
44023
44024             if (g.enableColumnHide !== false) {
44025                 this.colMenu = new Ext.menu.Menu({id:g.id + '-hcols-menu'});
44026                 this.colMenu.on({
44027                     scope     : this,
44028                     beforeshow: this.beforeColMenuShow,
44029                     itemclick : this.handleHdMenuClick
44030                 });
44031                 this.hmenu.add('-', {
44032                     itemId:'columns',
44033                     hideOnClick: false,
44034                     text: this.columnsText,
44035                     menu: this.colMenu,
44036                     iconCls: 'x-cols-icon'
44037                 });
44038             }
44039
44040             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
44041         }
44042
44043         if (g.trackMouseOver) {
44044             this.mainBody.on({
44045                 scope    : this,
44046                 mouseover: this.onRowOver,
44047                 mouseout : this.onRowOut
44048             });
44049         }
44050
44051         if (g.enableDragDrop || g.enableDrag) {
44052             this.dragZone = new Ext.grid.GridDragZone(g, {
44053                 ddGroup : g.ddGroup || 'GridDD'
44054             });
44055         }
44056
44057         this.updateHeaderSortState();
44058     },
44059
44060     
44061     processEvent : function(name, e) {
44062         var t = e.getTarget(),
44063             g = this.grid,
44064             header = this.findHeaderIndex(t);
44065         g.fireEvent(name, e);
44066         if (header !== false) {
44067             g.fireEvent('header' + name, g, header, e);
44068         } else {
44069             var row = this.findRowIndex(t),
44070                 cell,
44071                 body;
44072             if (row !== false) {
44073                 g.fireEvent('row' + name, g, row, e);
44074                 cell = this.findCellIndex(t);
44075                 if (cell !== false) {
44076                     g.fireEvent('cell' + name, g, row, cell, e);
44077                 } else {
44078                     body = this.findRowBody(t);
44079                     if (body) {
44080                         g.fireEvent('rowbody' + name, g, row, e);
44081                     }
44082                 }
44083             } else {
44084                 g.fireEvent('container' + name, g, e);
44085             }
44086         }
44087     },
44088
44089     
44090     layout : function() {
44091         if(!this.mainBody){
44092             return; 
44093         }
44094         var g = this.grid;
44095         var c = g.getGridEl();
44096         var csize = c.getSize(true);
44097         var vw = csize.width;
44098
44099         if(!g.hideHeaders && (vw < 20 || csize.height < 20)){ 
44100             return;
44101         }
44102
44103         if(g.autoHeight){
44104             this.scroller.dom.style.overflow = 'visible';
44105             if(Ext.isWebKit){
44106                 this.scroller.dom.style.position = 'static';
44107             }
44108         }else{
44109             this.el.setSize(csize.width, csize.height);
44110
44111             var hdHeight = this.mainHd.getHeight();
44112             var vh = csize.height - (hdHeight);
44113
44114             this.scroller.setSize(vw, vh);
44115             if(this.innerHd){
44116                 this.innerHd.style.width = (vw)+'px';
44117             }
44118         }
44119         if(this.forceFit){
44120             if(this.lastViewWidth != vw){
44121                 this.fitColumns(false, false);
44122                 this.lastViewWidth = vw;
44123             }
44124         }else {
44125             this.autoExpand();
44126             this.syncHeaderScroll();
44127         }
44128         this.onLayout(vw, vh);
44129     },
44130
44131     
44132     
44133     onLayout : function(vw, vh){
44134         
44135     },
44136
44137     onColumnWidthUpdated : function(col, w, tw){
44138         
44139     },
44140
44141     onAllColumnWidthsUpdated : function(ws, tw){
44142         
44143     },
44144
44145     onColumnHiddenUpdated : function(col, hidden, tw){
44146         
44147     },
44148
44149     updateColumnText : function(col, text){
44150         
44151     },
44152
44153     afterMove : function(colIndex){
44154         
44155     },
44156
44157     
44158     
44159     init : function(grid){
44160         this.grid = grid;
44161
44162         this.initTemplates();
44163         this.initData(grid.store, grid.colModel);
44164         this.initUI(grid);
44165     },
44166
44167     
44168     getColumnId : function(index){
44169       return this.cm.getColumnId(index);
44170     },
44171
44172     
44173     getOffsetWidth : function() {
44174         return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
44175     },
44176
44177     getScrollOffset: function(){
44178         return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
44179     },
44180
44181     
44182     renderHeaders : function() {
44183         var cm   = this.cm,
44184             ts   = this.templates,
44185             ct   = ts.hcell,
44186             cb   = [],
44187             p    = {},
44188             len  = cm.getColumnCount(),
44189             last = len - 1;
44190
44191         for (var i = 0; i < len; i++) {
44192             p.id = cm.getColumnId(i);
44193             p.value = cm.getColumnHeader(i) || '';
44194             p.style = this.getColumnStyle(i, true);
44195             p.tooltip = this.getColumnTooltip(i);
44196             p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
44197
44198             if (cm.config[i].align == 'right') {
44199                 p.istyle = 'padding-right:16px';
44200             } else {
44201                 delete p.istyle;
44202             }
44203             cb[cb.length] = ct.apply(p);
44204         }
44205         return ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'});
44206     },
44207
44208     
44209     getColumnTooltip : function(i){
44210         var tt = this.cm.getColumnTooltip(i);
44211         if(tt){
44212             if(Ext.QuickTips.isEnabled()){
44213                 return 'ext:qtip="'+tt+'"';
44214             }else{
44215                 return 'title="'+tt+'"';
44216             }
44217         }
44218         return '';
44219     },
44220
44221     
44222     beforeUpdate : function(){
44223         this.grid.stopEditing(true);
44224     },
44225
44226     
44227     updateHeaders : function(){
44228         this.innerHd.firstChild.innerHTML = this.renderHeaders();
44229         this.innerHd.firstChild.style.width = this.getOffsetWidth();
44230         this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
44231     },
44232
44233     
44234     focusRow : function(row){
44235         this.focusCell(row, 0, false);
44236     },
44237
44238     
44239     focusCell : function(row, col, hscroll){
44240         this.syncFocusEl(this.ensureVisible(row, col, hscroll));
44241         if(Ext.isGecko){
44242             this.focusEl.focus();
44243         }else{
44244             this.focusEl.focus.defer(1, this.focusEl);
44245         }
44246     },
44247
44248     resolveCell : function(row, col, hscroll){
44249         if(!Ext.isNumber(row)){
44250             row = row.rowIndex;
44251         }
44252         if(!this.ds){
44253             return null;
44254         }
44255         if(row < 0 || row >= this.ds.getCount()){
44256             return null;
44257         }
44258         col = (col !== undefined ? col : 0);
44259
44260         var rowEl = this.getRow(row),
44261             cm = this.cm,
44262             colCount = cm.getColumnCount(),
44263             cellEl;
44264         if(!(hscroll === false && col === 0)){
44265             while(col < colCount && cm.isHidden(col)){
44266                 col++;
44267             }
44268             cellEl = this.getCell(row, col);
44269         }
44270
44271         return {row: rowEl, cell: cellEl};
44272     },
44273
44274     getResolvedXY : function(resolved){
44275         if(!resolved){
44276             return null;
44277         }
44278         var s = this.scroller.dom, c = resolved.cell, r = resolved.row;
44279         return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];
44280     },
44281
44282     syncFocusEl : function(row, col, hscroll){
44283         var xy = row;
44284         if(!Ext.isArray(xy)){
44285             row = Math.min(row, Math.max(0, this.getRows().length-1));
44286             if (isNaN(row)) {
44287                 return;
44288             }
44289             xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
44290         }
44291         this.focusEl.setXY(xy||this.scroller.getXY());
44292     },
44293
44294     ensureVisible : function(row, col, hscroll){
44295         var resolved = this.resolveCell(row, col, hscroll);
44296         if(!resolved || !resolved.row){
44297             return;
44298         }
44299
44300         var rowEl = resolved.row,
44301             cellEl = resolved.cell,
44302             c = this.scroller.dom,
44303             ctop = 0,
44304             p = rowEl,
44305             stop = this.el.dom;
44306
44307         while(p && p != stop){
44308             ctop += p.offsetTop;
44309             p = p.offsetParent;
44310         }
44311
44312         ctop -= this.mainHd.dom.offsetHeight;
44313         stop = parseInt(c.scrollTop, 10);
44314
44315         var cbot = ctop + rowEl.offsetHeight,
44316             ch = c.clientHeight,
44317             sbot = stop + ch;
44318
44319
44320         if(ctop < stop){
44321           c.scrollTop = ctop;
44322         }else if(cbot > sbot){
44323             c.scrollTop = cbot-ch;
44324         }
44325
44326         if(hscroll !== false){
44327             var cleft = parseInt(cellEl.offsetLeft, 10);
44328             var cright = cleft + cellEl.offsetWidth;
44329
44330             var sleft = parseInt(c.scrollLeft, 10);
44331             var sright = sleft + c.clientWidth;
44332             if(cleft < sleft){
44333                 c.scrollLeft = cleft;
44334             }else if(cright > sright){
44335                 c.scrollLeft = cright-c.clientWidth;
44336             }
44337         }
44338         return this.getResolvedXY(resolved);
44339     },
44340
44341     
44342     insertRows : function(dm, firstRow, lastRow, isUpdate) {
44343         var last = dm.getCount() - 1;
44344         if( !isUpdate && firstRow === 0 && lastRow >= last) {
44345             this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
44346                 this.refresh();
44347             this.fireEvent('rowsinserted', this, firstRow, lastRow);
44348         } else {
44349             if (!isUpdate) {
44350                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
44351             }
44352             var html = this.renderRows(firstRow, lastRow),
44353                 before = this.getRow(firstRow);
44354             if (before) {
44355                 if(firstRow === 0){
44356                     Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
44357                 }
44358                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
44359             } else {
44360                 var r = this.getRow(last - 1);
44361                 if(r){
44362                     Ext.fly(r).removeClass(this.lastRowCls);
44363                 }
44364                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
44365             }
44366             if (!isUpdate) {
44367                 this.fireEvent('rowsinserted', this, firstRow, lastRow);
44368                 this.processRows(firstRow);
44369             } else if (firstRow === 0 || firstRow >= last) {
44370                 
44371                 Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
44372             }
44373         }
44374         this.syncFocusEl(firstRow);
44375     },
44376
44377     
44378     deleteRows : function(dm, firstRow, lastRow){
44379         if(dm.getRowCount()<1){
44380             this.refresh();
44381         }else{
44382             this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
44383
44384             this.removeRows(firstRow, lastRow);
44385
44386             this.processRows(firstRow);
44387             this.fireEvent('rowsdeleted', this, firstRow, lastRow);
44388         }
44389     },
44390
44391     
44392     getColumnStyle : function(col, isHeader){
44393         var style = !isHeader ? (this.cm.config[col].css || '') : '';
44394         style += 'width:'+this.getColumnWidth(col)+';';
44395         if(this.cm.isHidden(col)){
44396             style += 'display:none;';
44397         }
44398         var align = this.cm.config[col].align;
44399         if(align){
44400             style += 'text-align:'+align+';';
44401         }
44402         return style;
44403     },
44404
44405     
44406     getColumnWidth : function(col){
44407         var w = this.cm.getColumnWidth(col);
44408         if(Ext.isNumber(w)){
44409             return (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? w : (w - this.borderWidth > 0 ? w - this.borderWidth : 0)) + 'px';
44410         }
44411         return w;
44412     },
44413
44414     
44415     getTotalWidth : function(){
44416         return this.cm.getTotalWidth()+'px';
44417     },
44418
44419     
44420     fitColumns : function(preventRefresh, onlyExpand, omitColumn){
44421         var cm = this.cm, i;
44422         var tw = cm.getTotalWidth(false);
44423         var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
44424
44425         if(aw < 20){ 
44426             return;
44427         }
44428         var extra = aw - tw;
44429
44430         if(extra === 0){
44431             return false;
44432         }
44433
44434         var vc = cm.getColumnCount(true);
44435         var ac = vc-(Ext.isNumber(omitColumn) ? 1 : 0);
44436         if(ac === 0){
44437             ac = 1;
44438             omitColumn = undefined;
44439         }
44440         var colCount = cm.getColumnCount();
44441         var cols = [];
44442         var extraCol = 0;
44443         var width = 0;
44444         var w;
44445         for (i = 0; i < colCount; i++){
44446             if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){
44447                 w = cm.getColumnWidth(i);
44448                 cols.push(i);
44449                 extraCol = i;
44450                 cols.push(w);
44451                 width += w;
44452             }
44453         }
44454         var frac = (aw - cm.getTotalWidth())/width;
44455         while (cols.length){
44456             w = cols.pop();
44457             i = cols.pop();
44458             cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
44459         }
44460
44461         if((tw = cm.getTotalWidth(false)) > aw){
44462             var adjustCol = ac != vc ? omitColumn : extraCol;
44463              cm.setColumnWidth(adjustCol, Math.max(1,
44464                      cm.getColumnWidth(adjustCol)- (tw-aw)), true);
44465         }
44466
44467         if(preventRefresh !== true){
44468             this.updateAllColumnWidths();
44469         }
44470
44471
44472         return true;
44473     },
44474
44475     
44476     autoExpand : function(preventUpdate){
44477         var g = this.grid, cm = this.cm;
44478         if(!this.userResized && g.autoExpandColumn){
44479             var tw = cm.getTotalWidth(false);
44480             var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
44481             if(tw != aw){
44482                 var ci = cm.getIndexById(g.autoExpandColumn);
44483                 var currentWidth = cm.getColumnWidth(ci);
44484                 var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
44485                 if(cw != currentWidth){
44486                     cm.setColumnWidth(ci, cw, true);
44487                     if(preventUpdate !== true){
44488                         this.updateColumnWidth(ci, cw);
44489                     }
44490                 }
44491             }
44492         }
44493     },
44494
44495     
44496     getColumnData : function(){
44497         
44498         var cs       = [],
44499             cm       = this.cm,
44500             colCount = cm.getColumnCount();
44501
44502         for (var i = 0; i < colCount; i++) {
44503             var name = cm.getDataIndex(i);
44504
44505             cs[i] = {
44506                 name    : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
44507                 renderer: cm.getRenderer(i),
44508                 scope   : cm.getRendererScope(i),
44509                 id      : cm.getColumnId(i),
44510                 style   : this.getColumnStyle(i)
44511             };
44512         }
44513
44514         return cs;
44515     },
44516
44517     
44518     renderRows : function(startRow, endRow){
44519         
44520         var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
44521         var colCount = cm.getColumnCount();
44522
44523         if(ds.getCount() < 1){
44524             return '';
44525         }
44526
44527         var cs = this.getColumnData();
44528
44529         startRow = startRow || 0;
44530         endRow = !Ext.isDefined(endRow) ? ds.getCount()-1 : endRow;
44531
44532         
44533         var rs = ds.getRange(startRow, endRow);
44534
44535         return this.doRender(cs, rs, ds, startRow, colCount, stripe);
44536     },
44537
44538     
44539     renderBody : function(){
44540         var markup = this.renderRows() || '&#160;';
44541         return this.templates.body.apply({rows: markup});
44542     },
44543
44544     
44545     refreshRow : function(record){
44546         var ds = this.ds, index;
44547         if(Ext.isNumber(record)){
44548             index = record;
44549             record = ds.getAt(index);
44550             if(!record){
44551                 return;
44552             }
44553         }else{
44554             index = ds.indexOf(record);
44555             if(index < 0){
44556                 return;
44557             }
44558         }
44559         this.insertRows(ds, index, index, true);
44560         this.getRow(index).rowIndex = index;
44561         this.onRemove(ds, record, index+1, true);
44562         this.fireEvent('rowupdated', this, index, record);
44563     },
44564
44565     
44566     refresh : function(headersToo){
44567         this.fireEvent('beforerefresh', this);
44568         this.grid.stopEditing(true);
44569
44570         var result = this.renderBody();
44571         this.mainBody.update(result).setWidth(this.getTotalWidth());
44572         if(headersToo === true){
44573             this.updateHeaders();
44574             this.updateHeaderSortState();
44575         }
44576         this.processRows(0, true);
44577         this.layout();
44578         this.applyEmptyText();
44579         this.fireEvent('refresh', this);
44580     },
44581
44582     
44583     applyEmptyText : function(){
44584         if(this.emptyText && !this.hasRows()){
44585             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
44586         }
44587     },
44588
44589     
44590     updateHeaderSortState : function(){
44591         var state = this.ds.getSortState();
44592         if (!state) {
44593             return;
44594         }
44595
44596         if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
44597             this.grid.fireEvent('sortchange', this.grid, state);
44598         }
44599
44600         this.sortState = state;
44601
44602         var sortColumn = this.cm.findColumnIndex(state.field);
44603         if (sortColumn != -1){
44604             var sortDir = state.direction;
44605             this.updateSortIcon(sortColumn, sortDir);
44606         }
44607     },
44608
44609     
44610     clearHeaderSortState : function(){
44611         if (!this.sortState) {
44612             return;
44613         }
44614         this.grid.fireEvent('sortchange', this.grid, null);
44615         this.mainHd.select('td').removeClass(this.sortClasses);
44616         delete this.sortState;
44617     },
44618
44619     
44620     destroy : function(){
44621         if (this.scrollToTopTask && this.scrollToTopTask.cancel){
44622             this.scrollToTopTask.cancel();
44623         }
44624         if(this.colMenu){
44625             Ext.menu.MenuMgr.unregister(this.colMenu);
44626             this.colMenu.destroy();
44627             delete this.colMenu;
44628         }
44629         if(this.hmenu){
44630             Ext.menu.MenuMgr.unregister(this.hmenu);
44631             this.hmenu.destroy();
44632             delete this.hmenu;
44633         }
44634
44635         this.initData(null, null);
44636         this.purgeListeners();
44637         Ext.fly(this.innerHd).un("click", this.handleHdDown, this);
44638
44639         if(this.grid.enableColumnMove){
44640             Ext.destroy(
44641                 this.columnDrag.el,
44642                 this.columnDrag.proxy.ghost,
44643                 this.columnDrag.proxy.el,
44644                 this.columnDrop.el,
44645                 this.columnDrop.proxyTop,
44646                 this.columnDrop.proxyBottom,
44647                 this.columnDrag.dragData.ddel,
44648                 this.columnDrag.dragData.header
44649             );
44650             if (this.columnDrag.proxy.anim) {
44651                 Ext.destroy(this.columnDrag.proxy.anim);
44652             }
44653             delete this.columnDrag.proxy.ghost;
44654             delete this.columnDrag.dragData.ddel;
44655             delete this.columnDrag.dragData.header;
44656             this.columnDrag.destroy();
44657             delete Ext.dd.DDM.locationCache[this.columnDrag.id];
44658             delete this.columnDrag._domRef;
44659
44660             delete this.columnDrop.proxyTop;
44661             delete this.columnDrop.proxyBottom;
44662             this.columnDrop.destroy();
44663             delete Ext.dd.DDM.locationCache["gridHeader" + this.grid.getGridEl().id];
44664             delete this.columnDrop._domRef;
44665             delete Ext.dd.DDM.ids[this.columnDrop.ddGroup];
44666         }
44667
44668         if (this.splitZone){ 
44669             this.splitZone.destroy();
44670             delete this.splitZone._domRef;
44671             delete Ext.dd.DDM.ids["gridSplitters" + this.grid.getGridEl().id];
44672         }
44673
44674         Ext.fly(this.innerHd).removeAllListeners();
44675         Ext.removeNode(this.innerHd);
44676         delete this.innerHd;
44677
44678         Ext.destroy(
44679             this.el,
44680             this.mainWrap,
44681             this.mainHd,
44682             this.scroller,
44683             this.mainBody,
44684             this.focusEl,
44685             this.resizeMarker,
44686             this.resizeProxy,
44687             this.activeHdBtn,
44688             this.dragZone,
44689             this.splitZone,
44690             this._flyweight
44691         );
44692
44693         delete this.grid.container;
44694
44695         if(this.dragZone){
44696             this.dragZone.destroy();
44697         }
44698
44699         Ext.dd.DDM.currentTarget = null;
44700         delete Ext.dd.DDM.locationCache[this.grid.getGridEl().id];
44701
44702         Ext.EventManager.removeResizeListener(this.onWindowResize, this);
44703     },
44704
44705     
44706     onDenyColumnHide : function(){
44707
44708     },
44709
44710     
44711     render : function(){
44712         if(this.autoFill){
44713             var ct = this.grid.ownerCt;
44714             if (ct && ct.getLayout()){
44715                 ct.on('afterlayout', function(){
44716                     this.fitColumns(true, true);
44717                     this.updateHeaders();
44718                 }, this, {single: true});
44719             }else{
44720                 this.fitColumns(true, true);
44721             }
44722         }else if(this.forceFit){
44723             this.fitColumns(true, false);
44724         }else if(this.grid.autoExpandColumn){
44725             this.autoExpand(true);
44726         }
44727
44728         this.renderUI();
44729     },
44730
44731     
44732     
44733     initData : function(ds, cm){
44734         if(this.ds){
44735             this.ds.un('load', this.onLoad, this);
44736             this.ds.un('datachanged', this.onDataChange, this);
44737             this.ds.un('add', this.onAdd, this);
44738             this.ds.un('remove', this.onRemove, this);
44739             this.ds.un('update', this.onUpdate, this);
44740             this.ds.un('clear', this.onClear, this);
44741             if(this.ds !== ds && this.ds.autoDestroy){
44742                 this.ds.destroy();
44743             }
44744         }
44745         if(ds){
44746             ds.on({
44747                 scope: this,
44748                 load: this.onLoad,
44749                 datachanged: this.onDataChange,
44750                 add: this.onAdd,
44751                 remove: this.onRemove,
44752                 update: this.onUpdate,
44753                 clear: this.onClear
44754             });
44755         }
44756         this.ds = ds;
44757
44758         if(this.cm){
44759             this.cm.un('configchange', this.onColConfigChange, this);
44760             this.cm.un('widthchange', this.onColWidthChange, this);
44761             this.cm.un('headerchange', this.onHeaderChange, this);
44762             this.cm.un('hiddenchange', this.onHiddenChange, this);
44763             this.cm.un('columnmoved', this.onColumnMove, this);
44764         }
44765         if(cm){
44766             delete this.lastViewWidth;
44767             cm.on({
44768                 scope: this,
44769                 configchange: this.onColConfigChange,
44770                 widthchange: this.onColWidthChange,
44771                 headerchange: this.onHeaderChange,
44772                 hiddenchange: this.onHiddenChange,
44773                 columnmoved: this.onColumnMove
44774             });
44775         }
44776         this.cm = cm;
44777     },
44778
44779     
44780     onDataChange : function(){
44781         this.refresh();
44782         this.updateHeaderSortState();
44783         this.syncFocusEl(0);
44784     },
44785
44786     
44787     onClear : function(){
44788         this.refresh();
44789         this.syncFocusEl(0);
44790     },
44791
44792     
44793     onUpdate : function(ds, record){
44794         this.refreshRow(record);
44795     },
44796
44797     
44798     onAdd : function(ds, records, index){
44799         this.insertRows(ds, index, index + (records.length-1));
44800     },
44801
44802     
44803     onRemove : function(ds, record, index, isUpdate){
44804         if(isUpdate !== true){
44805             this.fireEvent('beforerowremoved', this, index, record);
44806         }
44807         this.removeRow(index);
44808         if(isUpdate !== true){
44809             this.processRows(index);
44810             this.applyEmptyText();
44811             this.fireEvent('rowremoved', this, index, record);
44812         }
44813     },
44814
44815     
44816     onLoad : function(){
44817         if (Ext.isGecko){
44818             if (!this.scrollToTopTask) {
44819                 this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
44820             }
44821             this.scrollToTopTask.delay(1);
44822         }else{
44823             this.scrollToTop();
44824         }
44825     },
44826
44827     
44828     onColWidthChange : function(cm, col, width){
44829         this.updateColumnWidth(col, width);
44830     },
44831
44832     
44833     onHeaderChange : function(cm, col, text){
44834         this.updateHeaders();
44835     },
44836
44837     
44838     onHiddenChange : function(cm, col, hidden){
44839         this.updateColumnHidden(col, hidden);
44840     },
44841
44842     
44843     onColumnMove : function(cm, oldIndex, newIndex){
44844         this.indexMap = null;
44845         var s = this.getScrollState();
44846         this.refresh(true);
44847         this.restoreScroll(s);
44848         this.afterMove(newIndex);
44849         this.grid.fireEvent('columnmove', oldIndex, newIndex);
44850     },
44851
44852     
44853     onColConfigChange : function(){
44854         delete this.lastViewWidth;
44855         this.indexMap = null;
44856         this.refresh(true);
44857     },
44858
44859     
44860     
44861     initUI : function(grid){
44862         grid.on('headerclick', this.onHeaderClick, this);
44863     },
44864
44865     
44866     initEvents : function(){
44867     },
44868
44869     
44870     onHeaderClick : function(g, index){
44871         if(this.headersDisabled || !this.cm.isSortable(index)){
44872             return;
44873         }
44874         g.stopEditing(true);
44875         g.store.sort(this.cm.getDataIndex(index));
44876     },
44877
44878     
44879     onRowOver : function(e, t){
44880         var row;
44881         if((row = this.findRowIndex(t)) !== false){
44882             this.addRowClass(row, 'x-grid3-row-over');
44883         }
44884     },
44885
44886     
44887     onRowOut : function(e, t){
44888         var row;
44889         if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
44890             this.removeRowClass(row, 'x-grid3-row-over');
44891         }
44892     },
44893
44894     
44895     handleWheel : function(e){
44896         e.stopPropagation();
44897     },
44898
44899     
44900     onRowSelect : function(row){
44901         this.addRowClass(row, this.selectedRowClass);
44902     },
44903
44904     
44905     onRowDeselect : function(row){
44906         this.removeRowClass(row, this.selectedRowClass);
44907     },
44908
44909     
44910     onCellSelect : function(row, col){
44911         var cell = this.getCell(row, col);
44912         if(cell){
44913             this.fly(cell).addClass('x-grid3-cell-selected');
44914         }
44915     },
44916
44917     
44918     onCellDeselect : function(row, col){
44919         var cell = this.getCell(row, col);
44920         if(cell){
44921             this.fly(cell).removeClass('x-grid3-cell-selected');
44922         }
44923     },
44924
44925     
44926     onColumnSplitterMoved : function(i, w){
44927         this.userResized = true;
44928         var cm = this.grid.colModel;
44929         cm.setColumnWidth(i, w, true);
44930
44931         if(this.forceFit){
44932             this.fitColumns(true, false, i);
44933             this.updateAllColumnWidths();
44934         }else{
44935             this.updateColumnWidth(i, w);
44936             this.syncHeaderScroll();
44937         }
44938
44939         this.grid.fireEvent('columnresize', i, w);
44940     },
44941
44942     
44943     handleHdMenuClick : function(item){
44944         var index = this.hdCtxIndex,
44945             cm = this.cm,
44946             ds = this.ds,
44947             id = item.getItemId();
44948         switch(id){
44949             case 'asc':
44950                 ds.sort(cm.getDataIndex(index), 'ASC');
44951                 break;
44952             case 'desc':
44953                 ds.sort(cm.getDataIndex(index), 'DESC');
44954                 break;
44955             default:
44956                 index = cm.getIndexById(id.substr(4));
44957                 if(index != -1){
44958                     if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
44959                         this.onDenyColumnHide();
44960                         return false;
44961                     }
44962                     cm.setHidden(index, item.checked);
44963                 }
44964         }
44965         return true;
44966     },
44967
44968     
44969     isHideableColumn : function(c){
44970         return !c.hidden;
44971     },
44972
44973     
44974     beforeColMenuShow : function(){
44975         var cm = this.cm,  colCount = cm.getColumnCount();
44976         this.colMenu.removeAll();
44977         for(var i = 0; i < colCount; i++){
44978             if(cm.config[i].hideable !== false){
44979                 this.colMenu.add(new Ext.menu.CheckItem({
44980                     itemId: 'col-'+cm.getColumnId(i),
44981                     text: cm.getColumnHeader(i),
44982                     checked: !cm.isHidden(i),
44983                     hideOnClick:false,
44984                     disabled: cm.config[i].hideable === false
44985                 }));
44986             }
44987         }
44988     },
44989
44990     
44991     handleHdDown : function(e, t){
44992         if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
44993             e.stopEvent();
44994             var hd = this.findHeaderCell(t);
44995             Ext.fly(hd).addClass('x-grid3-hd-menu-open');
44996             var index = this.getCellIndex(hd);
44997             this.hdCtxIndex = index;
44998             var ms = this.hmenu.items, cm = this.cm;
44999             ms.get('asc').setDisabled(!cm.isSortable(index));
45000             ms.get('desc').setDisabled(!cm.isSortable(index));
45001             this.hmenu.on('hide', function(){
45002                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
45003             }, this, {single:true});
45004             this.hmenu.show(t, 'tl-bl?');
45005         }
45006     },
45007
45008     
45009     handleHdOver : function(e, t){
45010         var hd = this.findHeaderCell(t);
45011         if(hd && !this.headersDisabled){
45012             this.activeHdRef = t;
45013             this.activeHdIndex = this.getCellIndex(hd);
45014             var fly = this.fly(hd);
45015             this.activeHdRegion = fly.getRegion();
45016             if(!this.cm.isMenuDisabled(this.activeHdIndex)){
45017                 fly.addClass('x-grid3-hd-over');
45018                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
45019                 if(this.activeHdBtn){
45020                     this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
45021                 }
45022             }
45023         }
45024     },
45025
45026     
45027     handleHdMove : function(e, t){
45028         var hd = this.findHeaderCell(this.activeHdRef);
45029         if(hd && !this.headersDisabled){
45030             var hw = this.splitHandleWidth || 5,
45031                 r = this.activeHdRegion,
45032                 x = e.getPageX(),
45033                 ss = hd.style,
45034                 cur = '';
45035             if(this.grid.enableColumnResize !== false){
45036                 if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
45037                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
45038                 }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
45039                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
45040                 }
45041             }
45042             ss.cursor = cur;
45043         }
45044     },
45045
45046     
45047     handleHdOut : function(e, t){
45048         var hd = this.findHeaderCell(t);
45049         if(hd && (!Ext.isIE || !e.within(hd, true))){
45050             this.activeHdRef = null;
45051             this.fly(hd).removeClass('x-grid3-hd-over');
45052             hd.style.cursor = '';
45053         }
45054     },
45055
45056     
45057     hasRows : function(){
45058         var fc = this.mainBody.dom.firstChild;
45059         return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
45060     },
45061
45062     
45063     bind : function(d, c){
45064         this.initData(d, c);
45065     }
45066 });
45067
45068
45069
45070
45071 Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
45072     
45073     constructor: function(grid, hd){
45074         this.grid = grid;
45075         this.view = grid.getView();
45076         this.marker = this.view.resizeMarker;
45077         this.proxy = this.view.resizeProxy;
45078         Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
45079             'gridSplitters' + this.grid.getGridEl().id, {
45080             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
45081         });
45082         this.scroll = false;
45083         this.hw = this.view.splitHandleWidth || 5;
45084     },
45085
45086     b4StartDrag : function(x, y){
45087         this.dragHeadersDisabled = this.view.headersDisabled;
45088         this.view.headersDisabled = true;
45089         var h = this.view.mainWrap.getHeight();
45090         this.marker.setHeight(h);
45091         this.marker.show();
45092         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
45093         this.proxy.setHeight(h);
45094         var w = this.cm.getColumnWidth(this.cellIndex),
45095             minw = Math.max(w-this.grid.minColumnWidth, 0);
45096         this.resetConstraints();
45097         this.setXConstraint(minw, 1000);
45098         this.setYConstraint(0, 0);
45099         this.minX = x - minw;
45100         this.maxX = x + 1000;
45101         this.startPos = x;
45102         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
45103     },
45104
45105     allowHeaderDrag : function(e){
45106         return true;
45107     },
45108
45109     handleMouseDown : function(e){
45110         var t = this.view.findHeaderCell(e.getTarget());
45111         if(t && this.allowHeaderDrag(e)){
45112             var xy = this.view.fly(t).getXY(), 
45113                 x = xy[0], 
45114                 y = xy[1],
45115                 exy = e.getXY(), ex = exy[0],
45116                 w = t.offsetWidth, adjust = false;
45117                 
45118             if((ex - x) <= this.hw){
45119                 adjust = -1;
45120             }else if((x+w) - ex <= this.hw){
45121                 adjust = 0;
45122             }
45123             if(adjust !== false){
45124                 this.cm = this.grid.colModel;
45125                 var ci = this.view.getCellIndex(t);
45126                 if(adjust == -1){
45127                   if (ci + adjust < 0) {
45128                     return;
45129                   }
45130                     while(this.cm.isHidden(ci+adjust)){
45131                         --adjust;
45132                         if(ci+adjust < 0){
45133                             return;
45134                         }
45135                     }
45136                 }
45137                 this.cellIndex = ci+adjust;
45138                 this.split = t.dom;
45139                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
45140                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
45141                 }
45142             }else if(this.view.columnDrag){
45143                 this.view.columnDrag.callHandleMouseDown(e);
45144             }
45145         }
45146     },
45147
45148     endDrag : function(e){
45149         this.marker.hide();
45150         var v = this.view,
45151             endX = Math.max(this.minX, e.getPageX()),
45152             diff = endX - this.startPos,
45153             disabled = this.dragHeadersDisabled;
45154             
45155         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
45156         setTimeout(function(){
45157             v.headersDisabled = disabled;
45158         }, 50);
45159     },
45160
45161     autoOffset : function(){
45162         this.setDelta(0,0);
45163     }
45164 });
45165
45166
45167 Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
45168     maxDragWidth: 120,
45169     
45170     constructor : function(grid, hd, hd2){
45171         this.grid = grid;
45172         this.view = grid.getView();
45173         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
45174         Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
45175         if(hd2){
45176             this.setHandleElId(Ext.id(hd));
45177             this.setOuterHandleElId(Ext.id(hd2));
45178         }
45179         this.scroll = false;
45180     },
45181     
45182     getDragData : function(e){
45183         var t = Ext.lib.Event.getTarget(e),
45184             h = this.view.findHeaderCell(t);
45185         if(h){
45186             return {ddel: h.firstChild, header:h};
45187         }
45188         return false;
45189     },
45190
45191     onInitDrag : function(e){
45192         
45193         this.dragHeadersDisabled = this.view.headersDisabled;
45194         this.view.headersDisabled = true;
45195         var clone = this.dragData.ddel.cloneNode(true);
45196         clone.id = Ext.id();
45197         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
45198         this.proxy.update(clone);
45199         return true;
45200     },
45201
45202     afterValidDrop : function(){
45203         this.completeDrop();
45204     },
45205
45206     afterInvalidDrop : function(){
45207         this.completeDrop();
45208     },
45209     
45210     completeDrop: function(){
45211         var v = this.view,
45212             disabled = this.dragHeadersDisabled;
45213         setTimeout(function(){
45214             v.headersDisabled = disabled;
45215         }, 50);
45216     }
45217 });
45218
45219
45220
45221 Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
45222     proxyOffsets : [-4, -9],
45223     fly: Ext.Element.fly,
45224     
45225     constructor : function(grid, hd, hd2){
45226         this.grid = grid;
45227         this.view = grid.getView();
45228         
45229         this.proxyTop = Ext.DomHelper.append(document.body, {
45230             cls:"col-move-top", html:"&#160;"
45231         }, true);
45232         this.proxyBottom = Ext.DomHelper.append(document.body, {
45233             cls:"col-move-bottom", html:"&#160;"
45234         }, true);
45235         this.proxyTop.hide = this.proxyBottom.hide = function(){
45236             this.setLeftTop(-100,-100);
45237             this.setStyle("visibility", "hidden");
45238         };
45239         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
45240         
45241         
45242         Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
45243     },
45244
45245     getTargetFromEvent : function(e){
45246         var t = Ext.lib.Event.getTarget(e),
45247             cindex = this.view.findCellIndex(t);
45248         if(cindex !== false){
45249             return this.view.getHeaderCell(cindex);
45250         }
45251     },
45252
45253     nextVisible : function(h){
45254         var v = this.view, cm = this.grid.colModel;
45255         h = h.nextSibling;
45256         while(h){
45257             if(!cm.isHidden(v.getCellIndex(h))){
45258                 return h;
45259             }
45260             h = h.nextSibling;
45261         }
45262         return null;
45263     },
45264
45265     prevVisible : function(h){
45266         var v = this.view, cm = this.grid.colModel;
45267         h = h.prevSibling;
45268         while(h){
45269             if(!cm.isHidden(v.getCellIndex(h))){
45270                 return h;
45271             }
45272             h = h.prevSibling;
45273         }
45274         return null;
45275     },
45276
45277     positionIndicator : function(h, n, e){
45278         var x = Ext.lib.Event.getPageX(e),
45279             r = Ext.lib.Dom.getRegion(n.firstChild),
45280             px, 
45281             pt, 
45282             py = r.top + this.proxyOffsets[1];
45283         if((r.right - x) <= (r.right-r.left)/2){
45284             px = r.right+this.view.borderWidth;
45285             pt = "after";
45286         }else{
45287             px = r.left;
45288             pt = "before";
45289         }
45290
45291         if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
45292             return false;
45293         }
45294
45295         px +=  this.proxyOffsets[0];
45296         this.proxyTop.setLeftTop(px, py);
45297         this.proxyTop.show();
45298         if(!this.bottomOffset){
45299             this.bottomOffset = this.view.mainHd.getHeight();
45300         }
45301         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
45302         this.proxyBottom.show();
45303         return pt;
45304     },
45305
45306     onNodeEnter : function(n, dd, e, data){
45307         if(data.header != n){
45308             this.positionIndicator(data.header, n, e);
45309         }
45310     },
45311
45312     onNodeOver : function(n, dd, e, data){
45313         var result = false;
45314         if(data.header != n){
45315             result = this.positionIndicator(data.header, n, e);
45316         }
45317         if(!result){
45318             this.proxyTop.hide();
45319             this.proxyBottom.hide();
45320         }
45321         return result ? this.dropAllowed : this.dropNotAllowed;
45322     },
45323
45324     onNodeOut : function(n, dd, e, data){
45325         this.proxyTop.hide();
45326         this.proxyBottom.hide();
45327     },
45328
45329     onNodeDrop : function(n, dd, e, data){
45330         var h = data.header;
45331         if(h != n){
45332             var cm = this.grid.colModel,
45333                 x = Ext.lib.Event.getPageX(e),
45334                 r = Ext.lib.Dom.getRegion(n.firstChild),
45335                 pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
45336                 oldIndex = this.view.getCellIndex(h),
45337                 newIndex = this.view.getCellIndex(n);
45338             if(pt == "after"){
45339                 newIndex++;
45340             }
45341             if(oldIndex < newIndex){
45342                 newIndex--;
45343             }
45344             cm.moveColumn(oldIndex, newIndex);
45345             return true;
45346         }
45347         return false;
45348     }
45349 });
45350
45351 Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
45352     
45353     constructor : function(grid, hd){
45354         Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
45355         this.proxy.el.addClass('x-grid3-col-dd');
45356     },
45357     
45358     handleMouseDown : function(e){
45359     },
45360
45361     callHandleMouseDown : function(e){
45362         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
45363     }
45364 });
45365
45366 Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
45367     fly: Ext.Element.fly,
45368     
45369     constructor : function(grid, hd, hd2){
45370         this.grid = grid;
45371         this.view = grid.getView();
45372         this.proxy = this.view.resizeProxy;
45373         Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
45374             "gridSplitters" + this.grid.getGridEl().id, {
45375             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
45376         });
45377         this.setHandleElId(Ext.id(hd));
45378         this.setOuterHandleElId(Ext.id(hd2));
45379         this.scroll = false;
45380     },
45381
45382     b4StartDrag : function(x, y){
45383         this.view.headersDisabled = true;
45384         this.proxy.setHeight(this.view.mainWrap.getHeight());
45385         var w = this.cm.getColumnWidth(this.cellIndex);
45386         var minw = Math.max(w-this.grid.minColumnWidth, 0);
45387         this.resetConstraints();
45388         this.setXConstraint(minw, 1000);
45389         this.setYConstraint(0, 0);
45390         this.minX = x - minw;
45391         this.maxX = x + 1000;
45392         this.startPos = x;
45393         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
45394     },
45395
45396
45397     handleMouseDown : function(e){
45398         var ev = Ext.EventObject.setEvent(e);
45399         var t = this.fly(ev.getTarget());
45400         if(t.hasClass("x-grid-split")){
45401             this.cellIndex = this.view.getCellIndex(t.dom);
45402             this.split = t.dom;
45403             this.cm = this.grid.colModel;
45404             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
45405                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
45406             }
45407         }
45408     },
45409
45410     endDrag : function(e){
45411         this.view.headersDisabled = false;
45412         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
45413         var diff = endX - this.startPos;
45414         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
45415     },
45416
45417     autoOffset : function(){
45418         this.setDelta(0,0);
45419     }
45420 });
45421 Ext.grid.GridDragZone = function(grid, config){
45422     this.view = grid.getView();
45423     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
45424     this.scroll = false;
45425     this.grid = grid;
45426     this.ddel = document.createElement('div');
45427     this.ddel.className = 'x-grid-dd-wrap';
45428 };
45429
45430 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
45431     ddGroup : "GridDD",
45432
45433     
45434     getDragData : function(e){
45435         var t = Ext.lib.Event.getTarget(e);
45436         var rowIndex = this.view.findRowIndex(t);
45437         if(rowIndex !== false){
45438             var sm = this.grid.selModel;
45439             if(!sm.isSelected(rowIndex) || e.hasModifier()){
45440                 sm.handleMouseDown(this.grid, rowIndex, e);
45441             }
45442             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
45443         }
45444         return false;
45445     },
45446
45447     
45448     onInitDrag : function(e){
45449         var data = this.dragData;
45450         this.ddel.innerHTML = this.grid.getDragDropText();
45451         this.proxy.update(this.ddel);
45452         
45453     },
45454
45455     
45456     afterRepair : function(){
45457         this.dragging = false;
45458     },
45459
45460     
45461     getRepairXY : function(e, data){
45462         return false;
45463     },
45464
45465     onEndDrag : function(data, e){
45466         
45467     },
45468
45469     onValidDrop : function(dd, e, id){
45470         
45471         this.hideProxy();
45472     },
45473
45474     beforeInvalidDrop : function(e, id){
45475
45476     }
45477 });
45478
45479 Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
45480     
45481     defaultWidth: 100,
45482     
45483     defaultSortable: false,
45484     
45485     
45486
45487     constructor : function(config){
45488         
45489             if(config.columns){
45490                 Ext.apply(this, config);
45491                 this.setConfig(config.columns, true);
45492             }else{
45493                 this.setConfig(config, true);
45494             }
45495             this.addEvents(
45496                 
45497                 "widthchange",
45498                 
45499                 "headerchange",
45500                 
45501                 "hiddenchange",
45502                 
45503                 "columnmoved",
45504                 
45505                 "configchange"
45506             );
45507             Ext.grid.ColumnModel.superclass.constructor.call(this);
45508     },
45509
45510     
45511     getColumnId : function(index){
45512         return this.config[index].id;
45513     },
45514
45515     getColumnAt : function(index){
45516         return this.config[index];
45517     },
45518
45519     
45520     setConfig : function(config, initial){
45521         var i, c, len;
45522         if(!initial){ 
45523             delete this.totalWidth;
45524             for(i = 0, len = this.config.length; i < len; i++){
45525                 c = this.config[i];
45526                 if(c.setEditor){
45527                     
45528                     c.setEditor(null);
45529                 }
45530             }
45531         }
45532
45533         
45534         this.defaults = Ext.apply({
45535             width: this.defaultWidth,
45536             sortable: this.defaultSortable
45537         }, this.defaults);
45538
45539         this.config = config;
45540         this.lookup = {};
45541
45542         for(i = 0, len = config.length; i < len; i++){
45543             c = Ext.applyIf(config[i], this.defaults);
45544             
45545             if(Ext.isEmpty(c.id)){
45546                 c.id = i;
45547             }
45548             if(!c.isColumn){
45549                 var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
45550                 c = new Cls(c);
45551                 config[i] = c;
45552             }
45553             this.lookup[c.id] = c;
45554         }
45555         if(!initial){
45556             this.fireEvent('configchange', this);
45557         }
45558     },
45559
45560     
45561     getColumnById : function(id){
45562         return this.lookup[id];
45563     },
45564
45565     
45566     getIndexById : function(id){
45567         for(var i = 0, len = this.config.length; i < len; i++){
45568             if(this.config[i].id == id){
45569                 return i;
45570             }
45571         }
45572         return -1;
45573     },
45574
45575     
45576     moveColumn : function(oldIndex, newIndex){
45577         var c = this.config[oldIndex];
45578         this.config.splice(oldIndex, 1);
45579         this.config.splice(newIndex, 0, c);
45580         this.dataMap = null;
45581         this.fireEvent("columnmoved", this, oldIndex, newIndex);
45582     },
45583
45584     
45585     getColumnCount : function(visibleOnly){
45586         if(visibleOnly === true){
45587             var c = 0;
45588             for(var i = 0, len = this.config.length; i < len; i++){
45589                 if(!this.isHidden(i)){
45590                     c++;
45591                 }
45592             }
45593             return c;
45594         }
45595         return this.config.length;
45596     },
45597
45598     
45599     getColumnsBy : function(fn, scope){
45600         var r = [];
45601         for(var i = 0, len = this.config.length; i < len; i++){
45602             var c = this.config[i];
45603             if(fn.call(scope||this, c, i) === true){
45604                 r[r.length] = c;
45605             }
45606         }
45607         return r;
45608     },
45609
45610     
45611     isSortable : function(col){
45612         return !!this.config[col].sortable;
45613     },
45614
45615     
45616     isMenuDisabled : function(col){
45617         return !!this.config[col].menuDisabled;
45618     },
45619
45620     
45621     getRenderer : function(col){
45622         if(!this.config[col].renderer){
45623             return Ext.grid.ColumnModel.defaultRenderer;
45624         }
45625         return this.config[col].renderer;
45626     },
45627
45628     getRendererScope : function(col){
45629         return this.config[col].scope;
45630     },
45631
45632     
45633     setRenderer : function(col, fn){
45634         this.config[col].renderer = fn;
45635     },
45636
45637     
45638     getColumnWidth : function(col){
45639         return this.config[col].width;
45640     },
45641
45642     
45643     setColumnWidth : function(col, width, suppressEvent){
45644         this.config[col].width = width;
45645         this.totalWidth = null;
45646         if(!suppressEvent){
45647              this.fireEvent("widthchange", this, col, width);
45648         }
45649     },
45650
45651     
45652     getTotalWidth : function(includeHidden){
45653         if(!this.totalWidth){
45654             this.totalWidth = 0;
45655             for(var i = 0, len = this.config.length; i < len; i++){
45656                 if(includeHidden || !this.isHidden(i)){
45657                     this.totalWidth += this.getColumnWidth(i);
45658                 }
45659             }
45660         }
45661         return this.totalWidth;
45662     },
45663
45664     
45665     getColumnHeader : function(col){
45666         return this.config[col].header;
45667     },
45668
45669     
45670     setColumnHeader : function(col, header){
45671         this.config[col].header = header;
45672         this.fireEvent("headerchange", this, col, header);
45673     },
45674
45675     
45676     getColumnTooltip : function(col){
45677             return this.config[col].tooltip;
45678     },
45679     
45680     setColumnTooltip : function(col, tooltip){
45681             this.config[col].tooltip = tooltip;
45682     },
45683
45684     
45685     getDataIndex : function(col){
45686         return this.config[col].dataIndex;
45687     },
45688
45689     
45690     setDataIndex : function(col, dataIndex){
45691         this.config[col].dataIndex = dataIndex;
45692     },
45693
45694     
45695     findColumnIndex : function(dataIndex){
45696         var c = this.config;
45697         for(var i = 0, len = c.length; i < len; i++){
45698             if(c[i].dataIndex == dataIndex){
45699                 return i;
45700             }
45701         }
45702         return -1;
45703     },
45704
45705     
45706     isCellEditable : function(colIndex, rowIndex){
45707         var c = this.config[colIndex],
45708             ed = c.editable;
45709
45710         
45711         return !!(ed || (!Ext.isDefined(ed) && c.editor));
45712     },
45713
45714     
45715     getCellEditor : function(colIndex, rowIndex){
45716         return this.config[colIndex].getCellEditor(rowIndex);
45717     },
45718
45719     
45720     setEditable : function(col, editable){
45721         this.config[col].editable = editable;
45722     },
45723
45724     
45725     isHidden : function(colIndex){
45726         return !!this.config[colIndex].hidden; 
45727     },
45728
45729     
45730     isFixed : function(colIndex){
45731         return !!this.config[colIndex].fixed;
45732     },
45733
45734     
45735     isResizable : function(colIndex){
45736         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
45737     },
45738     
45739     setHidden : function(colIndex, hidden){
45740         var c = this.config[colIndex];
45741         if(c.hidden !== hidden){
45742             c.hidden = hidden;
45743             this.totalWidth = null;
45744             this.fireEvent("hiddenchange", this, colIndex, hidden);
45745         }
45746     },
45747
45748     
45749     setEditor : function(col, editor){
45750         this.config[col].setEditor(editor);
45751     },
45752
45753     
45754     destroy : function(){
45755         var c;
45756         for(var i = 0, len = this.config.length; i < len; i++){
45757             c = this.config[i];
45758             if(c.setEditor){
45759                 c.setEditor(null);
45760             }
45761         }
45762         this.purgeListeners();
45763     }
45764 });
45765
45766
45767 Ext.grid.ColumnModel.defaultRenderer = function(value){
45768     if(typeof value == "string" && value.length < 1){
45769         return "&#160;";
45770     }
45771     return value;
45772 };
45773 Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
45774     
45775
45776     constructor : function(){
45777         this.locked = false;
45778         Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
45779     },
45780
45781     
45782     init : function(grid){
45783         this.grid = grid;
45784         if(this.lockOnInit){
45785             delete this.lockOnInit;
45786             this.locked = false;
45787             this.lock();
45788         }
45789         this.initEvents();
45790     },
45791
45792     
45793     lock : function(){
45794         if(!this.locked){
45795             this.locked = true;
45796             
45797             var g = this.grid;
45798             if(g){
45799                 g.getView().on({
45800                     scope: this,
45801                     beforerefresh: this.sortUnLock,
45802                     refresh: this.sortLock
45803                 });
45804             }else{
45805                 this.lockOnInit = true;
45806             }
45807         }
45808     },
45809
45810     
45811     sortLock : function() {
45812         this.locked = true;
45813     },
45814
45815     
45816     sortUnLock : function() {
45817         this.locked = false;
45818     },
45819
45820     
45821     unlock : function(){
45822         if(this.locked){
45823             this.locked = false;
45824             var g = this.grid,
45825                 gv;
45826                 
45827             
45828             if(g){
45829                 gv = g.getView();
45830                 gv.un('beforerefresh', this.sortUnLock, this);
45831                 gv.un('refresh', this.sortLock, this);    
45832             }else{
45833                 delete this.lockOnInit;
45834             }
45835         }
45836     },
45837
45838     
45839     isLocked : function(){
45840         return this.locked;
45841     },
45842
45843     destroy: function(){
45844         this.unlock();
45845         this.purgeListeners();
45846     }
45847 });
45848 Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
45849     
45850     singleSelect : false,
45851     
45852     constructor : function(config){
45853         Ext.apply(this, config);
45854         this.selections = new Ext.util.MixedCollection(false, function(o){
45855             return o.id;
45856         });
45857
45858         this.last = false;
45859         this.lastActive = false;
45860
45861         this.addEvents(
45862                 
45863                 'selectionchange',
45864                 
45865                 'beforerowselect',
45866                 
45867                 'rowselect',
45868                 
45869                 'rowdeselect'
45870         );
45871         Ext.grid.RowSelectionModel.superclass.constructor.call(this);
45872     },
45873
45874     
45875     
45876     initEvents : function(){
45877
45878         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
45879             this.grid.on('rowmousedown', this.handleMouseDown, this);
45880         }
45881
45882         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
45883             'up' : function(e){
45884                 if(!e.shiftKey || this.singleSelect){
45885                     this.selectPrevious(false);
45886                 }else if(this.last !== false && this.lastActive !== false){
45887                     var last = this.last;
45888                     this.selectRange(this.last,  this.lastActive-1);
45889                     this.grid.getView().focusRow(this.lastActive);
45890                     if(last !== false){
45891                         this.last = last;
45892                     }
45893                 }else{
45894                     this.selectFirstRow();
45895                 }
45896             },
45897             'down' : function(e){
45898                 if(!e.shiftKey || this.singleSelect){
45899                     this.selectNext(false);
45900                 }else if(this.last !== false && this.lastActive !== false){
45901                     var last = this.last;
45902                     this.selectRange(this.last,  this.lastActive+1);
45903                     this.grid.getView().focusRow(this.lastActive);
45904                     if(last !== false){
45905                         this.last = last;
45906                     }
45907                 }else{
45908                     this.selectFirstRow();
45909                 }
45910             },
45911             scope: this
45912         });
45913
45914         this.grid.getView().on({
45915             scope: this,
45916             refresh: this.onRefresh,
45917             rowupdated: this.onRowUpdated,
45918             rowremoved: this.onRemove
45919         });
45920     },
45921
45922     
45923     onRefresh : function(){
45924         var ds = this.grid.store, index;
45925         var s = this.getSelections();
45926         this.clearSelections(true);
45927         for(var i = 0, len = s.length; i < len; i++){
45928             var r = s[i];
45929             if((index = ds.indexOfId(r.id)) != -1){
45930                 this.selectRow(index, true);
45931             }
45932         }
45933         if(s.length != this.selections.getCount()){
45934             this.fireEvent('selectionchange', this);
45935         }
45936     },
45937
45938     
45939     onRemove : function(v, index, r){
45940         if(this.selections.remove(r) !== false){
45941             this.fireEvent('selectionchange', this);
45942         }
45943     },
45944
45945     
45946     onRowUpdated : function(v, index, r){
45947         if(this.isSelected(r)){
45948             v.onRowSelect(index);
45949         }
45950     },
45951
45952     
45953     selectRecords : function(records, keepExisting){
45954         if(!keepExisting){
45955             this.clearSelections();
45956         }
45957         var ds = this.grid.store;
45958         for(var i = 0, len = records.length; i < len; i++){
45959             this.selectRow(ds.indexOf(records[i]), true);
45960         }
45961     },
45962
45963     
45964     getCount : function(){
45965         return this.selections.length;
45966     },
45967
45968     
45969     selectFirstRow : function(){
45970         this.selectRow(0);
45971     },
45972
45973     
45974     selectLastRow : function(keepExisting){
45975         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
45976     },
45977
45978     
45979     selectNext : function(keepExisting){
45980         if(this.hasNext()){
45981             this.selectRow(this.last+1, keepExisting);
45982             this.grid.getView().focusRow(this.last);
45983             return true;
45984         }
45985         return false;
45986     },
45987
45988     
45989     selectPrevious : function(keepExisting){
45990         if(this.hasPrevious()){
45991             this.selectRow(this.last-1, keepExisting);
45992             this.grid.getView().focusRow(this.last);
45993             return true;
45994         }
45995         return false;
45996     },
45997
45998     
45999     hasNext : function(){
46000         return this.last !== false && (this.last+1) < this.grid.store.getCount();
46001     },
46002
46003     
46004     hasPrevious : function(){
46005         return !!this.last;
46006     },
46007
46008
46009     
46010     getSelections : function(){
46011         return [].concat(this.selections.items);
46012     },
46013
46014     
46015     getSelected : function(){
46016         return this.selections.itemAt(0);
46017     },
46018
46019     
46020     each : function(fn, scope){
46021         var s = this.getSelections();
46022         for(var i = 0, len = s.length; i < len; i++){
46023             if(fn.call(scope || this, s[i], i) === false){
46024                 return false;
46025             }
46026         }
46027         return true;
46028     },
46029
46030     
46031     clearSelections : function(fast){
46032         if(this.isLocked()){
46033             return;
46034         }
46035         if(fast !== true){
46036             var ds = this.grid.store;
46037             var s = this.selections;
46038             s.each(function(r){
46039                 this.deselectRow(ds.indexOfId(r.id));
46040             }, this);
46041             s.clear();
46042         }else{
46043             this.selections.clear();
46044         }
46045         this.last = false;
46046     },
46047
46048
46049     
46050     selectAll : function(){
46051         if(this.isLocked()){
46052             return;
46053         }
46054         this.selections.clear();
46055         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
46056             this.selectRow(i, true);
46057         }
46058     },
46059
46060     
46061     hasSelection : function(){
46062         return this.selections.length > 0;
46063     },
46064
46065     
46066     isSelected : function(index){
46067         var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
46068         return (r && this.selections.key(r.id) ? true : false);
46069     },
46070
46071     
46072     isIdSelected : function(id){
46073         return (this.selections.key(id) ? true : false);
46074     },
46075
46076     
46077     handleMouseDown : function(g, rowIndex, e){
46078         if(e.button !== 0 || this.isLocked()){
46079             return;
46080         }
46081         var view = this.grid.getView();
46082         if(e.shiftKey && !this.singleSelect && this.last !== false){
46083             var last = this.last;
46084             this.selectRange(last, rowIndex, e.ctrlKey);
46085             this.last = last; 
46086             view.focusRow(rowIndex);
46087         }else{
46088             var isSelected = this.isSelected(rowIndex);
46089             if(e.ctrlKey && isSelected){
46090                 this.deselectRow(rowIndex);
46091             }else if(!isSelected || this.getCount() > 1){
46092                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
46093                 view.focusRow(rowIndex);
46094             }
46095         }
46096     },
46097
46098     
46099     selectRows : function(rows, keepExisting){
46100         if(!keepExisting){
46101             this.clearSelections();
46102         }
46103         for(var i = 0, len = rows.length; i < len; i++){
46104             this.selectRow(rows[i], true);
46105         }
46106     },
46107
46108     
46109     selectRange : function(startRow, endRow, keepExisting){
46110         var i;
46111         if(this.isLocked()){
46112             return;
46113         }
46114         if(!keepExisting){
46115             this.clearSelections();
46116         }
46117         if(startRow <= endRow){
46118             for(i = startRow; i <= endRow; i++){
46119                 this.selectRow(i, true);
46120             }
46121         }else{
46122             for(i = startRow; i >= endRow; i--){
46123                 this.selectRow(i, true);
46124             }
46125         }
46126     },
46127
46128     
46129     deselectRange : function(startRow, endRow, preventViewNotify){
46130         if(this.isLocked()){
46131             return;
46132         }
46133         for(var i = startRow; i <= endRow; i++){
46134             this.deselectRow(i, preventViewNotify);
46135         }
46136     },
46137
46138     
46139     selectRow : function(index, keepExisting, preventViewNotify){
46140         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
46141             return;
46142         }
46143         var r = this.grid.store.getAt(index);
46144         if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
46145             if(!keepExisting || this.singleSelect){
46146                 this.clearSelections();
46147             }
46148             this.selections.add(r);
46149             this.last = this.lastActive = index;
46150             if(!preventViewNotify){
46151                 this.grid.getView().onRowSelect(index);
46152             }
46153             this.fireEvent('rowselect', this, index, r);
46154             this.fireEvent('selectionchange', this);
46155         }
46156     },
46157
46158     
46159     deselectRow : function(index, preventViewNotify){
46160         if(this.isLocked()){
46161             return;
46162         }
46163         if(this.last == index){
46164             this.last = false;
46165         }
46166         if(this.lastActive == index){
46167             this.lastActive = false;
46168         }
46169         var r = this.grid.store.getAt(index);
46170         if(r){
46171             this.selections.remove(r);
46172             if(!preventViewNotify){
46173                 this.grid.getView().onRowDeselect(index);
46174             }
46175             this.fireEvent('rowdeselect', this, index, r);
46176             this.fireEvent('selectionchange', this);
46177         }
46178     },
46179
46180     
46181     restoreLast : function(){
46182         if(this._last){
46183             this.last = this._last;
46184         }
46185     },
46186
46187     
46188     acceptsNav : function(row, col, cm){
46189         return !cm.isHidden(col) && cm.isCellEditable(col, row);
46190     },
46191
46192     
46193     onEditorKey : function(field, e){
46194         var k = e.getKey(), 
46195             newCell, 
46196             g = this.grid, 
46197             last = g.lastEdit,
46198             ed = g.activeEditor,
46199             ae, last, r, c;
46200         var shift = e.shiftKey;
46201         if(k == e.TAB){
46202             e.stopEvent();
46203             ed.completeEdit();
46204             if(shift){
46205                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
46206             }else{
46207                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
46208             }
46209         }else if(k == e.ENTER){
46210             if(this.moveEditorOnEnter !== false){
46211                 if(shift){
46212                     newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
46213                 }else{
46214                     newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
46215                 }
46216             }
46217         }
46218         if(newCell){
46219             r = newCell[0];
46220             c = newCell[1];
46221
46222             if(last.row != r){
46223                 this.selectRow(r); 
46224             }
46225
46226             if(g.isEditor && g.editing){ 
46227                 ae = g.activeEditor;
46228                 if(ae && ae.field.triggerBlur){
46229                     
46230                     ae.field.triggerBlur();
46231                 }
46232             }
46233             g.startEditing(r, c);
46234         }
46235     },
46236     
46237     destroy : function(){
46238         if(this.rowNav){
46239             this.rowNav.disable();
46240             this.rowNav = null;
46241         }
46242         Ext.grid.RowSelectionModel.superclass.destroy.call(this);
46243     }
46244 });
46245 Ext.grid.Column = Ext.extend(Object, {
46246     
46247     
46248     
46249     
46250     
46251     
46252     
46253     
46254     
46255     
46256     
46257     
46258     
46259     
46260     
46261     
46262     
46263     
46264     
46265     
46266     
46267     
46268
46269     
46270     isColumn : true,
46271
46272     constructor : function(config){
46273         Ext.apply(this, config);
46274
46275         if(Ext.isString(this.renderer)){
46276             this.renderer = Ext.util.Format[this.renderer];
46277         }else if(Ext.isObject(this.renderer)){
46278             this.scope = this.renderer.scope;
46279             this.renderer = this.renderer.fn;
46280         }
46281         if(!this.scope){
46282             this.scope = this;
46283         }
46284
46285         var ed = this.editor;
46286         delete this.editor;
46287         this.setEditor(ed);
46288     },
46289
46290     
46291     renderer : function(value){
46292         if(Ext.isString(value) && value.length < 1){
46293             return '&#160;';
46294         }
46295         return value;
46296     },
46297
46298     
46299     getEditor: function(rowIndex){
46300         return this.editable !== false ? this.editor : null;
46301     },
46302
46303     
46304     setEditor : function(editor){
46305         var ed = this.editor;
46306         if(ed){
46307             if(ed.gridEditor){
46308                 ed.gridEditor.destroy();
46309                 delete ed.gridEditor;
46310             }else{
46311                 ed.destroy();
46312             }
46313         }
46314         this.editor = null;
46315         if(editor){
46316             
46317             if(!editor.isXType){
46318                 editor = Ext.create(editor, 'textfield');
46319             }
46320             this.editor = editor;
46321         }
46322     },
46323
46324     
46325     getCellEditor: function(rowIndex){
46326         var ed = this.getEditor(rowIndex);
46327         if(ed){
46328             if(!ed.startEdit){
46329                 if(!ed.gridEditor){
46330                     ed.gridEditor = new Ext.grid.GridEditor(ed);
46331                 }
46332                 ed = ed.gridEditor;
46333             }
46334         }
46335         return ed;
46336     }
46337 });
46338
46339
46340 Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
46341     
46342     trueText: 'true',
46343     
46344     falseText: 'false',
46345     
46346     undefinedText: '&#160;',
46347
46348     constructor: function(cfg){
46349         Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
46350         var t = this.trueText, f = this.falseText, u = this.undefinedText;
46351         this.renderer = function(v){
46352             if(v === undefined){
46353                 return u;
46354             }
46355             if(!v || v === 'false'){
46356                 return f;
46357             }
46358             return t;
46359         };
46360     }
46361 });
46362
46363
46364 Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
46365     
46366     format : '0,000.00',
46367     constructor: function(cfg){
46368         Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
46369         this.renderer = Ext.util.Format.numberRenderer(this.format);
46370     }
46371 });
46372
46373
46374 Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
46375     
46376     format : 'm/d/Y',
46377     constructor: function(cfg){
46378         Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
46379         this.renderer = Ext.util.Format.dateRenderer(this.format);
46380     }
46381 });
46382
46383
46384 Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
46385     
46386     constructor: function(cfg){
46387         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
46388         var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
46389         this.renderer = function(value, p, r){
46390             return tpl.apply(r.data);
46391         };
46392         this.tpl = tpl;
46393     }
46394 });
46395
46396
46397 Ext.grid.Column.types = {
46398     gridcolumn : Ext.grid.Column,
46399     booleancolumn: Ext.grid.BooleanColumn,
46400     numbercolumn: Ext.grid.NumberColumn,
46401     datecolumn: Ext.grid.DateColumn,
46402     templatecolumn: Ext.grid.TemplateColumn
46403 };
46404 Ext.grid.RowNumberer = Ext.extend(Object, {
46405     
46406     header: "",
46407     
46408     width: 23,
46409     
46410     sortable: false,
46411     
46412     constructor : function(config){
46413         Ext.apply(this, config);
46414         if(this.rowspan){
46415             this.renderer = this.renderer.createDelegate(this);
46416         }
46417     },
46418
46419     
46420     fixed:true,
46421     hideable: false,
46422     menuDisabled:true,
46423     dataIndex: '',
46424     id: 'numberer',
46425     rowspan: undefined,
46426
46427     
46428     renderer : function(v, p, record, rowIndex){
46429         if(this.rowspan){
46430             p.cellAttr = 'rowspan="'+this.rowspan+'"';
46431         }
46432         return rowIndex+1;
46433     }
46434 });
46435 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
46436
46437     
46438     
46439     header : '<div class="x-grid3-hd-checker">&#160;</div>',
46440     
46441     width : 20,
46442     
46443     sortable : false,
46444
46445     
46446     menuDisabled : true,
46447     fixed : true,
46448     hideable: false,
46449     dataIndex : '',
46450     id : 'checker',
46451
46452     constructor : function(){
46453         Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
46454
46455         if(this.checkOnly){
46456             this.handleMouseDown = Ext.emptyFn;
46457         }
46458     },
46459
46460     
46461     initEvents : function(){
46462         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
46463         this.grid.on('render', function(){
46464             var view = this.grid.getView();
46465             view.mainBody.on('mousedown', this.onMouseDown, this);
46466             Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
46467
46468         }, this);
46469     },
46470
46471     
46472     
46473     handleMouseDown : function() {
46474         Ext.grid.CheckboxSelectionModel.superclass.handleMouseDown.apply(this, arguments);
46475         this.mouseHandled = true;
46476     },
46477
46478     
46479     onMouseDown : function(e, t){
46480         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
46481             e.stopEvent();
46482             var row = e.getTarget('.x-grid3-row');
46483
46484             
46485             if(!this.mouseHandled && row){
46486                 var index = row.rowIndex;
46487                 if(this.isSelected(index)){
46488                     this.deselectRow(index);
46489                 }else{
46490                     this.selectRow(index, true);
46491                     this.grid.getView().focusRow(index);
46492                 }
46493             }
46494         }
46495         this.mouseHandled = false;
46496     },
46497
46498     
46499     onHdMouseDown : function(e, t){
46500         if(t.className == 'x-grid3-hd-checker'){
46501             e.stopEvent();
46502             var hd = Ext.fly(t.parentNode);
46503             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
46504             if(isChecked){
46505                 hd.removeClass('x-grid3-hd-checker-on');
46506                 this.clearSelections();
46507             }else{
46508                 hd.addClass('x-grid3-hd-checker-on');
46509                 this.selectAll();
46510             }
46511         }
46512     },
46513
46514     
46515     renderer : function(v, p, record){
46516         return '<div class="x-grid3-row-checker">&#160;</div>';
46517     }
46518 });
46519 Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
46520     
46521     constructor : function(config){
46522         Ext.apply(this, config);
46523
46524             this.selection = null;
46525         
46526             this.addEvents(
46527                 
46528                 "beforecellselect",
46529                 
46530                 "cellselect",
46531                 
46532                 "selectionchange"
46533             );
46534         
46535             Ext.grid.CellSelectionModel.superclass.constructor.call(this);
46536     },
46537
46538     
46539     initEvents : function(){
46540         this.grid.on('cellmousedown', this.handleMouseDown, this);
46541         this.grid.on(Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.handleKeyDown, this);
46542         this.grid.getView().on({
46543             scope: this,
46544             refresh: this.onViewChange,
46545             rowupdated: this.onRowUpdated,
46546             beforerowremoved: this.clearSelections,
46547             beforerowsinserted: this.clearSelections
46548         });
46549         if(this.grid.isEditor){
46550             this.grid.on('beforeedit', this.beforeEdit,  this);
46551         }
46552     },
46553
46554         
46555     beforeEdit : function(e){
46556         this.select(e.row, e.column, false, true, e.record);
46557     },
46558
46559         
46560     onRowUpdated : function(v, index, r){
46561         if(this.selection && this.selection.record == r){
46562             v.onCellSelect(index, this.selection.cell[1]);
46563         }
46564     },
46565
46566         
46567     onViewChange : function(){
46568         this.clearSelections(true);
46569     },
46570
46571         
46572     getSelectedCell : function(){
46573         return this.selection ? this.selection.cell : null;
46574     },
46575
46576     
46577     clearSelections : function(preventNotify){
46578         var s = this.selection;
46579         if(s){
46580             if(preventNotify !== true){
46581                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
46582             }
46583             this.selection = null;
46584             this.fireEvent("selectionchange", this, null);
46585         }
46586     },
46587
46588     
46589     hasSelection : function(){
46590         return this.selection ? true : false;
46591     },
46592
46593     
46594     handleMouseDown : function(g, row, cell, e){
46595         if(e.button !== 0 || this.isLocked()){
46596             return;
46597         }
46598         this.select(row, cell);
46599     },
46600
46601     
46602     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
46603         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
46604             this.clearSelections();
46605             r = r || this.grid.store.getAt(rowIndex);
46606             this.selection = {
46607                 record : r,
46608                 cell : [rowIndex, colIndex]
46609             };
46610             if(!preventViewNotify){
46611                 var v = this.grid.getView();
46612                 v.onCellSelect(rowIndex, colIndex);
46613                 if(preventFocus !== true){
46614                     v.focusCell(rowIndex, colIndex);
46615                 }
46616             }
46617             this.fireEvent("cellselect", this, rowIndex, colIndex);
46618             this.fireEvent("selectionchange", this, this.selection);
46619         }
46620     },
46621
46622         
46623     isSelectable : function(rowIndex, colIndex, cm){
46624         return !cm.isHidden(colIndex);
46625     },
46626     
46627     
46628     onEditorKey: function(field, e){
46629         if(e.getKey() == e.TAB){
46630             this.handleKeyDown(e);
46631         }
46632     },
46633
46634     
46635     handleKeyDown : function(e){
46636         if(!e.isNavKeyPress()){
46637             return;
46638         }
46639         
46640         var k = e.getKey(),
46641             g = this.grid,
46642             s = this.selection,
46643             sm = this,
46644             walk = function(row, col, step){
46645                 return g.walkCells(
46646                     row,
46647                     col,
46648                     step,
46649                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
46650                     sm
46651                 );
46652             },
46653             cell, newCell, r, c, ae;
46654
46655         switch(k){
46656             case e.ESC:
46657             case e.PAGE_UP:
46658             case e.PAGE_DOWN:
46659                 
46660                 break;
46661             default:
46662                 
46663                 e.stopEvent();
46664                 break;
46665         }
46666
46667         if(!s){
46668             cell = walk(0, 0, 1); 
46669             if(cell){
46670                 this.select(cell[0], cell[1]);
46671             }
46672             return;
46673         }
46674
46675         cell = s.cell;  
46676         r = cell[0];    
46677         c = cell[1];    
46678         
46679         switch(k){
46680             case e.TAB:
46681                 if(e.shiftKey){
46682                     newCell = walk(r, c - 1, -1);
46683                 }else{
46684                     newCell = walk(r, c + 1, 1);
46685                 }
46686                 break;
46687             case e.DOWN:
46688                 newCell = walk(r + 1, c, 1);
46689                 break;
46690             case e.UP:
46691                 newCell = walk(r - 1, c, -1);
46692                 break;
46693             case e.RIGHT:
46694                 newCell = walk(r, c + 1, 1);
46695                 break;
46696             case e.LEFT:
46697                 newCell = walk(r, c - 1, -1);
46698                 break;
46699             case e.ENTER:
46700                 if (g.isEditor && !g.editing) {
46701                     g.startEditing(r, c);
46702                     return;
46703                 }
46704                 break;
46705         }
46706
46707         if(newCell){
46708             
46709             r = newCell[0];
46710             c = newCell[1];
46711
46712             this.select(r, c); 
46713
46714             if(g.isEditor && g.editing){ 
46715                 ae = g.activeEditor;
46716                 if(ae && ae.field.triggerBlur){
46717                     
46718                     ae.field.triggerBlur();
46719                 }
46720                 g.startEditing(r, c);
46721             }
46722         }
46723     },
46724
46725     acceptsNav : function(row, col, cm){
46726         return !cm.isHidden(col) && cm.isCellEditable(col, row);
46727     }
46728 });
46729 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
46730     
46731     clicksToEdit: 2,
46732
46733     
46734     forceValidation: false,
46735
46736     
46737     isEditor : true,
46738     
46739     detectEdit: false,
46740
46741     
46742     autoEncode : false,
46743
46744     
46745     
46746     trackMouseOver: false, 
46747
46748     
46749     initComponent : function(){
46750         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
46751
46752         if(!this.selModel){
46753             
46754             this.selModel = new Ext.grid.CellSelectionModel();
46755         }
46756
46757         this.activeEditor = null;
46758
46759         this.addEvents(
46760             
46761             "beforeedit",
46762             
46763             "afteredit",
46764             
46765             "validateedit"
46766         );
46767     },
46768
46769     
46770     initEvents : function(){
46771         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
46772
46773         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
46774         this.on('columnresize', this.stopEditing, this, [true]);
46775
46776         if(this.clicksToEdit == 1){
46777             this.on("cellclick", this.onCellDblClick, this);
46778         }else {
46779             var view = this.getView();
46780             if(this.clicksToEdit == 'auto' && view.mainBody){
46781                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
46782             }
46783             this.on('celldblclick', this.onCellDblClick, this);
46784         }
46785     },
46786
46787     onResize : function(){
46788         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
46789         var ae = this.activeEditor;
46790         if(this.editing && ae){
46791             ae.realign(true);
46792         }
46793     },
46794
46795     
46796     onCellDblClick : function(g, row, col){
46797         this.startEditing(row, col);
46798     },
46799
46800     
46801     onAutoEditClick : function(e, t){
46802         if(e.button !== 0){
46803             return;
46804         }
46805         var row = this.view.findRowIndex(t),
46806             col = this.view.findCellIndex(t);
46807         if(row !== false && col !== false){
46808             this.stopEditing();
46809             if(this.selModel.getSelectedCell){ 
46810                 var sc = this.selModel.getSelectedCell();
46811                 if(sc && sc[0] === row && sc[1] === col){
46812                     this.startEditing(row, col);
46813                 }
46814             }else{
46815                 if(this.selModel.isSelected(row)){
46816                     this.startEditing(row, col);
46817                 }
46818             }
46819         }
46820     },
46821
46822     
46823     onEditComplete : function(ed, value, startValue){
46824         this.editing = false;
46825         this.lastActiveEditor = this.activeEditor;
46826         this.activeEditor = null;
46827
46828         var r = ed.record,
46829             field = this.colModel.getDataIndex(ed.col);
46830         value = this.postEditValue(value, startValue, r, field);
46831         if(this.forceValidation === true || String(value) !== String(startValue)){
46832             var e = {
46833                 grid: this,
46834                 record: r,
46835                 field: field,
46836                 originalValue: startValue,
46837                 value: value,
46838                 row: ed.row,
46839                 column: ed.col,
46840                 cancel:false
46841             };
46842             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
46843                 r.set(field, e.value);
46844                 delete e.cancel;
46845                 this.fireEvent("afteredit", e);
46846             }
46847         }
46848         this.view.focusCell(ed.row, ed.col);
46849     },
46850
46851     
46852     startEditing : function(row, col){
46853         this.stopEditing();
46854         if(this.colModel.isCellEditable(col, row)){
46855             this.view.ensureVisible(row, col, true);
46856             var r = this.store.getAt(row),
46857                 field = this.colModel.getDataIndex(col),
46858                 e = {
46859                     grid: this,
46860                     record: r,
46861                     field: field,
46862                     value: r.data[field],
46863                     row: row,
46864                     column: col,
46865                     cancel:false
46866                 };
46867             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
46868                 this.editing = true;
46869                 var ed = this.colModel.getCellEditor(col, row);
46870                 if(!ed){
46871                     return;
46872                 }
46873                 if(!ed.rendered){
46874                     ed.parentEl = this.view.getEditorParent(ed);
46875                     ed.on({
46876                         scope: this,
46877                         render: {
46878                             fn: function(c){
46879                                 c.field.focus(false, true);
46880                             },
46881                             single: true,
46882                             scope: this
46883                         },
46884                         specialkey: function(field, e){
46885                             this.getSelectionModel().onEditorKey(field, e);
46886                         },
46887                         complete: this.onEditComplete,
46888                         canceledit: this.stopEditing.createDelegate(this, [true])
46889                     });
46890                 }
46891                 Ext.apply(ed, {
46892                     row     : row,
46893                     col     : col,
46894                     record  : r
46895                 });
46896                 this.lastEdit = {
46897                     row: row,
46898                     col: col
46899                 };
46900                 this.activeEditor = ed;
46901                 
46902                 
46903                 ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
46904                 var v = this.preEditValue(r, field);
46905                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
46906
46907                 
46908                 (function(){
46909                     delete ed.selectSameEditor;
46910                 }).defer(50);
46911             }
46912         }
46913     },
46914
46915     
46916     preEditValue : function(r, field){
46917         var value = r.data[field];
46918         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
46919     },
46920
46921     
46922     postEditValue : function(value, originalValue, r, field){
46923         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
46924     },
46925
46926     
46927     stopEditing : function(cancel){
46928         if(this.editing){
46929             
46930             var ae = this.lastActiveEditor = this.activeEditor;
46931             if(ae){
46932                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
46933                 this.view.focusCell(ae.row, ae.col);
46934             }
46935             this.activeEditor = null;
46936         }
46937         this.editing = false;
46938     }
46939 });
46940 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
46941
46942 Ext.grid.GridEditor = function(field, config){
46943     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
46944     field.monitorTab = false;
46945 };
46946
46947 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
46948     alignment: "tl-tl",
46949     autoSize: "width",
46950     hideEl : false,
46951     cls: "x-small-editor x-grid-editor",
46952     shim:false,
46953     shadow:false
46954 });
46955 Ext.grid.PropertyRecord = Ext.data.Record.create([
46956     {name:'name',type:'string'}, 'value'
46957 ]);
46958
46959
46960 Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
46961     
46962     constructor : function(grid, source){
46963         this.grid = grid;
46964         this.store = new Ext.data.Store({
46965             recordType : Ext.grid.PropertyRecord
46966         });
46967         this.store.on('update', this.onUpdate,  this);
46968         if(source){
46969             this.setSource(source);
46970         }
46971         Ext.grid.PropertyStore.superclass.constructor.call(this);    
46972     },
46973     
46974     
46975     setSource : function(o){
46976         this.source = o;
46977         this.store.removeAll();
46978         var data = [];
46979         for(var k in o){
46980             if(this.isEditableValue(o[k])){
46981                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
46982             }
46983         }
46984         this.store.loadRecords({records: data}, {}, true);
46985     },
46986
46987     
46988     onUpdate : function(ds, record, type){
46989         if(type == Ext.data.Record.EDIT){
46990             var v = record.data.value;
46991             var oldValue = record.modified.value;
46992             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
46993                 this.source[record.id] = v;
46994                 record.commit();
46995                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
46996             }else{
46997                 record.reject();
46998             }
46999         }
47000     },
47001
47002     
47003     getProperty : function(row){
47004        return this.store.getAt(row);
47005     },
47006
47007     
47008     isEditableValue: function(val){
47009         return Ext.isPrimitive(val) || Ext.isDate(val);
47010     },
47011
47012     
47013     setValue : function(prop, value, create){
47014         var r = this.getRec(prop);
47015         if(r){
47016             r.set('value', value);
47017             this.source[prop] = value;
47018         }else if(create){
47019             
47020             this.source[prop] = value;
47021             r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
47022             this.store.add(r);
47023
47024         }
47025     },
47026     
47027     
47028     remove : function(prop){
47029         var r = this.getRec(prop);
47030         if(r){
47031             this.store.remove(r);
47032             delete this.source[prop];
47033         }
47034     },
47035     
47036     
47037     getRec : function(prop){
47038         return this.store.getById(prop);
47039     },
47040
47041     
47042     getSource : function(){
47043         return this.source;
47044     }
47045 });
47046
47047
47048 Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
47049     
47050     nameText : 'Name',
47051     valueText : 'Value',
47052     dateFormat : 'm/j/Y',
47053     trueText: 'true',
47054     falseText: 'false',
47055     
47056     constructor : function(grid, store){
47057         var g = Ext.grid,
47058                 f = Ext.form;
47059                 
47060             this.grid = grid;
47061             g.PropertyColumnModel.superclass.constructor.call(this, [
47062                 {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
47063                 {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
47064             ]);
47065             this.store = store;
47066         
47067             var bfield = new f.Field({
47068                 autoCreate: {tag: 'select', children: [
47069                     {tag: 'option', value: 'true', html: this.trueText},
47070                     {tag: 'option', value: 'false', html: this.falseText}
47071                 ]},
47072                 getValue : function(){
47073                     return this.el.dom.value == 'true';
47074                 }
47075             });
47076             this.editors = {
47077                 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
47078                 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
47079                 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
47080                 'boolean' : new g.GridEditor(bfield, {
47081                     autoSize: 'both'
47082                 })
47083             };
47084             this.renderCellDelegate = this.renderCell.createDelegate(this);
47085             this.renderPropDelegate = this.renderProp.createDelegate(this);
47086     },
47087
47088     
47089     renderDate : function(dateVal){
47090         return dateVal.dateFormat(this.dateFormat);
47091     },
47092
47093     
47094     renderBool : function(bVal){
47095         return this[bVal ? 'trueText' : 'falseText'];
47096     },
47097
47098     
47099     isCellEditable : function(colIndex, rowIndex){
47100         return colIndex == 1;
47101     },
47102
47103     
47104     getRenderer : function(col){
47105         return col == 1 ?
47106             this.renderCellDelegate : this.renderPropDelegate;
47107     },
47108
47109     
47110     renderProp : function(v){
47111         return this.getPropertyName(v);
47112     },
47113
47114     
47115     renderCell : function(val, meta, rec){
47116         var renderer = this.grid.customRenderers[rec.get('name')];
47117         if(renderer){
47118             return renderer.apply(this, arguments);
47119         }
47120         var rv = val;
47121         if(Ext.isDate(val)){
47122             rv = this.renderDate(val);
47123         }else if(typeof val == 'boolean'){
47124             rv = this.renderBool(val);
47125         }
47126         return Ext.util.Format.htmlEncode(rv);
47127     },
47128
47129     
47130     getPropertyName : function(name){
47131         var pn = this.grid.propertyNames;
47132         return pn && pn[name] ? pn[name] : name;
47133     },
47134
47135     
47136     getCellEditor : function(colIndex, rowIndex){
47137         var p = this.store.getProperty(rowIndex),
47138             n = p.data.name, 
47139             val = p.data.value;
47140         if(this.grid.customEditors[n]){
47141             return this.grid.customEditors[n];
47142         }
47143         if(Ext.isDate(val)){
47144             return this.editors.date;
47145         }else if(typeof val == 'number'){
47146             return this.editors.number;
47147         }else if(typeof val == 'boolean'){
47148             return this.editors['boolean'];
47149         }else{
47150             return this.editors.string;
47151         }
47152     },
47153
47154     
47155     destroy : function(){
47156         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
47157         for(var ed in this.editors){
47158             Ext.destroy(this.editors[ed]);
47159         }
47160     }
47161 });
47162
47163
47164 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
47165     
47166     
47167     
47168     
47169     
47170
47171     
47172     enableColumnMove:false,
47173     stripeRows:false,
47174     trackMouseOver: false,
47175     clicksToEdit:1,
47176     enableHdMenu : false,
47177     viewConfig : {
47178         forceFit:true
47179     },
47180
47181     
47182     initComponent : function(){
47183         this.customRenderers = this.customRenderers || {};
47184         this.customEditors = this.customEditors || {};
47185         this.lastEditRow = null;
47186         var store = new Ext.grid.PropertyStore(this);
47187         this.propStore = store;
47188         var cm = new Ext.grid.PropertyColumnModel(this, store);
47189         store.store.sort('name', 'ASC');
47190         this.addEvents(
47191             
47192             'beforepropertychange',
47193             
47194             'propertychange'
47195         );
47196         this.cm = cm;
47197         this.ds = store.store;
47198         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
47199
47200                 this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
47201             if(colIndex === 0){
47202                 this.startEditing.defer(200, this, [rowIndex, 1]);
47203                 return false;
47204             }
47205         }, this);
47206     },
47207
47208     
47209     onRender : function(){
47210         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
47211
47212         this.getGridEl().addClass('x-props-grid');
47213     },
47214
47215     
47216     afterRender: function(){
47217         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
47218         if(this.source){
47219             this.setSource(this.source);
47220         }
47221     },
47222
47223     
47224     setSource : function(source){
47225         this.propStore.setSource(source);
47226     },
47227
47228     
47229     getSource : function(){
47230         return this.propStore.getSource();
47231     },
47232     
47233     
47234     setProperty : function(prop, value, create){
47235         this.propStore.setValue(prop, value, create);    
47236     },
47237     
47238     
47239     removeProperty : function(prop){
47240         this.propStore.remove(prop);
47241     }
47242
47243     
47244     
47245     
47246     
47247 });
47248 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
47249
47250 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
47251
47252     
47253     groupByText : 'Group By This Field',
47254     
47255     showGroupsText : 'Show in Groups',
47256     
47257     hideGroupedColumn : false,
47258     
47259     showGroupName : true,
47260     
47261     startCollapsed : false,
47262     
47263     enableGrouping : true,
47264     
47265     enableGroupingMenu : true,
47266     
47267     enableNoGroups : true,
47268     
47269     emptyGroupText : '(None)',
47270     
47271     ignoreAdd : false,
47272     
47273     groupTextTpl : '{text}',
47274
47275     
47276     groupMode: 'value',
47277
47278     
47279
47280     
47281     initTemplates : function(){
47282         Ext.grid.GroupingView.superclass.initTemplates.call(this);
47283         this.state = {};
47284
47285         var sm = this.grid.getSelectionModel();
47286         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
47287                 this.onBeforeRowSelect, this);
47288
47289         if(!this.startGroup){
47290             this.startGroup = new Ext.XTemplate(
47291                 '<div id="{groupId}" class="x-grid-group {cls}">',
47292                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
47293                     '<div id="{groupId}-bd" class="x-grid-group-body">'
47294             );
47295         }
47296         this.startGroup.compile();
47297
47298         if (!this.endGroup) {
47299             this.endGroup = '</div></div>';
47300         }
47301     },
47302
47303     
47304     findGroup : function(el){
47305         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
47306     },
47307
47308     
47309     getGroups : function(){
47310         return this.hasRows() ? this.mainBody.dom.childNodes : [];
47311     },
47312
47313     
47314     onAdd : function(ds, records, index) {
47315         if (this.canGroup() && !this.ignoreAdd) {
47316             var ss = this.getScrollState();
47317             this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
47318             this.refresh();
47319             this.restoreScroll(ss);
47320             this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
47321         } else if (!this.canGroup()) {
47322             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
47323         }
47324     },
47325
47326     
47327     onRemove : function(ds, record, index, isUpdate){
47328         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
47329         var g = document.getElementById(record._groupId);
47330         if(g && g.childNodes[1].childNodes.length < 1){
47331             Ext.removeNode(g);
47332         }
47333         this.applyEmptyText();
47334     },
47335
47336     
47337     refreshRow : function(record){
47338         if(this.ds.getCount()==1){
47339             this.refresh();
47340         }else{
47341             this.isUpdating = true;
47342             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
47343             this.isUpdating = false;
47344         }
47345     },
47346
47347     
47348     beforeMenuShow : function(){
47349         var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
47350         if((item = items.get('groupBy'))){
47351             item.setDisabled(disabled);
47352         }
47353         if((item = items.get('showGroups'))){
47354             item.setDisabled(disabled);
47355             item.setChecked(this.enableGrouping, true);
47356         }
47357     },
47358
47359     
47360     renderUI : function(){
47361         Ext.grid.GroupingView.superclass.renderUI.call(this);
47362         this.mainBody.on('mousedown', this.interceptMouse, this);
47363
47364         if(this.enableGroupingMenu && this.hmenu){
47365             this.hmenu.add('-',{
47366                 itemId:'groupBy',
47367                 text: this.groupByText,
47368                 handler: this.onGroupByClick,
47369                 scope: this,
47370                 iconCls:'x-group-by-icon'
47371             });
47372             if(this.enableNoGroups){
47373                 this.hmenu.add({
47374                     itemId:'showGroups',
47375                     text: this.showGroupsText,
47376                     checked: true,
47377                     checkHandler: this.onShowGroupsClick,
47378                     scope: this
47379                 });
47380             }
47381             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
47382         }
47383     },
47384
47385     processEvent: function(name, e){
47386         Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
47387         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
47388         if(hd){
47389             
47390             var field = this.getGroupField(),
47391                 prefix = this.getPrefix(field),
47392                 groupValue = hd.id.substring(prefix.length);
47393
47394             
47395             groupValue = groupValue.substr(0, groupValue.length - 3);
47396             if(groupValue){
47397                 this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
47398             }
47399         }
47400
47401     },
47402
47403     
47404     onGroupByClick : function(){
47405         this.enableGrouping = true;
47406         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
47407         this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());
47408         this.beforeMenuShow(); 
47409         this.refresh();
47410     },
47411
47412     
47413     onShowGroupsClick : function(mi, checked){
47414         this.enableGrouping = checked;
47415         if(checked){
47416             this.onGroupByClick();
47417         }else{
47418             this.grid.store.clearGrouping();
47419             this.grid.fireEvent('groupchange', this, null);
47420         }
47421     },
47422
47423     
47424     toggleRowIndex : function(rowIndex, expanded){
47425         if(!this.canGroup()){
47426             return;
47427         }
47428         var row = this.getRow(rowIndex);
47429         if(row){
47430             this.toggleGroup(this.findGroup(row), expanded);
47431         }
47432     },
47433
47434     
47435     toggleGroup : function(group, expanded){
47436         var gel = Ext.get(group);
47437         expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
47438         if(this.state[gel.id] !== expanded){
47439             this.grid.stopEditing(true);
47440             this.state[gel.id] = expanded;
47441             gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
47442         }
47443     },
47444
47445     
47446     toggleAllGroups : function(expanded){
47447         var groups = this.getGroups();
47448         for(var i = 0, len = groups.length; i < len; i++){
47449             this.toggleGroup(groups[i], expanded);
47450         }
47451     },
47452
47453     
47454     expandAllGroups : function(){
47455         this.toggleAllGroups(true);
47456     },
47457
47458     
47459     collapseAllGroups : function(){
47460         this.toggleAllGroups(false);
47461     },
47462
47463     
47464     interceptMouse : function(e){
47465         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
47466         if(hd){
47467             e.stopEvent();
47468             this.toggleGroup(hd.parentNode);
47469         }
47470     },
47471
47472     
47473     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
47474         var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
47475         if(g === '' || g === '&#160;'){
47476             g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
47477         }
47478         return g;
47479     },
47480
47481     
47482     getGroupField : function(){
47483         return this.grid.store.getGroupState();
47484     },
47485
47486     
47487     afterRender : function(){
47488         if(!this.ds || !this.cm){
47489             return;
47490         }
47491         Ext.grid.GroupingView.superclass.afterRender.call(this);
47492         if(this.grid.deferRowRender){
47493             this.updateGroupWidths();
47494         }
47495     },
47496
47497     
47498     renderRows : function(){
47499         var groupField = this.getGroupField();
47500         var eg = !!groupField;
47501         
47502         if(this.hideGroupedColumn) {
47503             var colIndex = this.cm.findColumnIndex(groupField),
47504                 hasLastGroupField = Ext.isDefined(this.lastGroupField);
47505             if(!eg && hasLastGroupField){
47506                 this.mainBody.update('');
47507                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
47508                 delete this.lastGroupField;
47509             }else if (eg && !hasLastGroupField){
47510                 this.lastGroupField = groupField;
47511                 this.cm.setHidden(colIndex, true);
47512             }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
47513                 this.mainBody.update('');
47514                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
47515                 this.cm.setHidden(oldIndex, false);
47516                 this.lastGroupField = groupField;
47517                 this.cm.setHidden(colIndex, true);
47518             }
47519         }
47520         return Ext.grid.GroupingView.superclass.renderRows.apply(
47521                     this, arguments);
47522     },
47523
47524     
47525     doRender : function(cs, rs, ds, startRow, colCount, stripe){
47526         if(rs.length < 1){
47527             return '';
47528         }
47529
47530         if(!this.canGroup() || this.isUpdating){
47531             return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
47532         }
47533
47534         var groupField = this.getGroupField(),
47535             colIndex = this.cm.findColumnIndex(groupField),
47536             g,
47537             gstyle = 'width:' + this.getTotalWidth() + ';',
47538             cfg = this.cm.config[colIndex],
47539             groupRenderer = cfg.groupRenderer || cfg.renderer,
47540             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
47541             groups = [],
47542             curGroup, i, len, gid;
47543
47544         for(i = 0, len = rs.length; i < len; i++){
47545             var rowIndex = startRow + i,
47546                 r = rs[i],
47547                 gvalue = r.data[groupField];
47548
47549                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
47550             if(!curGroup || curGroup.group != g){
47551                 gid = this.constructId(gvalue, groupField, colIndex);
47552                 
47553                 
47554                 this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
47555                 curGroup = {
47556                     group: g,
47557                     gvalue: gvalue,
47558                     text: prefix + g,
47559                     groupId: gid,
47560                     startRow: rowIndex,
47561                     rs: [r],
47562                     cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
47563                     style: gstyle
47564                 };
47565                 groups.push(curGroup);
47566             }else{
47567                 curGroup.rs.push(r);
47568             }
47569             r._groupId = gid;
47570         }
47571
47572         var buf = [];
47573         for(i = 0, len = groups.length; i < len; i++){
47574             g = groups[i];
47575             this.doGroupStart(buf, g, cs, ds, colCount);
47576             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
47577                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
47578
47579             this.doGroupEnd(buf, g, cs, ds, colCount);
47580         }
47581         return buf.join('');
47582     },
47583
47584     
47585     getGroupId : function(value){
47586         var field = this.getGroupField();
47587         return this.constructId(value, field, this.cm.findColumnIndex(field));
47588     },
47589
47590     
47591     constructId : function(value, field, idx){
47592         var cfg = this.cm.config[idx],
47593             groupRenderer = cfg.groupRenderer || cfg.renderer,
47594             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
47595
47596         return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
47597     },
47598
47599     
47600     canGroup  : function(){
47601         return this.enableGrouping && !!this.getGroupField();
47602     },
47603
47604     
47605     getPrefix: function(field){
47606         return this.grid.getGridEl().id + '-gp-' + field + '-';
47607     },
47608
47609     
47610     doGroupStart : function(buf, g, cs, ds, colCount){
47611         buf[buf.length] = this.startGroup.apply(g);
47612     },
47613
47614     
47615     doGroupEnd : function(buf, g, cs, ds, colCount){
47616         buf[buf.length] = this.endGroup;
47617     },
47618
47619     
47620     getRows : function(){
47621         if(!this.canGroup()){
47622             return Ext.grid.GroupingView.superclass.getRows.call(this);
47623         }
47624         var r = [],
47625             gs = this.getGroups(),
47626             g,
47627             i = 0,
47628             len = gs.length,
47629             j,
47630             jlen;
47631         for(; i < len; ++i){
47632             g = gs[i].childNodes[1];
47633             if(g){
47634                 g = g.childNodes;
47635                 for(j = 0, jlen = g.length; j < jlen; ++j){
47636                     r[r.length] = g[j];
47637                 }
47638             }
47639         }
47640         return r;
47641     },
47642
47643     
47644     updateGroupWidths : function(){
47645         if(!this.canGroup() || !this.hasRows()){
47646             return;
47647         }
47648         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
47649         var gs = this.getGroups();
47650         for(var i = 0, len = gs.length; i < len; i++){
47651             gs[i].firstChild.style.width = tw;
47652         }
47653     },
47654
47655     
47656     onColumnWidthUpdated : function(col, w, tw){
47657         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
47658         this.updateGroupWidths();
47659     },
47660
47661     
47662     onAllColumnWidthsUpdated : function(ws, tw){
47663         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
47664         this.updateGroupWidths();
47665     },
47666
47667     
47668     onColumnHiddenUpdated : function(col, hidden, tw){
47669         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
47670         this.updateGroupWidths();
47671     },
47672
47673     
47674     onLayout : function(){
47675         this.updateGroupWidths();
47676     },
47677
47678     
47679     onBeforeRowSelect : function(sm, rowIndex){
47680         this.toggleRowIndex(rowIndex, true);
47681     }
47682 });
47683
47684 Ext.grid.GroupingView.GROUP_ID = 1000;