Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[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             cn;
37
38         if(typeof o == "string"){
39             b = o;
40         } else if (Ext.isArray(o)) {
41             for (var i=0; i < o.length; i++) {
42                 if(o[i]) {
43                     b += createHtml(o[i]);
44                 }
45             };
46         } else {
47             b += '<' + (o.tag = o.tag || 'div');
48             for (attr in o) {
49                 val = o[attr];
50                 if(!confRe.test(attr)){
51                     if (typeof val == "object") {
52                         b += ' ' + attr + '="';
53                         for (key in val) {
54                             b += key + ':' + val[key] + ';';
55                         };
56                         b += '"';
57                     }else{
58                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
59                     }
60                 }
61             };
62             
63             if (emptyTags.test(o.tag)) {
64                 b += '/>';
65             } else {
66                 b += '>';
67                 if ((cn = o.children || o.cn)) {
68                     b += createHtml(cn);
69                 } else if(o.html){
70                     b += o.html;
71                 }
72                 b += '</' + o.tag + '>';
73             }
74         }
75         return b;
76     }
77
78     function ieTable(depth, s, h, e){
79         tempTableEl.innerHTML = [s, h, e].join('');
80         var i = -1,
81             el = tempTableEl,
82             ns;
83         while(++i < depth){
84             el = el.firstChild;
85         }
86
87         if(ns = el.nextSibling){
88             var df = document.createDocumentFragment();
89             while(el){
90                 ns = el.nextSibling;
91                 df.appendChild(el);
92                 el = ns;
93             }
94             el = df;
95         }
96         return el;
97     }
98
99     
100     function insertIntoTable(tag, where, el, html) {
101         var node,
102             before;
103
104         tempTableEl = tempTableEl || document.createElement('div');
105
106         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
107            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
108             return;
109         }
110         before = where == beforebegin ? el :
111                  where == afterend ? el.nextSibling :
112                  where == afterbegin ? el.firstChild : null;
113
114         if (where == beforebegin || where == afterend) {
115             el = el.parentNode;
116         }
117
118         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
119             node = ieTable(4, trs, html, tre);
120         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
121                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
122             node = ieTable(3, tbs, html, tbe);
123         } else {
124             node = ieTable(2, ts, html, te);
125         }
126         el.insertBefore(node, before);
127         return node;
128     }
129
130
131     pub = {
132         
133         markup : function(o){
134             return createHtml(o);
135         },
136
137         
138         applyStyles : function(el, styles){
139             if (styles) {
140                 var matches;
141
142                 el = Ext.fly(el);
143                 if (typeof styles == "function") {
144                     styles = styles.call();
145                 }
146                 if (typeof styles == "string") {
147                     while ((matches = cssRe.exec(styles))) {
148                         el.setStyle(matches[1], matches[2]);
149                     }
150                 } else if (typeof styles == "object") {
151                     el.setStyle(styles);
152                 }
153             }
154         },
155
156         
157         insertHtml : function(where, el, html){
158             var hash = {},
159                 hashVal,
160                 setStart,
161                 range,
162                 frag,
163                 rangeEl,
164                 rs;
165
166             where = where.toLowerCase();
167             
168             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
169             hash[afterend] = ['AfterEnd', 'nextSibling'];
170
171             if (el.insertAdjacentHTML) {
172                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
173                     return rs;
174                 }
175                 
176                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
177                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
178                 if ((hashVal = hash[where])) {
179                     el.insertAdjacentHTML(hashVal[0], html);
180                     return el[hashVal[1]];
181                 }
182             } else {
183                 range = el.ownerDocument.createRange();
184                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
185                 if (hash[where]) {
186                     range[setStart](el);
187                     frag = range.createContextualFragment(html);
188                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
189                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
190                 } else {
191                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
192                     if (el.firstChild) {
193                         range[setStart](el[rangeEl]);
194                         frag = range.createContextualFragment(html);
195                         if(where == afterbegin){
196                             el.insertBefore(frag, el.firstChild);
197                         }else{
198                             el.appendChild(frag);
199                         }
200                     } else {
201                         el.innerHTML = html;
202                     }
203                     return el[rangeEl];
204                 }
205             }
206             throw 'Illegal insertion point -> "' + where + '"';
207         },
208
209         
210         insertBefore : function(el, o, returnElement){
211             return doInsert(el, o, returnElement, beforebegin);
212         },
213
214         
215         insertAfter : function(el, o, returnElement){
216             return doInsert(el, o, returnElement, afterend, 'nextSibling');
217         },
218
219         
220         insertFirst : function(el, o, returnElement){
221             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
222         },
223
224         
225         append : function(el, o, returnElement){
226             return doInsert(el, o, returnElement, beforeend, '', true);
227         },
228
229         
230         overwrite : function(el, o, returnElement){
231             el = Ext.getDom(el);
232             el.innerHTML = createHtml(o);
233             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
234         },
235
236         createHtml : createHtml
237     };
238     return pub;
239 }();
240
241 Ext.apply(Ext.DomHelper,
242 function(){
243     var pub,
244         afterbegin = 'afterbegin',
245         afterend = 'afterend',
246         beforebegin = 'beforebegin',
247         beforeend = 'beforeend',
248         confRe = /tag|children|cn|html$/i;
249
250     
251     function doInsert(el, o, returnElement, pos, sibling, append){
252         el = Ext.getDom(el);
253         var newNode;
254         if (pub.useDom) {
255             newNode = createDom(o, null);
256             if (append) {
257                 el.appendChild(newNode);
258             } else {
259                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
260             }
261         } else {
262             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
263         }
264         return returnElement ? Ext.get(newNode, true) : newNode;
265     }
266
267     
268     
269     function createDom(o, parentNode){
270         var el,
271             doc = document,
272             useSet,
273             attr,
274             val,
275             cn;
276
277         if (Ext.isArray(o)) {                       
278             el = doc.createDocumentFragment(); 
279             for (var i = 0, l = o.length; i < l; i++) {
280                 createDom(o[i], el);
281             }
282         } else if (typeof o == 'string') {         
283             el = doc.createTextNode(o);
284         } else {
285             el = doc.createElement( o.tag || 'div' );
286             useSet = !!el.setAttribute; 
287             for (var attr in o) {
288                 if(!confRe.test(attr)){
289                     val = o[attr];
290                     if(attr == 'cls'){
291                         el.className = val;
292                     }else{
293                         if(useSet){
294                             el.setAttribute(attr, val);
295                         }else{
296                             el[attr] = val;
297                         }
298                     }
299                 }
300             }
301             Ext.DomHelper.applyStyles(el, o.style);
302
303             if ((cn = o.children || o.cn)) {
304                 createDom(cn, el);
305             } else if (o.html) {
306                 el.innerHTML = o.html;
307             }
308         }
309         if(parentNode){
310            parentNode.appendChild(el);
311         }
312         return el;
313     }
314
315     pub = {
316         
317         createTemplate : function(o){
318             var html = Ext.DomHelper.createHtml(o);
319             return new Ext.Template(html);
320         },
321
322         
323         useDom : false,
324
325         
326         insertBefore : function(el, o, returnElement){
327             return doInsert(el, o, returnElement, beforebegin);
328         },
329
330         
331         insertAfter : function(el, o, returnElement){
332             return doInsert(el, o, returnElement, afterend, 'nextSibling');
333         },
334
335         
336         insertFirst : function(el, o, returnElement){
337             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
338         },
339
340         
341         append: function(el, o, returnElement){
342             return doInsert(el, o, returnElement, beforeend, '', true);
343         },
344
345         
346         createDom: createDom
347     };
348     return pub;
349 }());
350
351 Ext.Template = function(html){
352     var me = this,
353         a = arguments,
354         buf = [],
355         v;
356
357     if (Ext.isArray(html)) {
358         html = html.join("");
359     } else if (a.length > 1) {
360         for(var i = 0, len = a.length; i < len; i++){
361             v = a[i];
362             if(typeof v == 'object'){
363                 Ext.apply(me, v);
364             } else {
365                 buf.push(v);
366             }
367         };
368         html = buf.join('');
369     }
370
371     
372     me.html = html;
373     
374     if (me.compiled) {
375         me.compile();
376     }
377 };
378 Ext.Template.prototype = {
379     
380     re : /\{([\w-]+)\}/g,
381     
382
383     
384     applyTemplate : function(values){
385         var me = this;
386
387         return me.compiled ?
388                 me.compiled(values) :
389                 me.html.replace(me.re, function(m, name){
390                     return values[name] !== undefined ? values[name] : "";
391                 });
392     },
393
394     
395     set : function(html, compile){
396         var me = this;
397         me.html = html;
398         me.compiled = null;
399         return compile ? me.compile() : me;
400     },
401
402     
403     compile : function(){
404         var me = this,
405             sep = Ext.isGecko ? "+" : ",";
406
407         function fn(m, name){
408             name = "values['" + name + "']";
409             return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
410         }
411
412         eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
413              me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
414              (Ext.isGecko ?  "';};" : "'].join('');};"));
415         return me;
416     },
417
418     
419     insertFirst: function(el, values, returnElement){
420         return this.doInsert('afterBegin', el, values, returnElement);
421     },
422
423     
424     insertBefore: function(el, values, returnElement){
425         return this.doInsert('beforeBegin', el, values, returnElement);
426     },
427
428     
429     insertAfter : function(el, values, returnElement){
430         return this.doInsert('afterEnd', el, values, returnElement);
431     },
432
433     
434     append : function(el, values, returnElement){
435         return this.doInsert('beforeEnd', el, values, returnElement);
436     },
437
438     doInsert : function(where, el, values, returnEl){
439         el = Ext.getDom(el);
440         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
441         return returnEl ? Ext.get(newNode, true) : newNode;
442     },
443
444     
445     overwrite : function(el, values, returnElement){
446         el = Ext.getDom(el);
447         el.innerHTML = this.applyTemplate(values);
448         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
449     }
450 };
451
452 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
453
454
455 Ext.Template.from = function(el, config){
456     el = Ext.getDom(el);
457     return new Ext.Template(el.value || el.innerHTML, config || '');
458 };
459
460 Ext.apply(Ext.Template.prototype, {
461     
462     disableFormats : false,
463     
464
465     
466     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
467     argsRe : /^\s*['"](.*)["']\s*$/,
468     compileARe : /\\/g,
469     compileBRe : /(\r\n|\n)/g,
470     compileCRe : /'/g,
471
472     /**
473      * Returns an HTML fragment of this template with the specified values applied.
474      * @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'})
475      * @return {String} The HTML fragment
476      * @hide repeat doc
477      */
478     applyTemplate : function(values){
479         var me = this,
480             useF = me.disableFormats !== true,
481             fm = Ext.util.Format,
482             tpl = me;
483
484         if(me.compiled){
485             return me.compiled(values);
486         }
487         function fn(m, name, format, args){
488             if (format && useF) {
489                 if (format.substr(0, 5) == "this.") {
490                     return tpl.call(format.substr(5), values[name], values);
491                 } else {
492                     if (args) {
493                         // quoted values are required for strings in compiled templates,
494                         // but for non compiled we need to strip them
495                         // quoted reversed for jsmin
496                         var re = me.argsRe;
497                         args = args.split(',');
498                         for(var i = 0, len = args.length; i < len; i++){
499                             args[i] = args[i].replace(re, "$1");
500                         }
501                         args = [values[name]].concat(args);
502                     } else {
503                         args = [values[name]];
504                     }
505                     return fm[format].apply(fm, args);
506                 }
507             } else {
508                 return values[name] !== undefined ? values[name] : "";
509             }
510         }
511         return me.html.replace(me.re, fn);
512     },
513
514     /**
515      * Compiles the template into an internal function, eliminating the RegEx overhead.
516      * @return {Ext.Template} this
517      * @hide repeat doc
518      */
519     compile : function(){
520         var me = this,
521             fm = Ext.util.Format,
522             useF = me.disableFormats !== true,
523             sep = Ext.isGecko ? "+" : ",",
524             body;
525
526         function fn(m, name, format, args){
527             if(format && useF){
528                 args = args ? ',' + args : "";
529                 if(format.substr(0, 5) != "this."){
530                     format = "fm." + format + '(';
531                 }else{
532                     format = 'this.call("'+ format.substr(5) + '", ';
533                     args = ", values";
534                 }
535             }else{
536                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
537             }
538             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
539         }
540
541         // branched to use + in gecko and [].join() in others
542         if(Ext.isGecko){
543             body = "this.compiled = function(values){ return '" +
544                    me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
545                     "';};";
546         }else{
547             body = ["this.compiled = function(values){ return ['"];
548             body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
549             body.push("'].join('');};");
550             body = body.join('');
551         }
552         eval(body);
553         return me;
554     },
555
556     // private function used to call members
557     call : function(fnName, value, allValues){
558         return this[fnName](value, allValues);
559     }
560 });
561 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
562 /*
563  * This is code is also distributed under MIT license for use
564  * with jQuery and prototype JavaScript libraries.
565  */
566 /**
567  * @class Ext.DomQuery
568 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).
569 <p>
570 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>
571
572 <p>
573 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.
574 </p>
575 <h4>Element Selectors:</h4>
576 <ul class="list">
577     <li> <b>*</b> any element</li>
578     <li> <b>E</b> an element with the tag E</li>
579     <li> <b>E F</b> All descendent elements of E that have the tag F</li>
580     <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
581     <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
582     <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
583 </ul>
584 <h4>Attribute Selectors:</h4>
585 <p>The use of &#64; and quotes are optional. For example, div[&#64;foo='bar'] is also a valid attribute selector.</p>
586 <ul class="list">
587     <li> <b>E[foo]</b> has an attribute "foo"</li>
588     <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
589     <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
590     <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
591     <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
592     <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
593     <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
594 </ul>
595 <h4>Pseudo Classes:</h4>
596 <ul class="list">
597     <li> <b>E:first-child</b> E is the first child of its parent</li>
598     <li> <b>E:last-child</b> E is the last child of its parent</li>
599     <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>
600     <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
601     <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
602     <li> <b>E:only-child</b> E is the only child of its parent</li>
603     <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>
604     <li> <b>E:first</b> the first E in the resultset</li>
605     <li> <b>E:last</b> the last E in the resultset</li>
606     <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
607     <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
608     <li> <b>E:even</b> shortcut for :nth-child(even)</li>
609     <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
610     <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
611     <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
612     <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
613     <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
614     <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
615     <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3
616 </ul>
617 <h4>CSS Value Selectors:</h4>
618 <ul class="list">
619     <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
620     <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
621     <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
622     <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
623     <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
624     <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
625 </ul>
626  * @singleton
627  */
628 Ext.DomQuery = function(){
629     var cache = {}, 
630         simpleCache = {}, 
631         valueCache = {},
632         nonSpace = /\S/,
633         trimRe = /^\s+|\s+$/g,
634         tplRe = /\{(\d+)\}/g,
635         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
636         tagTokenRe = /^(#)?([\w-\*]+)/,
637         nthRe = /(\d*)n\+?(\d*)/, 
638         nthRe2 = /\D/,
639         
640         
641         
642         isIE = window.ActiveXObject ? true : false,
643         key = 30803;
644     
645     
646     
647     eval("var batch = 30803;");         
648
649     
650     
651     function child(parent, index){
652         var i = 0,
653             n = parent.firstChild;
654         while(n){
655             if(n.nodeType == 1){
656                if(++i == index){
657                    return n;
658                }
659             }
660             n = n.nextSibling;
661         }
662         return null;
663     }
664
665     
666     function next(n){   
667         while((n = n.nextSibling) && n.nodeType != 1);
668         return n;
669     }
670
671     
672     function prev(n){
673         while((n = n.previousSibling) && n.nodeType != 1);
674         return n;
675     }
676
677     
678     
679     function children(parent){
680         var n = parent.firstChild,
681             nodeIndex = -1,
682             nextNode;
683         while(n){
684             nextNode = n.nextSibling;
685             
686             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
687                 parent.removeChild(n);
688             }else{
689                 
690                 n.nodeIndex = ++nodeIndex;
691             }
692             n = nextNode;
693         }
694         return this;
695     }
696
697
698     
699     
700     function byClassName(nodeSet, cls){
701         if(!cls){
702             return nodeSet;
703         }
704         var result = [], ri = -1;
705         for(var i = 0, ci; ci = nodeSet[i]; i++){
706             if((' '+ci.className+' ').indexOf(cls) != -1){
707                 result[++ri] = ci;
708             }
709         }
710         return result;
711     };
712
713     function attrValue(n, attr){
714         
715         if(!n.tagName && typeof n.length != "undefined"){
716             n = n[0];
717         }
718         if(!n){
719             return null;
720         }
721
722         if(attr == "for"){
723             return n.htmlFor;
724         }
725         if(attr == "class" || attr == "className"){
726             return n.className;
727         }
728         return n.getAttribute(attr) || n[attr];
729
730     };
731
732
733     
734     
735     
736     function getNodes(ns, mode, tagName){
737         var result = [], ri = -1, cs;
738         if(!ns){
739             return result;
740         }
741         tagName = tagName || "*";
742         
743         if(typeof ns.getElementsByTagName != "undefined"){
744             ns = [ns];
745         }
746         
747         
748         
749         if(!mode){
750             for(var i = 0, ni; ni = ns[i]; i++){
751                 cs = ni.getElementsByTagName(tagName);
752                 for(var j = 0, ci; ci = cs[j]; j++){
753                     result[++ri] = ci;
754                 }
755             }
756         
757         
758         } else if(mode == "/" || mode == ">"){
759             var utag = tagName.toUpperCase();
760             for(var i = 0, ni, cn; ni = ns[i]; i++){
761                 cn = ni.childNodes;
762                 for(var j = 0, cj; cj = cn[j]; j++){
763                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
764                         result[++ri] = cj;
765                     }
766                 }
767             }
768         
769         
770         }else if(mode == "+"){
771             var utag = tagName.toUpperCase();
772             for(var i = 0, n; n = ns[i]; i++){
773                 while((n = n.nextSibling) && n.nodeType != 1);
774                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
775                     result[++ri] = n;
776                 }
777             }
778         
779         
780         }else if(mode == "~"){
781             var utag = tagName.toUpperCase();
782             for(var i = 0, n; n = ns[i]; i++){
783                 while((n = n.nextSibling)){
784                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
785                         result[++ri] = n;
786                     }
787                 }
788             }
789         }
790         return result;
791     }
792
793     function concat(a, b){
794         if(b.slice){
795             return a.concat(b);
796         }
797         for(var i = 0, l = b.length; i < l; i++){
798             a[a.length] = b[i];
799         }
800         return a;
801     }
802
803     function byTag(cs, tagName){
804         if(cs.tagName || cs == document){
805             cs = [cs];
806         }
807         if(!tagName){
808             return cs;
809         }
810         var result = [], ri = -1;
811         tagName = tagName.toLowerCase();
812         for(var i = 0, ci; ci = cs[i]; i++){
813             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
814                 result[++ri] = ci;
815             }
816         }
817         return result;
818     }
819
820     function byId(cs, id){
821         if(cs.tagName || cs == document){
822             cs = [cs];
823         }
824         if(!id){
825             return cs;
826         }
827         var result = [], ri = -1;
828         for(var i = 0, ci; ci = cs[i]; i++){
829             if(ci && ci.id == id){
830                 result[++ri] = ci;
831                 return result;
832             }
833         }
834         return result;
835     }
836
837     
838     
839     function byAttribute(cs, attr, value, op, custom){
840         var result = [], 
841             ri = -1, 
842             useGetStyle = custom == "{",            
843             fn = Ext.DomQuery.operators[op],        
844             a,
845             xml,
846             hasXml;
847             
848         for(var i = 0, ci; ci = cs[i]; i++){
849             
850             if(ci.nodeType != 1){
851                 continue;
852             }
853             
854             if(!hasXml){
855                 xml = Ext.DomQuery.isXml(ci);
856                 hasXml = true;
857             }
858             
859             
860             if(!xml){
861                 if(useGetStyle){
862                     a = Ext.DomQuery.getStyle(ci, attr);
863                 } else if (attr == "class" || attr == "className"){
864                     a = ci.className;
865                 } else if (attr == "for"){
866                     a = ci.htmlFor;
867                 } else if (attr == "href"){
868                     
869                     
870                     a = ci.getAttribute("href", 2);
871                 } else{
872                     a = ci.getAttribute(attr);
873                 }
874             }else{
875                 a = ci.getAttribute(attr);
876             }
877             if((fn && fn(a, value)) || (!fn && a)){
878                 result[++ri] = ci;
879             }
880         }
881         return result;
882     }
883
884     function byPseudo(cs, name, value){
885         return Ext.DomQuery.pseudos[name](cs, value);
886     }
887
888     function nodupIEXml(cs){
889         var d = ++key, 
890             r;
891         cs[0].setAttribute("_nodup", d);
892         r = [cs[0]];
893         for(var i = 1, len = cs.length; i < len; i++){
894             var c = cs[i];
895             if(!c.getAttribute("_nodup") != d){
896                 c.setAttribute("_nodup", d);
897                 r[r.length] = c;
898             }
899         }
900         for(var i = 0, len = cs.length; i < len; i++){
901             cs[i].removeAttribute("_nodup");
902         }
903         return r;
904     }
905
906     function nodup(cs){
907         if(!cs){
908             return [];
909         }
910         var len = cs.length, c, i, r = cs, cj, ri = -1;
911         if(!len || typeof cs.nodeType != "undefined" || len == 1){
912             return cs;
913         }
914         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
915             return nodupIEXml(cs);
916         }
917         var d = ++key;
918         cs[0]._nodup = d;
919         for(i = 1; c = cs[i]; i++){
920             if(c._nodup != d){
921                 c._nodup = d;
922             }else{
923                 r = [];
924                 for(var j = 0; j < i; j++){
925                     r[++ri] = cs[j];
926                 }
927                 for(j = i+1; cj = cs[j]; j++){
928                     if(cj._nodup != d){
929                         cj._nodup = d;
930                         r[++ri] = cj;
931                     }
932                 }
933                 return r;
934             }
935         }
936         return r;
937     }
938
939     function quickDiffIEXml(c1, c2){
940         var d = ++key,
941             r = [];
942         for(var i = 0, len = c1.length; i < len; i++){
943             c1[i].setAttribute("_qdiff", d);
944         }        
945         for(var i = 0, len = c2.length; i < len; i++){
946             if(c2[i].getAttribute("_qdiff") != d){
947                 r[r.length] = c2[i];
948             }
949         }
950         for(var i = 0, len = c1.length; i < len; i++){
951            c1[i].removeAttribute("_qdiff");
952         }
953         return r;
954     }
955
956     function quickDiff(c1, c2){
957         var len1 = c1.length,
958                 d = ++key,
959                 r = [];
960         if(!len1){
961             return c2;
962         }
963         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
964             return quickDiffIEXml(c1, c2);
965         }        
966         for(var i = 0; i < len1; i++){
967             c1[i]._qdiff = d;
968         }        
969         for(var i = 0, len = c2.length; i < len; i++){
970             if(c2[i]._qdiff != d){
971                 r[r.length] = c2[i];
972             }
973         }
974         return r;
975     }
976
977     function quickId(ns, mode, root, id){
978         if(ns == root){
979            var d = root.ownerDocument || root;
980            return d.getElementById(id);
981         }
982         ns = getNodes(ns, mode, "*");
983         return byId(ns, id);
984     }
985
986     return {
987         getStyle : function(el, name){
988             return Ext.fly(el).getStyle(name);
989         },
990         
991         compile : function(path, type){
992             type = type || "select";
993
994             
995             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
996                         mode,           
997                         lastPath,
998                 matchers = Ext.DomQuery.matchers,
999                 matchersLn = matchers.length,
1000                 modeMatch,
1001                 
1002                 lmode = path.match(modeRe);
1003             
1004             if(lmode && lmode[1]){
1005                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
1006                 path = path.replace(lmode[1], "");
1007             }
1008             
1009             
1010             while(path.substr(0, 1)=="/"){
1011                 path = path.substr(1);
1012             }
1013
1014             while(path && lastPath != path){
1015                 lastPath = path;
1016                 var tokenMatch = path.match(tagTokenRe);
1017                 if(type == "select"){
1018                     if(tokenMatch){
1019                         
1020                         if(tokenMatch[1] == "#"){
1021                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                 
1022                         }else{
1023                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
1024                         }
1025                         path = path.replace(tokenMatch[0], "");
1026                     }else if(path.substr(0, 1) != '@'){
1027                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
1028                     }
1029                 
1030                 }else{
1031                     if(tokenMatch){
1032                         if(tokenMatch[1] == "#"){
1033                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
1034                         }else{
1035                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
1036                         }
1037                         path = path.replace(tokenMatch[0], "");
1038                     }
1039                 }
1040                 while(!(modeMatch = path.match(modeRe))){
1041                     var matched = false;
1042                     for(var j = 0; j < matchersLn; j++){
1043                         var t = matchers[j];
1044                         var m = path.match(t.re);
1045                         if(m){
1046                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
1047                                 return m[i];
1048                             });
1049                             path = path.replace(m[0], "");
1050                             matched = true;
1051                             break;
1052                         }
1053                     }
1054                     
1055                     if(!matched){
1056                         throw 'Error parsing selector, parsing failed at "' + path + '"';
1057                     }
1058                 }
1059                 if(modeMatch[1]){
1060                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
1061                     path = path.replace(modeMatch[1], "");
1062                 }
1063             }
1064             
1065             fn[fn.length] = "return nodup(n);\n}";
1066             
1067             
1068             eval(fn.join(""));
1069             return f;
1070         },
1071
1072         
1073         jsSelect: function(path, root, type){
1074             
1075             root = root || document;
1076             
1077             if(typeof root == "string"){
1078                 root = document.getElementById(root);
1079             }
1080             var paths = path.split(","),
1081                 results = [];
1082                 
1083             
1084             for(var i = 0, len = paths.length; i < len; i++){           
1085                 var subPath = paths[i].replace(trimRe, "");
1086                 
1087                 if(!cache[subPath]){
1088                     cache[subPath] = Ext.DomQuery.compile(subPath);
1089                     if(!cache[subPath]){
1090                         throw subPath + " is not a valid selector";
1091                     }
1092                 }
1093                 var result = cache[subPath](root);
1094                 if(result && result != document){
1095                     results = results.concat(result);
1096                 }
1097             }
1098             
1099             
1100             
1101             if(paths.length > 1){
1102                 return nodup(results);
1103             }
1104             return results;
1105         },
1106         isXml: function(el) {
1107             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
1108             return docEl ? docEl.nodeName !== "HTML" : false;
1109         },
1110         select : document.querySelectorAll ? function(path, root, type) {
1111             root = root || document;
1112             if (!Ext.DomQuery.isXml(root)) {
1113                 try {
1114                     var cs = root.querySelectorAll(path);
1115                     return Ext.toArray(cs);
1116                 }
1117                 catch (ex) {}           
1118             }       
1119             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1120         } : function(path, root, type) {
1121             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1122         },
1123
1124         
1125         selectNode : function(path, root){
1126             return Ext.DomQuery.select(path, root)[0];
1127         },
1128
1129         
1130         selectValue : function(path, root, defaultValue){
1131             path = path.replace(trimRe, "");
1132             if(!valueCache[path]){
1133                 valueCache[path] = Ext.DomQuery.compile(path, "select");
1134             }
1135             var n = valueCache[path](root), v;
1136             n = n[0] ? n[0] : n;
1137                     
1138             
1139             
1140             
1141             
1142             if (typeof n.normalize == 'function') n.normalize();
1143             
1144             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
1145             return ((v === null||v === undefined||v==='') ? defaultValue : v);
1146         },
1147
1148         
1149         selectNumber : function(path, root, defaultValue){
1150             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
1151             return parseFloat(v);
1152         },
1153
1154         
1155         is : function(el, ss){
1156             if(typeof el == "string"){
1157                 el = document.getElementById(el);
1158             }
1159             var isArray = Ext.isArray(el),
1160                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
1161             return isArray ? (result.length == el.length) : (result.length > 0);
1162         },
1163
1164         
1165         filter : function(els, ss, nonMatches){
1166             ss = ss.replace(trimRe, "");
1167             if(!simpleCache[ss]){
1168                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
1169             }
1170             var result = simpleCache[ss](els);
1171             return nonMatches ? quickDiff(result, els) : result;
1172         },
1173
1174         
1175         matchers : [{
1176                 re: /^\.([\w-]+)/,
1177                 select: 'n = byClassName(n, " {1} ");'
1178             }, {
1179                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
1180                 select: 'n = byPseudo(n, "{1}", "{2}");'
1181             },{
1182                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
1183                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
1184             }, {
1185                 re: /^#([\w-]+)/,
1186                 select: 'n = byId(n, "{1}");'
1187             },{
1188                 re: /^@([\w-]+)/,
1189                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
1190             }
1191         ],
1192
1193         
1194         operators : {
1195             "=" : function(a, v){
1196                 return a == v;
1197             },
1198             "!=" : function(a, v){
1199                 return a != v;
1200             },
1201             "^=" : function(a, v){
1202                 return a && a.substr(0, v.length) == v;
1203             },
1204             "$=" : function(a, v){
1205                 return a && a.substr(a.length-v.length) == v;
1206             },
1207             "*=" : function(a, v){
1208                 return a && a.indexOf(v) !== -1;
1209             },
1210             "%=" : function(a, v){
1211                 return (a % v) == 0;
1212             },
1213             "|=" : function(a, v){
1214                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
1215             },
1216             "~=" : function(a, v){
1217                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
1218             }
1219         },
1220
1221         
1222         pseudos : {
1223             "first-child" : function(c){
1224                 var r = [], ri = -1, n;
1225                 for(var i = 0, ci; ci = n = c[i]; i++){
1226                     while((n = n.previousSibling) && n.nodeType != 1);
1227                     if(!n){
1228                         r[++ri] = ci;
1229                     }
1230                 }
1231                 return r;
1232             },
1233
1234             "last-child" : function(c){
1235                 var r = [], ri = -1, n;
1236                 for(var i = 0, ci; ci = n = c[i]; i++){
1237                     while((n = n.nextSibling) && n.nodeType != 1);
1238                     if(!n){
1239                         r[++ri] = ci;
1240                     }
1241                 }
1242                 return r;
1243             },
1244
1245             "nth-child" : function(c, a) {
1246                 var r = [], ri = -1,
1247                         m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
1248                         f = (m[1] || 1) - 0, l = m[2] - 0;
1249                 for(var i = 0, n; n = c[i]; i++){
1250                     var pn = n.parentNode;
1251                     if (batch != pn._batch) {
1252                         var j = 0;
1253                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1254                             if(cn.nodeType == 1){
1255                                cn.nodeIndex = ++j;
1256                             }
1257                         }
1258                         pn._batch = batch;
1259                     }
1260                     if (f == 1) {
1261                         if (l == 0 || n.nodeIndex == l){
1262                             r[++ri] = n;
1263                         }
1264                     } else if ((n.nodeIndex + l) % f == 0){
1265                         r[++ri] = n;
1266                     }
1267                 }
1268
1269                 return r;
1270             },
1271
1272             "only-child" : function(c){
1273                 var r = [], ri = -1;;
1274                 for(var i = 0, ci; ci = c[i]; i++){
1275                     if(!prev(ci) && !next(ci)){
1276                         r[++ri] = ci;
1277                     }
1278                 }
1279                 return r;
1280             },
1281
1282             "empty" : function(c){
1283                 var r = [], ri = -1;
1284                 for(var i = 0, ci; ci = c[i]; i++){
1285                     var cns = ci.childNodes, j = 0, cn, empty = true;
1286                     while(cn = cns[j]){
1287                         ++j;
1288                         if(cn.nodeType == 1 || cn.nodeType == 3){
1289                             empty = false;
1290                             break;
1291                         }
1292                     }
1293                     if(empty){
1294                         r[++ri] = ci;
1295                     }
1296                 }
1297                 return r;
1298             },
1299
1300             "contains" : function(c, v){
1301                 var r = [], ri = -1;
1302                 for(var i = 0, ci; ci = c[i]; i++){
1303                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1304                         r[++ri] = ci;
1305                     }
1306                 }
1307                 return r;
1308             },
1309
1310             "nodeValue" : function(c, v){
1311                 var r = [], ri = -1;
1312                 for(var i = 0, ci; ci = c[i]; i++){
1313                     if(ci.firstChild && ci.firstChild.nodeValue == v){
1314                         r[++ri] = ci;
1315                     }
1316                 }
1317                 return r;
1318             },
1319
1320             "checked" : function(c){
1321                 var r = [], ri = -1;
1322                 for(var i = 0, ci; ci = c[i]; i++){
1323                     if(ci.checked == true){
1324                         r[++ri] = ci;
1325                     }
1326                 }
1327                 return r;
1328             },
1329
1330             "not" : function(c, ss){
1331                 return Ext.DomQuery.filter(c, ss, true);
1332             },
1333
1334             "any" : function(c, selectors){
1335                 var ss = selectors.split('|'),
1336                         r = [], ri = -1, s;
1337                 for(var i = 0, ci; ci = c[i]; i++){
1338                     for(var j = 0; s = ss[j]; j++){
1339                         if(Ext.DomQuery.is(ci, s)){
1340                             r[++ri] = ci;
1341                             break;
1342                         }
1343                     }
1344                 }
1345                 return r;
1346             },
1347
1348             "odd" : function(c){
1349                 return this["nth-child"](c, "odd");
1350             },
1351
1352             "even" : function(c){
1353                 return this["nth-child"](c, "even");
1354             },
1355
1356             "nth" : function(c, a){
1357                 return c[a-1] || [];
1358             },
1359
1360             "first" : function(c){
1361                 return c[0] || [];
1362             },
1363
1364             "last" : function(c){
1365                 return c[c.length-1] || [];
1366             },
1367
1368             "has" : function(c, ss){
1369                 var s = Ext.DomQuery.select,
1370                         r = [], ri = -1;
1371                 for(var i = 0, ci; ci = c[i]; i++){
1372                     if(s(ss, ci).length > 0){
1373                         r[++ri] = ci;
1374                     }
1375                 }
1376                 return r;
1377             },
1378
1379             "next" : function(c, ss){
1380                 var is = Ext.DomQuery.is,
1381                         r = [], ri = -1;
1382                 for(var i = 0, ci; ci = c[i]; i++){
1383                     var n = next(ci);
1384                     if(n && is(n, ss)){
1385                         r[++ri] = ci;
1386                     }
1387                 }
1388                 return r;
1389             },
1390
1391             "prev" : function(c, ss){
1392                 var is = Ext.DomQuery.is,
1393                         r = [], ri = -1;
1394                 for(var i = 0, ci; ci = c[i]; i++){
1395                     var n = prev(ci);
1396                     if(n && is(n, ss)){
1397                         r[++ri] = ci;
1398                     }
1399                 }
1400                 return r;
1401             }
1402         }
1403     };
1404 }();
1405
1406
1407 Ext.query = Ext.DomQuery.select;
1408
1409 Ext.util.DelayedTask = function(fn, scope, args){
1410     var me = this,
1411         id,     
1412         call = function(){
1413                 clearInterval(id);
1414                 id = null;
1415                 fn.apply(scope, args || []);
1416             };
1417             
1418     
1419     me.delay = function(delay, newFn, newScope, newArgs){
1420         me.cancel();
1421         fn = newFn || fn;
1422         scope = newScope || scope;
1423         args = newArgs || args;
1424         id = setInterval(call, delay);
1425     };
1426
1427     
1428     me.cancel = function(){
1429         if(id){
1430             clearInterval(id);
1431             id = null;
1432         }
1433     };
1434 };(function(){
1435
1436 var EXTUTIL = Ext.util,
1437     EACH = Ext.each,
1438     TRUE = true,
1439     FALSE = false;
1440
1441 EXTUTIL.Observable = function(){
1442     
1443     var me = this, e = me.events;
1444     if(me.listeners){
1445         me.on(me.listeners);
1446         delete me.listeners;
1447     }
1448     me.events = e || {};
1449 };
1450
1451 EXTUTIL.Observable.prototype = {
1452     
1453     filterOptRe : /^(?:scope|delay|buffer|single)$/,
1454
1455     
1456     fireEvent : function(){
1457         var a = Array.prototype.slice.call(arguments, 0),
1458             ename = a[0].toLowerCase(),
1459             me = this,
1460             ret = TRUE,
1461             ce = me.events[ename],
1462             cc,
1463             q,
1464             c;
1465         if (me.eventsSuspended === TRUE) {
1466             if (q = me.eventQueue) {
1467                 q.push(a);
1468             }
1469         }
1470         else if(typeof ce == 'object') {
1471             if (ce.bubble){
1472                 if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
1473                     return FALSE;
1474                 }
1475                 c = me.getBubbleTarget && me.getBubbleTarget();
1476                 if(c && c.enableBubble) {
1477                     cc = c.events[ename];
1478                     if(!cc || typeof cc != 'object' || !cc.bubble) {
1479                         c.enableBubble(ename);
1480                     }
1481                     return c.fireEvent.apply(c, a);
1482                 }
1483             }
1484             else {
1485                 a.shift();
1486                 ret = ce.fire.apply(ce, a);
1487             }
1488         }
1489         return ret;
1490     },
1491
1492     
1493     addListener : function(eventName, fn, scope, o){
1494         var me = this,
1495             e,
1496             oe,
1497             ce;
1498             
1499         if (typeof eventName == 'object') {
1500             o = eventName;
1501             for (e in o) {
1502                 oe = o[e];
1503                 if (!me.filterOptRe.test(e)) {
1504                     me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
1505                 }
1506             }
1507         } else {
1508             eventName = eventName.toLowerCase();
1509             ce = me.events[eventName] || TRUE;
1510             if (typeof ce == 'boolean') {
1511                 me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
1512             }
1513             ce.addListener(fn, scope, typeof o == 'object' ? o : {});
1514         }
1515     },
1516
1517     
1518     removeListener : function(eventName, fn, scope){
1519         var ce = this.events[eventName.toLowerCase()];
1520         if (typeof ce == 'object') {
1521             ce.removeListener(fn, scope);
1522         }
1523     },
1524
1525     
1526     purgeListeners : function(){
1527         var events = this.events,
1528             evt,
1529             key;
1530         for(key in events){
1531             evt = events[key];
1532             if(typeof evt == 'object'){
1533                 evt.clearListeners();
1534             }
1535         }
1536     },
1537
1538     
1539     addEvents : function(o){
1540         var me = this;
1541         me.events = me.events || {};
1542         if (typeof o == 'string') {
1543             var a = arguments,
1544                 i = a.length;
1545             while(i--) {
1546                 me.events[a[i]] = me.events[a[i]] || TRUE;
1547             }
1548         } else {
1549             Ext.applyIf(me.events, o);
1550         }
1551     },
1552
1553     
1554     hasListener : function(eventName){
1555         var e = this.events[eventName.toLowerCase()];
1556         return typeof e == 'object' && e.listeners.length > 0;
1557     },
1558
1559     
1560     suspendEvents : function(queueSuspended){
1561         this.eventsSuspended = TRUE;
1562         if(queueSuspended && !this.eventQueue){
1563             this.eventQueue = [];
1564         }
1565     },
1566
1567     
1568     resumeEvents : function(){
1569         var me = this,
1570             queued = me.eventQueue || [];
1571         me.eventsSuspended = FALSE;
1572         delete me.eventQueue;
1573         EACH(queued, function(e) {
1574             me.fireEvent.apply(me, e);
1575         });
1576     }
1577 };
1578
1579 var OBSERVABLE = EXTUTIL.Observable.prototype;
1580
1581 OBSERVABLE.on = OBSERVABLE.addListener;
1582
1583 OBSERVABLE.un = OBSERVABLE.removeListener;
1584
1585
1586 EXTUTIL.Observable.releaseCapture = function(o){
1587     o.fireEvent = OBSERVABLE.fireEvent;
1588 };
1589
1590 function createTargeted(h, o, scope){
1591     return function(){
1592         if(o.target == arguments[0]){
1593             h.apply(scope, Array.prototype.slice.call(arguments, 0));
1594         }
1595     };
1596 };
1597
1598 function createBuffered(h, o, l, scope){
1599     l.task = new EXTUTIL.DelayedTask();
1600     return function(){
1601         l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
1602     };
1603 };
1604
1605 function createSingle(h, e, fn, scope){
1606     return function(){
1607         e.removeListener(fn, scope);
1608         return h.apply(scope, arguments);
1609     };
1610 };
1611
1612 function createDelayed(h, o, l, scope){
1613     return function(){
1614         var task = new EXTUTIL.DelayedTask();
1615         if(!l.tasks) {
1616             l.tasks = [];
1617         }
1618         l.tasks.push(task);
1619         task.delay(o.delay || 10, h, scope, Array.prototype.slice.call(arguments, 0));
1620     };
1621 };
1622
1623 EXTUTIL.Event = function(obj, name){
1624     this.name = name;
1625     this.obj = obj;
1626     this.listeners = [];
1627 };
1628
1629 EXTUTIL.Event.prototype = {
1630     addListener : function(fn, scope, options){
1631         var me = this,
1632             l;
1633         scope = scope || me.obj;
1634         if(!me.isListening(fn, scope)){
1635             l = me.createListener(fn, scope, options);
1636             if(me.firing){ 
1637                 me.listeners = me.listeners.slice(0);
1638             }
1639             me.listeners.push(l);
1640         }
1641     },
1642
1643     createListener: function(fn, scope, o){
1644         o = o || {};
1645         scope = scope || this.obj;
1646         var l = {
1647             fn: fn,
1648             scope: scope,
1649             options: o
1650         }, h = fn;
1651         if(o.target){
1652             h = createTargeted(h, o, scope);
1653         }
1654         if(o.delay){
1655             h = createDelayed(h, o, l, scope);
1656         }
1657         if(o.single){
1658             h = createSingle(h, this, fn, scope);
1659         }
1660         if(o.buffer){
1661             h = createBuffered(h, o, l, scope);
1662         }
1663         l.fireFn = h;
1664         return l;
1665     },
1666
1667     findListener : function(fn, scope){
1668         var list = this.listeners,
1669             i = list.length,
1670             l;
1671
1672         scope = scope || this.obj;
1673         while(i--){
1674             l = list[i];
1675             if(l){
1676                 if(l.fn == fn && l.scope == scope){
1677                     return i;
1678                 }
1679             }
1680         }
1681         return -1;
1682     },
1683
1684     isListening : function(fn, scope){
1685         return this.findListener(fn, scope) != -1;
1686     },
1687
1688     removeListener : function(fn, scope){
1689         var index,
1690             l,
1691             k,
1692             me = this,
1693             ret = FALSE;
1694         if((index = me.findListener(fn, scope)) != -1){
1695             if (me.firing) {
1696                 me.listeners = me.listeners.slice(0);
1697             }
1698             l = me.listeners[index];
1699             if(l.task) {
1700                 l.task.cancel();
1701                 delete l.task;
1702             }
1703             k = l.tasks && l.tasks.length;
1704             if(k) {
1705                 while(k--) {
1706                     l.tasks[k].cancel();
1707                 }
1708                 delete l.tasks;
1709             }
1710             me.listeners.splice(index, 1);
1711             ret = TRUE;
1712         }
1713         return ret;
1714     },
1715
1716     
1717     clearListeners : function(){
1718         var me = this,
1719             l = me.listeners,
1720             i = l.length;
1721         while(i--) {
1722             me.removeListener(l[i].fn, l[i].scope);
1723         }
1724     },
1725
1726     fire : function(){
1727         var me = this,
1728             listeners = me.listeners,
1729             len = listeners.length,
1730             i = 0,
1731             l;
1732
1733         if(len > 0){
1734             me.firing = TRUE;
1735             var args = Array.prototype.slice.call(arguments, 0);
1736             for (; i < len; i++) {
1737                 l = listeners[i];
1738                 if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
1739                     return (me.firing = FALSE);
1740                 }
1741             }
1742         }
1743         me.firing = FALSE;
1744         return TRUE;
1745     }
1746
1747 };
1748 })();
1749
1750 Ext.apply(Ext.util.Observable.prototype, function(){
1751     
1752     
1753     
1754     function getMethodEvent(method){
1755         var e = (this.methodEvents = this.methodEvents ||
1756         {})[method], returnValue, v, cancel, obj = this;
1757
1758         if (!e) {
1759             this.methodEvents[method] = e = {};
1760             e.originalFn = this[method];
1761             e.methodName = method;
1762             e.before = [];
1763             e.after = [];
1764
1765             var makeCall = function(fn, scope, args){
1766                 if((v = fn.apply(scope || obj, args)) !== undefined){
1767                     if (typeof v == 'object') {
1768                         if(v.returnValue !== undefined){
1769                             returnValue = v.returnValue;
1770                         }else{
1771                             returnValue = v;
1772                         }
1773                         cancel = !!v.cancel;
1774                     }
1775                     else
1776                         if (v === false) {
1777                             cancel = true;
1778                         }
1779                         else {
1780                             returnValue = v;
1781                         }
1782                 }
1783             };
1784
1785             this[method] = function(){
1786                 var args = Array.prototype.slice.call(arguments, 0),
1787                     b;
1788                 returnValue = v = undefined;
1789                 cancel = false;
1790
1791                 for(var i = 0, len = e.before.length; i < len; i++){
1792                     b = e.before[i];
1793                     makeCall(b.fn, b.scope, args);
1794                     if (cancel) {
1795                         return returnValue;
1796                     }
1797                 }
1798
1799                 if((v = e.originalFn.apply(obj, args)) !== undefined){
1800                     returnValue = v;
1801                 }
1802
1803                 for(var i = 0, len = e.after.length; i < len; i++){
1804                     b = e.after[i];
1805                     makeCall(b.fn, b.scope, args);
1806                     if (cancel) {
1807                         return returnValue;
1808                     }
1809                 }
1810                 return returnValue;
1811             };
1812         }
1813         return e;
1814     }
1815
1816     return {
1817         
1818         
1819         
1820         beforeMethod : function(method, fn, scope){
1821             getMethodEvent.call(this, method).before.push({
1822                 fn: fn,
1823                 scope: scope
1824             });
1825         },
1826
1827         
1828         afterMethod : function(method, fn, scope){
1829             getMethodEvent.call(this, method).after.push({
1830                 fn: fn,
1831                 scope: scope
1832             });
1833         },
1834
1835         removeMethodListener: function(method, fn, scope){
1836             var e = this.getMethodEvent(method);
1837             for(var i = 0, len = e.before.length; i < len; i++){
1838                 if(e.before[i].fn == fn && e.before[i].scope == scope){
1839                     e.before.splice(i, 1);
1840                     return;
1841                 }
1842             }
1843             for(var i = 0, len = e.after.length; i < len; i++){
1844                 if(e.after[i].fn == fn && e.after[i].scope == scope){
1845                     e.after.splice(i, 1);
1846                     return;
1847                 }
1848             }
1849         },
1850
1851         
1852         relayEvents : function(o, events){
1853             var me = this;
1854             function createHandler(ename){
1855                 return function(){
1856                     return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
1857                 };
1858             }
1859             for(var i = 0, len = events.length; i < len; i++){
1860                 var ename = events[i];
1861                 me.events[ename] = me.events[ename] || true;
1862                 o.on(ename, createHandler(ename), me);
1863             }
1864         },
1865
1866         
1867         enableBubble : function(events){
1868             var me = this;
1869             if(!Ext.isEmpty(events)){
1870                 events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
1871                 for(var i = 0, len = events.length; i < len; i++){
1872                     var ename = events[i];
1873                     ename = ename.toLowerCase();
1874                     var ce = me.events[ename] || true;
1875                     if (typeof ce == 'boolean') {
1876                         ce = new Ext.util.Event(me, ename);
1877                         me.events[ename] = ce;
1878                     }
1879                     ce.bubble = true;
1880                 }
1881             }
1882         }
1883     };
1884 }());
1885
1886
1887
1888 Ext.util.Observable.capture = function(o, fn, scope){
1889     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
1890 };
1891
1892
1893
1894 Ext.util.Observable.observeClass = function(c, listeners){
1895     if(c){
1896       if(!c.fireEvent){
1897           Ext.apply(c, new Ext.util.Observable());
1898           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
1899       }
1900       if(typeof listeners == 'object'){
1901           c.on(listeners);
1902       }
1903       return c;
1904    }
1905 };
1906
1907
1908 Ext.EventManager = function(){
1909     var docReadyEvent,
1910         docReadyProcId,
1911         docReadyState = false,
1912         DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
1913         E = Ext.lib.Event,
1914         D = Ext.lib.Dom,
1915         DOC = document,
1916         WINDOW = window,
1917         DOMCONTENTLOADED = "DOMContentLoaded",
1918         COMPLETE = 'complete',
1919         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
1920         
1921         specialElCache = [];
1922
1923      function getId(el){
1924         var id = false,
1925             i = 0,
1926             len = specialElCache.length,
1927             id = false,
1928             skip = false,
1929             o;
1930         if(el){
1931             if(el.getElementById || el.navigator){
1932                 
1933                 for(; i < len; ++i){
1934                     o = specialElCache[i];
1935                     if(o.el === el){
1936                         id = o.id;
1937                         break;
1938                     }
1939                 }
1940                 if(!id){
1941                     
1942                     id = Ext.id(el);
1943                     specialElCache.push({
1944                         id: id,
1945                         el: el
1946                     });
1947                     skip = true;
1948                 }
1949             }else{
1950                 id = Ext.id(el);
1951             }
1952             if(!Ext.elCache[id]){
1953                 Ext.Element.addToCache(new Ext.Element(el), id);
1954                 if(skip){
1955                     Ext.elCache[id].skipGC = true;
1956                 }
1957             }
1958         }
1959         return id;
1960      };
1961
1962     
1963     function addListener(el, ename, fn, task, wrap, scope){
1964         el = Ext.getDom(el);
1965         var id = getId(el),
1966             es = Ext.elCache[id].events,
1967             wfn;
1968
1969         wfn = E.on(el, ename, wrap);
1970         es[ename] = es[ename] || [];
1971
1972         
1973         es[ename].push([fn, wrap, scope, wfn, task]);
1974
1975         
1976         
1977
1978         
1979         if(el.addEventListener && ename == "mousewheel"){
1980             var args = ["DOMMouseScroll", wrap, false];
1981             el.addEventListener.apply(el, args);
1982             Ext.EventManager.addListener(WINDOW, 'unload', function(){
1983                 el.removeEventListener.apply(el, args);
1984             });
1985         }
1986
1987         
1988         if(el == DOC && ename == "mousedown"){
1989             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
1990         }
1991     };
1992
1993     function doScrollChk(){
1994         
1995         if(window != top){
1996             return false;
1997         }
1998
1999         try{
2000             DOC.documentElement.doScroll('left');
2001         }catch(e){
2002              return false;
2003         }
2004
2005         fireDocReady();
2006         return true;
2007     }
2008     
2009     function checkReadyState(e){
2010
2011         if(Ext.isIE && doScrollChk()){
2012             return true;
2013         }
2014         if(DOC.readyState == COMPLETE){
2015             fireDocReady();
2016             return true;
2017         }
2018         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
2019         return false;
2020     }
2021
2022     var styles;
2023     function checkStyleSheets(e){
2024         styles || (styles = Ext.query('style, link[rel=stylesheet]'));
2025         if(styles.length == DOC.styleSheets.length){
2026             fireDocReady();
2027             return true;
2028         }
2029         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
2030         return false;
2031     }
2032
2033     function OperaDOMContentLoaded(e){
2034         DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
2035         checkStyleSheets();
2036     }
2037
2038     function fireDocReady(e){
2039         if(!docReadyState){
2040             docReadyState = true; 
2041
2042             if(docReadyProcId){
2043                 clearTimeout(docReadyProcId);
2044             }
2045             if(DETECT_NATIVE) {
2046                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
2047             }
2048             if(Ext.isIE && checkReadyState.bindIE){  
2049                 DOC.detachEvent('onreadystatechange', checkReadyState);
2050             }
2051             E.un(WINDOW, "load", arguments.callee);
2052         }
2053         if(docReadyEvent && !Ext.isReady){
2054             Ext.isReady = true;
2055             docReadyEvent.fire();
2056             docReadyEvent.listeners = [];
2057         }
2058
2059     };
2060
2061     function initDocReady(){
2062         docReadyEvent || (docReadyEvent = new Ext.util.Event());
2063         if (DETECT_NATIVE) {
2064             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
2065         }
2066         
2067         if (Ext.isIE){
2068             
2069             
2070             if(!checkReadyState()){
2071                 checkReadyState.bindIE = true;
2072                 DOC.attachEvent('onreadystatechange', checkReadyState);
2073             }
2074
2075         }else if(Ext.isOpera ){
2076             
2077
2078             
2079             (DOC.readyState == COMPLETE && checkStyleSheets()) ||
2080                 DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
2081
2082         }else if (Ext.isWebKit){
2083             
2084             checkReadyState();
2085         }
2086         
2087         E.on(WINDOW, "load", fireDocReady);
2088     };
2089
2090     function createTargeted(h, o){
2091         return function(){
2092             var args = Ext.toArray(arguments);
2093             if(o.target == Ext.EventObject.setEvent(args[0]).target){
2094                 h.apply(this, args);
2095             }
2096         };
2097     };
2098
2099     function createBuffered(h, o, task){
2100         return function(e){
2101             
2102             task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
2103         };
2104     };
2105
2106     function createSingle(h, el, ename, fn, scope){
2107         return function(e){
2108             Ext.EventManager.removeListener(el, ename, fn, scope);
2109             h(e);
2110         };
2111     };
2112
2113     function createDelayed(h, o, fn){
2114         return function(e){
2115             var task = new Ext.util.DelayedTask(h);
2116             if(!fn.tasks) {
2117                 fn.tasks = [];
2118             }
2119             fn.tasks.push(task);
2120             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
2121         };
2122     };
2123
2124     function listen(element, ename, opt, fn, scope){
2125         var o = (!opt || typeof opt == "boolean") ? {} : opt,
2126             el = Ext.getDom(element), task;
2127
2128         fn = fn || o.fn;
2129         scope = scope || o.scope;
2130
2131         if(!el){
2132             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
2133         }
2134         function h(e){
2135             
2136             if(!Ext){
2137                 return;
2138             }
2139             e = Ext.EventObject.setEvent(e);
2140             var t;
2141             if (o.delegate) {
2142                 if(!(t = e.getTarget(o.delegate, el))){
2143                     return;
2144                 }
2145             } else {
2146                 t = e.target;
2147             }
2148             if (o.stopEvent) {
2149                 e.stopEvent();
2150             }
2151             if (o.preventDefault) {
2152                e.preventDefault();
2153             }
2154             if (o.stopPropagation) {
2155                 e.stopPropagation();
2156             }
2157             if (o.normalized) {
2158                 e = e.browserEvent;
2159             }
2160
2161             fn.call(scope || el, e, t, o);
2162         };
2163         if(o.target){
2164             h = createTargeted(h, o);
2165         }
2166         if(o.delay){
2167             h = createDelayed(h, o, fn);
2168         }
2169         if(o.single){
2170             h = createSingle(h, el, ename, fn, scope);
2171         }
2172         if(o.buffer){
2173             task = new Ext.util.DelayedTask(h);
2174             h = createBuffered(h, o, task);
2175         }
2176
2177         addListener(el, ename, fn, task, h, scope);
2178         return h;
2179     };
2180
2181     var pub = {
2182         
2183         addListener : function(element, eventName, fn, scope, options){
2184             if(typeof eventName == 'object'){
2185                 var o = eventName, e, val;
2186                 for(e in o){
2187                     val = o[e];
2188                     if(!propRe.test(e)){
2189                         if(Ext.isFunction(val)){
2190                             
2191                             listen(element, e, o, val, o.scope);
2192                         }else{
2193                             
2194                             listen(element, e, val);
2195                         }
2196                     }
2197                 }
2198             } else {
2199                 listen(element, eventName, options, fn, scope);
2200             }
2201         },
2202
2203         
2204         removeListener : function(el, eventName, fn, scope){
2205             el = Ext.getDom(el);
2206             var id = getId(el),
2207                 f = el && (Ext.elCache[id].events)[eventName] || [],
2208                 wrap, i, l, k, len, fnc;
2209
2210             for (i = 0, len = f.length; i < len; i++) {
2211
2212                 
2213                 if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
2214                     if(fnc[4]) {
2215                         fnc[4].cancel();
2216                     }
2217                     k = fn.tasks && fn.tasks.length;
2218                     if(k) {
2219                         while(k--) {
2220                             fn.tasks[k].cancel();
2221                         }
2222                         delete fn.tasks;
2223                     }
2224                     wrap = fnc[1];
2225                     E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
2226
2227                     
2228                     if(wrap && el.addEventListener && eventName == "mousewheel"){
2229                         el.removeEventListener("DOMMouseScroll", wrap, false);
2230                     }
2231
2232                     
2233                     if(wrap && el == DOC && eventName == "mousedown"){
2234                         Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
2235                     }
2236
2237                     f.splice(i, 1);
2238                     if (f.length === 0) {
2239                         delete Ext.elCache[id].events[eventName];
2240                     }
2241                     for (k in Ext.elCache[id].events) {
2242                         return false;
2243                     }
2244                     Ext.elCache[id].events = {};
2245                     return false;
2246                 }
2247             }
2248         },
2249
2250         
2251         removeAll : function(el){
2252             el = Ext.getDom(el);
2253             var id = getId(el),
2254                 ec = Ext.elCache[id] || {},
2255                 es = ec.events || {},
2256                 f, i, len, ename, fn, k, wrap;
2257
2258             for(ename in es){
2259                 if(es.hasOwnProperty(ename)){
2260                     f = es[ename];
2261                     
2262                     for (i = 0, len = f.length; i < len; i++) {
2263                         fn = f[i];
2264                         if(fn[4]) {
2265                             fn[4].cancel();
2266                         }
2267                         if(fn[0].tasks && (k = fn[0].tasks.length)) {
2268                             while(k--) {
2269                                 fn[0].tasks[k].cancel();
2270                             }
2271                             delete fn.tasks;
2272                         }
2273                         wrap =  fn[1];
2274                         E.un(el, ename, E.extAdapter ? fn[3] : wrap);
2275
2276                         
2277                         if(el.addEventListener && wrap && ename == "mousewheel"){
2278                             el.removeEventListener("DOMMouseScroll", wrap, false);
2279                         }
2280
2281                         
2282                         if(wrap && el == DOC &&  ename == "mousedown"){
2283                             Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
2284                         }
2285                     }
2286                 }
2287             }
2288             if (Ext.elCache[id]) {
2289                 Ext.elCache[id].events = {};
2290             }
2291         },
2292
2293         getListeners : function(el, eventName) {
2294             el = Ext.getDom(el);
2295             var id = getId(el),
2296                 ec = Ext.elCache[id] || {},
2297                 es = ec.events || {},
2298                 results = [];
2299             if (es && es[eventName]) {
2300                 return es[eventName];
2301             } else {
2302                 return null;
2303             }
2304         },
2305
2306         purgeElement : function(el, recurse, eventName) {
2307             el = Ext.getDom(el);
2308             var id = getId(el),
2309                 ec = Ext.elCache[id] || {},
2310                 es = ec.events || {},
2311                 i, f, len;
2312             if (eventName) {
2313                 if (es && es.hasOwnProperty(eventName)) {
2314                     f = es[eventName];
2315                     for (i = 0, len = f.length; i < len; i++) {
2316                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
2317                     }
2318                 }
2319             } else {
2320                 Ext.EventManager.removeAll(el);
2321             }
2322             if (recurse && el && el.childNodes) {
2323                 for (i = 0, len = el.childNodes.length; i < len; i++) {
2324                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
2325                 }
2326             }
2327         },
2328
2329         _unload : function() {
2330             var el;
2331             for (el in Ext.elCache) {
2332                 Ext.EventManager.removeAll(el);
2333             }
2334             delete Ext.elCache;
2335             delete Ext.Element._flyweights;
2336
2337             
2338             var c,
2339                 conn,
2340                 tid,
2341                 ajax = Ext.lib.Ajax;
2342             (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
2343             for (tid in conn) {
2344                 c = conn[tid];
2345                 if (c) {
2346                     ajax.abort({conn: c, tId: tid});
2347                 }
2348             }
2349         },
2350         
2351         onDocumentReady : function(fn, scope, options){
2352             if(Ext.isReady){ 
2353                 docReadyEvent || (docReadyEvent = new Ext.util.Event());
2354                 docReadyEvent.addListener(fn, scope, options);
2355                 docReadyEvent.fire();
2356                 docReadyEvent.listeners = [];
2357             }else{
2358                 if(!docReadyEvent){
2359                     initDocReady();
2360                 }
2361                 options = options || {};
2362                 options.delay = options.delay || 1;
2363                 docReadyEvent.addListener(fn, scope, options);
2364             }
2365         },
2366
2367         
2368         fireDocReady  : fireDocReady
2369     };
2370      
2371     pub.on = pub.addListener;
2372     
2373     pub.un = pub.removeListener;
2374
2375     pub.stoppedMouseDownEvent = new Ext.util.Event();
2376     return pub;
2377 }();
2378
2379 Ext.onReady = Ext.EventManager.onDocumentReady;
2380
2381
2382
2383 (function(){
2384
2385     var initExtCss = function(){
2386         
2387         var bd = document.body || document.getElementsByTagName('body')[0];
2388         if(!bd){ return false; }
2389         var cls = [' ',
2390                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
2391                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
2392                 : Ext.isOpera ? "ext-opera"
2393                 : Ext.isWebKit ? "ext-webkit" : ""];
2394
2395         if(Ext.isSafari){
2396             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
2397         }else if(Ext.isChrome){
2398             cls.push("ext-chrome");
2399         }
2400
2401         if(Ext.isMac){
2402             cls.push("ext-mac");
2403         }
2404         if(Ext.isLinux){
2405             cls.push("ext-linux");
2406         }
2407
2408         if(Ext.isStrict || Ext.isBorderBox){ 
2409             var p = bd.parentNode;
2410             if(p){
2411                 p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
2412             }
2413         }
2414         bd.className += cls.join(' ');
2415         return true;
2416     }
2417
2418     if(!initExtCss()){
2419         Ext.onReady(initExtCss);
2420     }
2421 })();
2422
2423
2424
2425 Ext.EventObject = function(){
2426     var E = Ext.lib.Event,
2427         clickRe = /(dbl)?click/,
2428         
2429         safariKeys = {
2430             3 : 13, 
2431             63234 : 37, 
2432             63235 : 39, 
2433             63232 : 38, 
2434             63233 : 40, 
2435             63276 : 33, 
2436             63277 : 34, 
2437             63272 : 46, 
2438             63273 : 36, 
2439             63275 : 35  
2440         },
2441         
2442         btnMap = Ext.isIE ? {1:0,4:1,2:2} :
2443                 (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
2444
2445     Ext.EventObjectImpl = function(e){
2446         if(e){
2447             this.setEvent(e.browserEvent || e);
2448         }
2449     };
2450
2451     Ext.EventObjectImpl.prototype = {
2452            
2453         setEvent : function(e){
2454             var me = this;
2455             if(e == me || (e && e.browserEvent)){ 
2456                 return e;
2457             }
2458             me.browserEvent = e;
2459             if(e){
2460                 
2461                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
2462                 if(clickRe.test(e.type) && me.button == -1){
2463                     me.button = 0;
2464                 }
2465                 me.type = e.type;
2466                 me.shiftKey = e.shiftKey;
2467                 
2468                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
2469                 me.altKey = e.altKey;
2470                 
2471                 me.keyCode = e.keyCode;
2472                 me.charCode = e.charCode;
2473                 
2474                 me.target = E.getTarget(e);
2475                 
2476                 me.xy = E.getXY(e);
2477             }else{
2478                 me.button = -1;
2479                 me.shiftKey = false;
2480                 me.ctrlKey = false;
2481                 me.altKey = false;
2482                 me.keyCode = 0;
2483                 me.charCode = 0;
2484                 me.target = null;
2485                 me.xy = [0, 0];
2486             }
2487             return me;
2488         },
2489
2490         
2491         stopEvent : function(){
2492             var me = this;
2493             if(me.browserEvent){
2494                 if(me.browserEvent.type == 'mousedown'){
2495                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2496                 }
2497                 E.stopEvent(me.browserEvent);
2498             }
2499         },
2500
2501         
2502         preventDefault : function(){
2503             if(this.browserEvent){
2504                 E.preventDefault(this.browserEvent);
2505             }
2506         },
2507
2508         
2509         stopPropagation : function(){
2510             var me = this;
2511             if(me.browserEvent){
2512                 if(me.browserEvent.type == 'mousedown'){
2513                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2514                 }
2515                 E.stopPropagation(me.browserEvent);
2516             }
2517         },
2518
2519         
2520         getCharCode : function(){
2521             return this.charCode || this.keyCode;
2522         },
2523
2524         
2525         getKey : function(){
2526             return this.normalizeKey(this.keyCode || this.charCode)
2527         },
2528
2529         
2530         normalizeKey: function(k){
2531             return Ext.isSafari ? (safariKeys[k] || k) : k;
2532         },
2533
2534         
2535         getPageX : function(){
2536             return this.xy[0];
2537         },
2538
2539         
2540         getPageY : function(){
2541             return this.xy[1];
2542         },
2543
2544         
2545         getXY : function(){
2546             return this.xy;
2547         },
2548
2549         
2550         getTarget : function(selector, maxDepth, returnEl){
2551             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
2552         },
2553
2554         
2555         getRelatedTarget : function(){
2556             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
2557         },
2558
2559         
2560         getWheelDelta : function(){
2561             var e = this.browserEvent;
2562             var delta = 0;
2563             if(e.wheelDelta){ 
2564                 delta = e.wheelDelta/120;
2565             }else if(e.detail){ 
2566                 delta = -e.detail/3;
2567             }
2568             return delta;
2569         },
2570
2571         
2572         within : function(el, related, allowEl){
2573             if(el){
2574                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
2575                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
2576             }
2577             return false;
2578         }
2579      };
2580
2581     return new Ext.EventObjectImpl();
2582 }();
2583
2584 Ext.apply(Ext.EventManager, function(){
2585    var resizeEvent,
2586        resizeTask,
2587        textEvent,
2588        textSize,
2589        D = Ext.lib.Dom,
2590        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
2591        curWidth = 0,
2592        curHeight = 0,
2593        
2594        
2595        
2596        useKeydown = Ext.isWebKit ?
2597                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
2598                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
2599
2600    return {
2601        
2602        doResizeEvent: function(){
2603            var h = D.getViewHeight(),
2604                w = D.getViewWidth();
2605
2606             
2607             if(curHeight != h || curWidth != w){
2608                resizeEvent.fire(curWidth = w, curHeight = h);
2609             }
2610        },
2611
2612        
2613        onWindowResize : function(fn, scope, options){
2614            if(!resizeEvent){
2615                resizeEvent = new Ext.util.Event();
2616                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
2617                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
2618            }
2619            resizeEvent.addListener(fn, scope, options);
2620        },
2621
2622        
2623        fireWindowResize : function(){
2624            if(resizeEvent){
2625                resizeTask.delay(100);
2626            }
2627        },
2628
2629        
2630        onTextResize : function(fn, scope, options){
2631            if(!textEvent){
2632                textEvent = new Ext.util.Event();
2633                var textEl = new Ext.Element(document.createElement('div'));
2634                textEl.dom.className = 'x-text-resize';
2635                textEl.dom.innerHTML = 'X';
2636                textEl.appendTo(document.body);
2637                textSize = textEl.dom.offsetHeight;
2638                setInterval(function(){
2639                    if(textEl.dom.offsetHeight != textSize){
2640                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
2641                    }
2642                }, this.textResizeInterval);
2643            }
2644            textEvent.addListener(fn, scope, options);
2645        },
2646
2647        
2648        removeResizeListener : function(fn, scope){
2649            if(resizeEvent){
2650                resizeEvent.removeListener(fn, scope);
2651            }
2652        },
2653
2654        
2655        fireResize : function(){
2656            if(resizeEvent){
2657                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
2658            }
2659        },
2660
2661         
2662        textResizeInterval : 50,
2663
2664        
2665        ieDeferSrc : false,
2666
2667        
2668        
2669        useKeydown: useKeydown
2670    };
2671 }());
2672
2673 Ext.EventManager.on = Ext.EventManager.addListener;
2674
2675
2676 Ext.apply(Ext.EventObjectImpl.prototype, {
2677    
2678    BACKSPACE: 8,
2679    
2680    TAB: 9,
2681    
2682    NUM_CENTER: 12,
2683    
2684    ENTER: 13,
2685    
2686    RETURN: 13,
2687    
2688    SHIFT: 16,
2689    
2690    CTRL: 17,
2691    CONTROL : 17, 
2692    
2693    ALT: 18,
2694    
2695    PAUSE: 19,
2696    
2697    CAPS_LOCK: 20,
2698    
2699    ESC: 27,
2700    
2701    SPACE: 32,
2702    
2703    PAGE_UP: 33,
2704    PAGEUP : 33, 
2705    
2706    PAGE_DOWN: 34,
2707    PAGEDOWN : 34, 
2708    
2709    END: 35,
2710    
2711    HOME: 36,
2712    
2713    LEFT: 37,
2714    
2715    UP: 38,
2716    
2717    RIGHT: 39,
2718    
2719    DOWN: 40,
2720    
2721    PRINT_SCREEN: 44,
2722    
2723    INSERT: 45,
2724    
2725    DELETE: 46,
2726    
2727    ZERO: 48,
2728    
2729    ONE: 49,
2730    
2731    TWO: 50,
2732    
2733    THREE: 51,
2734    
2735    FOUR: 52,
2736    
2737    FIVE: 53,
2738    
2739    SIX: 54,
2740    
2741    SEVEN: 55,
2742    
2743    EIGHT: 56,
2744    
2745    NINE: 57,
2746    
2747    A: 65,
2748    
2749    B: 66,
2750    
2751    C: 67,
2752    
2753    D: 68,
2754    
2755    E: 69,
2756    
2757    F: 70,
2758    
2759    G: 71,
2760    
2761    H: 72,
2762    
2763    I: 73,
2764    
2765    J: 74,
2766    
2767    K: 75,
2768    
2769    L: 76,
2770    
2771    M: 77,
2772    
2773    N: 78,
2774    
2775    O: 79,
2776    
2777    P: 80,
2778    
2779    Q: 81,
2780    
2781    R: 82,
2782    
2783    S: 83,
2784    
2785    T: 84,
2786    
2787    U: 85,
2788    
2789    V: 86,
2790    
2791    W: 87,
2792    
2793    X: 88,
2794    
2795    Y: 89,
2796    
2797    Z: 90,
2798    
2799    CONTEXT_MENU: 93,
2800    
2801    NUM_ZERO: 96,
2802    
2803    NUM_ONE: 97,
2804    
2805    NUM_TWO: 98,
2806    
2807    NUM_THREE: 99,
2808    
2809    NUM_FOUR: 100,
2810    
2811    NUM_FIVE: 101,
2812    
2813    NUM_SIX: 102,
2814    
2815    NUM_SEVEN: 103,
2816    
2817    NUM_EIGHT: 104,
2818    
2819    NUM_NINE: 105,
2820    
2821    NUM_MULTIPLY: 106,
2822    
2823    NUM_PLUS: 107,
2824    
2825    NUM_MINUS: 109,
2826    
2827    NUM_PERIOD: 110,
2828    
2829    NUM_DIVISION: 111,
2830    
2831    F1: 112,
2832    
2833    F2: 113,
2834    
2835    F3: 114,
2836    
2837    F4: 115,
2838    
2839    F5: 116,
2840    
2841    F6: 117,
2842    
2843    F7: 118,
2844    
2845    F8: 119,
2846    
2847    F9: 120,
2848    
2849    F10: 121,
2850    
2851    F11: 122,
2852    
2853    F12: 123,
2854
2855    
2856    isNavKeyPress : function(){
2857        var me = this,
2858            k = this.normalizeKey(me.keyCode);
2859        return (k >= 33 && k <= 40) ||  
2860        k == me.RETURN ||
2861        k == me.TAB ||
2862        k == me.ESC;
2863    },
2864
2865    isSpecialKey : function(){
2866        var k = this.normalizeKey(this.keyCode);
2867        return (this.type == 'keypress' && this.ctrlKey) ||
2868        this.isNavKeyPress() ||
2869        (k == this.BACKSPACE) || 
2870        (k >= 16 && k <= 20) || 
2871        (k >= 44 && k <= 46);   
2872    },
2873
2874    getPoint : function(){
2875        return new Ext.lib.Point(this.xy[0], this.xy[1]);
2876    },
2877
2878    
2879    hasModifier : function(){
2880        return ((this.ctrlKey || this.altKey) || this.shiftKey);
2881    }
2882 });
2883 (function(){
2884 var DOC = document;
2885
2886 Ext.Element = function(element, forceNew){
2887     var dom = typeof element == "string" ?
2888               DOC.getElementById(element) : element,
2889         id;
2890
2891     if(!dom) return null;
2892
2893     id = dom.id;
2894
2895     if(!forceNew && id && Ext.elCache[id]){ 
2896         return Ext.elCache[id].el;
2897     }
2898
2899     
2900     this.dom = dom;
2901
2902     
2903     this.id = id || Ext.id(dom);
2904 };
2905
2906 var DH = Ext.DomHelper,
2907     El = Ext.Element,
2908     EC = Ext.elCache;
2909
2910 El.prototype = {
2911     
2912     set : function(o, useSet){
2913         var el = this.dom,
2914             attr,
2915             val,
2916             useSet = (useSet !== false) && !!el.setAttribute;
2917
2918         for (attr in o) {
2919             if (o.hasOwnProperty(attr)) {
2920                 val = o[attr];
2921                 if (attr == 'style') {
2922                     DH.applyStyles(el, val);
2923                 } else if (attr == 'cls') {
2924                     el.className = val;
2925                 } else if (useSet) {
2926                     el.setAttribute(attr, val);
2927                 } else {
2928                     el[attr] = val;
2929                 }
2930             }
2931         }
2932         return this;
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     
2984     defaultUnit : "px",
2985
2986     
2987     is : function(simpleSelector){
2988         return Ext.DomQuery.is(this.dom, simpleSelector);
2989     },
2990
2991     
2992     focus : function(defer,  dom) {
2993         var me = this,
2994             dom = dom || me.dom;
2995         try{
2996             if(Number(defer)){
2997                 me.focus.defer(defer, null, [null, dom]);
2998             }else{
2999                 dom.focus();
3000             }
3001         }catch(e){}
3002         return me;
3003     },
3004
3005     
3006     blur : function() {
3007         try{
3008             this.dom.blur();
3009         }catch(e){}
3010         return this;
3011     },
3012
3013     
3014     getValue : function(asNumber){
3015         var val = this.dom.value;
3016         return asNumber ? parseInt(val, 10) : val;
3017     },
3018
3019     
3020     addListener : function(eventName, fn, scope, options){
3021         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
3022         return this;
3023     },
3024
3025     
3026     removeListener : function(eventName, fn, scope){
3027         Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
3028         return this;
3029     },
3030
3031     
3032     removeAllListeners : function(){
3033         Ext.EventManager.removeAll(this.dom);
3034         return this;
3035     },
3036
3037     
3038     purgeAllListeners : function() {
3039         Ext.EventManager.purgeElement(this, true);
3040         return this;
3041     },
3042     
3043     addUnits : function(size){
3044         if(size === "" || size == "auto" || size === undefined){
3045             size = size || '';
3046         } else if(!isNaN(size) || !unitPattern.test(size)){
3047             size = size + (this.defaultUnit || 'px');
3048         }
3049         return size;
3050     },
3051
3052     
3053     load : function(url, params, cb){
3054         Ext.Ajax.request(Ext.apply({
3055             params: params,
3056             url: url.url || url,
3057             callback: cb,
3058             el: this.dom,
3059             indicatorText: url.indicatorText || ''
3060         }, Ext.isObject(url) ? url : {}));
3061         return this;
3062     },
3063
3064     
3065     isBorderBox : function(){
3066         return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;
3067     },
3068
3069     
3070     remove : function(){
3071         var me = this,
3072             dom = me.dom;
3073
3074         if (dom) {
3075             delete me.dom;
3076             Ext.removeNode(dom);
3077         }
3078     },
3079
3080     
3081     hover : function(overFn, outFn, scope, options){
3082         var me = this;
3083         me.on('mouseenter', overFn, scope || me.dom, options);
3084         me.on('mouseleave', outFn, scope || me.dom, options);
3085         return me;
3086     },
3087
3088     
3089     contains : function(el){
3090         return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
3091     },
3092
3093     
3094     getAttributeNS : function(ns, name){
3095         return this.getAttribute(name, ns);
3096     },
3097
3098     
3099     getAttribute : Ext.isIE ? function(name, ns){
3100         var d = this.dom,
3101             type = typeof d[ns + ":" + name];
3102
3103         if(['undefined', 'unknown'].indexOf(type) == -1){
3104             return d[ns + ":" + name];
3105         }
3106         return d[name];
3107     } : function(name, ns){
3108         var d = this.dom;
3109         return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
3110     },
3111
3112     
3113     update : function(html) {
3114         if (this.dom) {
3115             this.dom.innerHTML = html;
3116         }
3117         return this;
3118     }
3119 };
3120
3121 var ep = El.prototype;
3122
3123 El.addMethods = function(o){
3124    Ext.apply(ep, o);
3125 };
3126
3127
3128 ep.on = ep.addListener;
3129
3130
3131 ep.un = ep.removeListener;
3132
3133
3134 ep.autoBoxAdjust = true;
3135
3136
3137 var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
3138     docEl;
3139
3140
3141
3142
3143 El.get = function(el){
3144     var ex,
3145         elm,
3146         id;
3147     if(!el){ return null; }
3148     if (typeof el == "string") { 
3149         if (!(elm = DOC.getElementById(el))) {
3150             return null;
3151         }
3152         if (EC[el] && EC[el].el) {
3153             ex = EC[el].el;
3154             ex.dom = elm;
3155         } else {
3156             ex = El.addToCache(new El(elm));
3157         }
3158         return ex;
3159     } else if (el.tagName) { 
3160         if(!(id = el.id)){
3161             id = Ext.id(el);
3162         }
3163         if (EC[id] && EC[id].el) {
3164             ex = EC[id].el;
3165             ex.dom = el;
3166         } else {
3167             ex = El.addToCache(new El(el));
3168         }
3169         return ex;
3170     } else if (el instanceof El) {
3171         if(el != docEl){
3172             
3173             
3174
3175             
3176             if (Ext.isIE && (el.id == undefined || el.id == '')) {
3177                 el.dom = el.dom;
3178             } else {
3179                 el.dom = DOC.getElementById(el.id) || el.dom;
3180             }
3181         }
3182         return el;
3183     } else if(el.isComposite) {
3184         return el;
3185     } else if(Ext.isArray(el)) {
3186         return El.select(el);
3187     } else if(el == DOC) {
3188         
3189         if(!docEl){
3190             var f = function(){};
3191             f.prototype = El.prototype;
3192             docEl = new f();
3193             docEl.dom = DOC;
3194         }
3195         return docEl;
3196     }
3197     return null;
3198 };
3199
3200 El.addToCache = function(el, id){
3201     id = id || el.id;
3202     EC[id] = {
3203         el:  el,
3204         data: {},
3205         events: {}
3206     };
3207     return el;
3208 };
3209
3210
3211 El.data = function(el, key, value){
3212     el = El.get(el);
3213     if (!el) {
3214         return null;
3215     }
3216     var c = EC[el.id].data;
3217     if(arguments.length == 2){
3218         return c[key];
3219     }else{
3220         return (c[key] = value);
3221     }
3222 };
3223
3224
3225
3226
3227 function garbageCollect(){
3228     if(!Ext.enableGarbageCollector){
3229         clearInterval(El.collectorThreadId);
3230     } else {
3231         var eid,
3232             el,
3233             d,
3234             o;
3235
3236         for(eid in EC){
3237             o = EC[eid];
3238             if(o.skipGC){
3239                 continue;
3240             }
3241             el = o.el;
3242             d = el.dom;
3243             
3244             
3245             
3246             
3247             
3248             
3249             
3250             
3251             
3252             
3253             
3254             
3255             
3256             
3257             
3258             
3259             
3260             if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
3261                 if(Ext.enableListenerCollection){
3262                     Ext.EventManager.removeAll(d);
3263                 }
3264                 delete EC[eid];
3265             }
3266         }
3267         
3268         if (Ext.isIE) {
3269             var t = {};
3270             for (eid in EC) {
3271                 t[eid] = EC[eid];
3272             }
3273             EC = Ext.elCache = t;
3274         }
3275     }
3276 }
3277 El.collectorThreadId = setInterval(garbageCollect, 30000);
3278
3279 var flyFn = function(){};
3280 flyFn.prototype = El.prototype;
3281
3282
3283 El.Flyweight = function(dom){
3284     this.dom = dom;
3285 };
3286
3287 El.Flyweight.prototype = new flyFn();
3288 El.Flyweight.prototype.isFlyweight = true;
3289 El._flyweights = {};
3290
3291
3292 El.fly = function(el, named){
3293     var ret = null;
3294     named = named || '_global';
3295
3296     if (el = Ext.getDom(el)) {
3297         (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
3298         ret = El._flyweights[named];
3299     }
3300     return ret;
3301 };
3302
3303
3304 Ext.get = El.get;
3305
3306
3307 Ext.fly = El.fly;
3308
3309
3310 var noBoxAdjust = Ext.isStrict ? {
3311     select:1
3312 } : {
3313     input:1, select:1, textarea:1
3314 };
3315 if(Ext.isIE || Ext.isGecko){
3316     noBoxAdjust['button'] = 1;
3317 }
3318
3319 })();
3320
3321 Ext.Element.addMethods({
3322     
3323     swallowEvent : function(eventName, preventDefault){
3324         var me = this;
3325         function fn(e){
3326             e.stopPropagation();
3327             if(preventDefault){
3328                 e.preventDefault();
3329             }
3330         }
3331         if(Ext.isArray(eventName)){
3332             Ext.each(eventName, function(e) {
3333                  me.on(e, fn);
3334             });
3335             return me;
3336         }
3337         me.on(eventName, fn);
3338         return me;
3339     },
3340
3341     
3342     relayEvent : function(eventName, observable){
3343         this.on(eventName, function(e){
3344             observable.fireEvent(eventName, e);
3345         });
3346     },
3347
3348     
3349     clean : function(forceReclean){
3350         var me = this,
3351             dom = me.dom,
3352             n = dom.firstChild,
3353             ni = -1;
3354
3355         if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
3356             return me;
3357         }
3358
3359         while(n){
3360             var nx = n.nextSibling;
3361             if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
3362                 dom.removeChild(n);
3363             }else{
3364                 n.nodeIndex = ++ni;
3365             }
3366             n = nx;
3367         }
3368         Ext.Element.data(dom, 'isCleaned', true);
3369         return me;
3370     },
3371
3372     
3373     load : function(){
3374         var um = this.getUpdater();
3375         um.update.apply(um, arguments);
3376         return this;
3377     },
3378
3379     
3380     getUpdater : function(){
3381         return this.updateManager || (this.updateManager = new Ext.Updater(this));
3382     },
3383
3384     
3385     update : function(html, loadScripts, callback){
3386         if (!this.dom) {
3387             return this;
3388         }
3389         html = html || "";
3390
3391         if(loadScripts !== true){
3392             this.dom.innerHTML = html;
3393             if(typeof callback == 'function'){
3394                 callback();
3395             }
3396             return this;
3397         }
3398
3399         var id = Ext.id(),
3400             dom = this.dom;
3401
3402         html += '<span id="' + id + '"></span>';
3403
3404         Ext.lib.Event.onAvailable(id, function(){
3405             var DOC = document,
3406                 hd = DOC.getElementsByTagName("head")[0],
3407                 re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
3408                 srcRe = /\ssrc=([\'\"])(.*?)\1/i,
3409                 typeRe = /\stype=([\'\"])(.*?)\1/i,
3410                 match,
3411                 attrs,
3412                 srcMatch,
3413                 typeMatch,
3414                 el,
3415                 s;
3416
3417             while((match = re.exec(html))){
3418                 attrs = match[1];
3419                 srcMatch = attrs ? attrs.match(srcRe) : false;
3420                 if(srcMatch && srcMatch[2]){
3421                    s = DOC.createElement("script");
3422                    s.src = srcMatch[2];
3423                    typeMatch = attrs.match(typeRe);
3424                    if(typeMatch && typeMatch[2]){
3425                        s.type = typeMatch[2];
3426                    }
3427                    hd.appendChild(s);
3428                 }else if(match[2] && match[2].length > 0){
3429                     if(window.execScript) {
3430                        window.execScript(match[2]);
3431                     } else {
3432                        window.eval(match[2]);
3433                     }
3434                 }
3435             }
3436             el = DOC.getElementById(id);
3437             if(el){Ext.removeNode(el);}
3438             if(typeof callback == 'function'){
3439                 callback();
3440             }
3441         });
3442         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
3443         return this;
3444     },
3445
3446     
3447     removeAllListeners : function(){
3448         this.removeAnchor();
3449         Ext.EventManager.removeAll(this.dom);
3450         return this;
3451     },
3452
3453     
3454     createProxy : function(config, renderTo, matchBox){
3455         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
3456
3457         var me = this,
3458             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
3459                                Ext.DomHelper.insertBefore(me.dom, config, true);
3460
3461         if(matchBox && me.setBox && me.getBox){ 
3462            proxy.setBox(me.getBox());
3463         }
3464         return proxy;
3465     }
3466 });
3467
3468 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
3469
3470 Ext.Element.addMethods({
3471     
3472     getAnchorXY : function(anchor, local, s){
3473         
3474         
3475                 anchor = (anchor || "tl").toLowerCase();
3476         s = s || {};
3477         
3478         var me = this,        
3479                 vp = me.dom == document.body || me.dom == document,
3480                 w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
3481                 h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
3482                 xy,             
3483                 r = Math.round,
3484                 o = me.getXY(),
3485                 scroll = me.getScroll(),
3486                 extraX = vp ? scroll.left : !local ? o[0] : 0,
3487                 extraY = vp ? scroll.top : !local ? o[1] : 0,
3488                 hash = {
3489                         c  : [r(w * 0.5), r(h * 0.5)],
3490                         t  : [r(w * 0.5), 0],
3491                         l  : [0, r(h * 0.5)],
3492                         r  : [w, r(h * 0.5)],
3493                         b  : [r(w * 0.5), h],
3494                         tl : [0, 0],    
3495                         bl : [0, h],
3496                         br : [w, h],
3497                         tr : [w, 0]
3498                 };
3499         
3500         xy = hash[anchor];      
3501         return [xy[0] + extraX, xy[1] + extraY]; 
3502     },
3503
3504     
3505     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
3506             var me = this,
3507             dom = me.dom,
3508             scroll = !Ext.isEmpty(monitorScroll),
3509             action = function(){
3510                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
3511                 Ext.callback(callback, Ext.fly(dom));
3512             },
3513             anchor = this.getAnchor();
3514             
3515         
3516         this.removeAnchor();
3517         Ext.apply(anchor, {
3518             fn: action,
3519             scroll: scroll
3520         });
3521
3522         Ext.EventManager.onWindowResize(action, null);
3523         
3524         if(scroll){
3525             Ext.EventManager.on(window, 'scroll', action, null,
3526                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
3527         }
3528         action.call(me); 
3529         return me;
3530     },
3531     
3532     
3533     removeAnchor : function(){
3534         var me = this,
3535             anchor = this.getAnchor();
3536             
3537         if(anchor && anchor.fn){
3538             Ext.EventManager.removeResizeListener(anchor.fn);
3539             if(anchor.scroll){
3540                 Ext.EventManager.un(window, 'scroll', anchor.fn);
3541             }
3542             delete anchor.fn;
3543         }
3544         return me;
3545     },
3546     
3547     
3548     getAnchor : function(){
3549         var data = Ext.Element.data,
3550             dom = this.dom;
3551             if (!dom) {
3552                 return;
3553             }
3554             var anchor = data(dom, '_anchor');
3555             
3556         if(!anchor){
3557             anchor = data(dom, '_anchor', {});
3558         }
3559         return anchor;
3560     },
3561
3562     
3563     getAlignToXY : function(el, p, o){      
3564         el = Ext.get(el);
3565         
3566         if(!el || !el.dom){
3567             throw "Element.alignToXY with an element that doesn't exist";
3568         }
3569         
3570         o = o || [0,0];
3571         p = (!p || p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
3572                 
3573         var me = this,
3574                 d = me.dom,
3575                 a1,
3576                 a2,
3577                 x,
3578                 y,
3579                 
3580                 w,
3581                 h,
3582                 r,
3583                 dw = Ext.lib.Dom.getViewWidth() -10, 
3584                 dh = Ext.lib.Dom.getViewHeight()-10, 
3585                 p1y,
3586                 p1x,            
3587                 p2y,
3588                 p2x,
3589                 swapY,
3590                 swapX,
3591                 doc = document,
3592                 docElement = doc.documentElement,
3593                 docBody = doc.body,
3594                 scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
3595                 scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
3596                 c = false, 
3597                 p1 = "", 
3598                 p2 = "",
3599                 m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
3600         
3601         if(!m){
3602            throw "Element.alignTo with an invalid alignment " + p;
3603         }
3604         
3605         p1 = m[1]; 
3606         p2 = m[2]; 
3607         c = !!m[3];
3608
3609         
3610         
3611         a1 = me.getAnchorXY(p1, true);
3612         a2 = el.getAnchorXY(p2, false);
3613
3614         x = a2[0] - a1[0] + o[0];
3615         y = a2[1] - a1[1] + o[1];
3616
3617         if(c){    
3618                w = me.getWidth();
3619            h = me.getHeight();
3620            r = el.getRegion();       
3621            
3622            
3623            
3624            p1y = p1.charAt(0);
3625            p1x = p1.charAt(p1.length-1);
3626            p2y = p2.charAt(0);
3627            p2x = p2.charAt(p2.length-1);
3628            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
3629            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
3630            
3631
3632            if (x + w > dw + scrollX) {
3633                 x = swapX ? r.left-w : dw+scrollX-w;
3634            }
3635            if (x < scrollX) {
3636                x = swapX ? r.right : scrollX;
3637            }
3638            if (y + h > dh + scrollY) {
3639                 y = swapY ? r.top-h : dh+scrollY-h;
3640             }
3641            if (y < scrollY){
3642                y = swapY ? r.bottom : scrollY;
3643            }
3644         }
3645         return [x,y];
3646     },
3647
3648     
3649     alignTo : function(element, position, offsets, animate){
3650             var me = this;
3651         return me.setXY(me.getAlignToXY(element, position, offsets),
3652                                 me.preanim && !!animate ? me.preanim(arguments, 3) : false);
3653     },
3654     
3655     
3656     adjustForConstraints : function(xy, parent, offsets){
3657         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
3658     },
3659
3660     
3661     getConstrainToXY : function(el, local, offsets, proposedXY){   
3662             var os = {top:0, left:0, bottom:0, right: 0};
3663
3664         return function(el, local, offsets, proposedXY){
3665             el = Ext.get(el);
3666             offsets = offsets ? Ext.applyIf(offsets, os) : os;
3667
3668             var vw, vh, vx = 0, vy = 0;
3669             if(el.dom == document.body || el.dom == document){
3670                 vw =Ext.lib.Dom.getViewWidth();
3671                 vh = Ext.lib.Dom.getViewHeight();
3672             }else{
3673                 vw = el.dom.clientWidth;
3674                 vh = el.dom.clientHeight;
3675                 if(!local){
3676                     var vxy = el.getXY();
3677                     vx = vxy[0];
3678                     vy = vxy[1];
3679                 }
3680             }
3681
3682             var s = el.getScroll();
3683
3684             vx += offsets.left + s.left;
3685             vy += offsets.top + s.top;
3686
3687             vw -= offsets.right;
3688             vh -= offsets.bottom;
3689
3690             var vr = vx + vw,
3691                 vb = vy + vh,
3692                 xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
3693                 x = xy[0], y = xy[1],
3694                 offset = this.getConstrainOffset(),
3695                 w = this.dom.offsetWidth + offset, 
3696                 h = this.dom.offsetHeight + offset;
3697
3698             
3699             var moved = false;
3700
3701             
3702             if((x + w) > vr){
3703                 x = vr - w;
3704                 moved = true;
3705             }
3706             if((y + h) > vb){
3707                 y = vb - h;
3708                 moved = true;
3709             }
3710             
3711             if(x < vx){
3712                 x = vx;
3713                 moved = true;
3714             }
3715             if(y < vy){
3716                 y = vy;
3717                 moved = true;
3718             }
3719             return moved ? [x, y] : false;
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
3778     
3779     getConstrainOffset : function(){
3780         return 0;
3781     },
3782     
3783     
3784     getCenterXY : function(){
3785         return this.getAlignToXY(document, 'c-c');
3786     },
3787
3788     
3789     center : function(centerIn){
3790         return this.alignTo(centerIn || document, 'c-c');        
3791     }    
3792 });
3793
3794 Ext.Element.addMethods(function(){
3795         var PARENTNODE = 'parentNode',
3796                 NEXTSIBLING = 'nextSibling',
3797                 PREVIOUSSIBLING = 'previousSibling',
3798                 DQ = Ext.DomQuery,
3799                 GET = Ext.get;
3800         
3801         return {
3802                 
3803             findParent : function(simpleSelector, maxDepth, returnEl){
3804                 var p = this.dom,
3805                         b = document.body, 
3806                         depth = 0,                      
3807                         stopEl;         
3808             if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
3809                 return null;
3810             }
3811                 maxDepth = maxDepth || 50;
3812                 if (isNaN(maxDepth)) {
3813                     stopEl = Ext.getDom(maxDepth);
3814                     maxDepth = Number.MAX_VALUE;
3815                 }
3816                 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
3817                     if(DQ.is(p, simpleSelector)){
3818                         return returnEl ? GET(p) : p;
3819                     }
3820                     depth++;
3821                     p = p.parentNode;
3822                 }
3823                 return null;
3824             },
3825         
3826             
3827             findParentNode : function(simpleSelector, maxDepth, returnEl){
3828                 var p = Ext.fly(this.dom.parentNode, '_internal');
3829                 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
3830             },
3831         
3832             
3833             up : function(simpleSelector, maxDepth){
3834                 return this.findParentNode(simpleSelector, maxDepth, true);
3835             },
3836         
3837             
3838             select : function(selector){
3839                 return Ext.Element.select(selector, this.dom);
3840             },
3841         
3842             
3843             query : function(selector){
3844                 return DQ.select(selector, this.dom);
3845             },
3846         
3847             
3848             child : function(selector, returnDom){
3849                 var n = DQ.selectNode(selector, this.dom);
3850                 return returnDom ? n : GET(n);
3851             },
3852         
3853             
3854             down : function(selector, returnDom){
3855                 var n = DQ.selectNode(" > " + selector, this.dom);
3856                 return returnDom ? n : GET(n);
3857             },
3858         
3859                  
3860             parent : function(selector, returnDom){
3861                 return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
3862             },
3863         
3864              
3865             next : function(selector, returnDom){
3866                 return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
3867             },
3868         
3869             
3870             prev : function(selector, returnDom){
3871                 return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
3872             },
3873         
3874         
3875             
3876             first : function(selector, returnDom){
3877                 return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
3878             },
3879         
3880             
3881             last : function(selector, returnDom){
3882                 return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
3883             },
3884             
3885             matchNode : function(dir, start, selector, returnDom){
3886                 var n = this.dom[start];
3887                 while(n){
3888                     if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
3889                         return !returnDom ? GET(n) : n;
3890                     }
3891                     n = n[dir];
3892                 }
3893                 return null;
3894             }   
3895     }
3896 }());
3897 Ext.Element.addMethods({
3898     
3899     select : function(selector, unique){
3900         return Ext.Element.select(selector, unique, this.dom);
3901     }
3902 });
3903 Ext.Element.addMethods(
3904 function() {
3905         var GETDOM = Ext.getDom,
3906                 GET = Ext.get,
3907                 DH = Ext.DomHelper;
3908         
3909         return {
3910             
3911             appendChild: function(el){        
3912                 return GET(el).appendTo(this);        
3913             },
3914         
3915             
3916             appendTo: function(el){        
3917                 GETDOM(el).appendChild(this.dom);        
3918                 return this;
3919             },
3920         
3921             
3922             insertBefore: function(el){                   
3923                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
3924                 return this;
3925             },
3926         
3927             
3928             insertAfter: function(el){
3929                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
3930                 return this;
3931             },
3932         
3933             
3934             insertFirst: function(el, returnDom){
3935             el = el || {};
3936             if(el.nodeType || el.dom || typeof el == 'string'){ 
3937                 el = GETDOM(el);
3938                 this.dom.insertBefore(el, this.dom.firstChild);
3939                 return !returnDom ? GET(el) : el;
3940             }else{ 
3941                 return this.createChild(el, this.dom.firstChild, returnDom);
3942             }
3943         },
3944         
3945             
3946             replace: function(el){
3947                 el = GET(el);
3948                 this.insertBefore(el);
3949                 el.remove();
3950                 return this;
3951             },
3952         
3953             
3954             replaceWith: function(el){
3955                     var me = this;
3956                 
3957             if(el.nodeType || el.dom || typeof el == 'string'){
3958                 el = GETDOM(el);
3959                 me.dom.parentNode.insertBefore(el, me.dom);
3960             }else{
3961                 el = DH.insertBefore(me.dom, el);
3962             }
3963                 
3964                 delete Ext.elCache[me.id];
3965                 Ext.removeNode(me.dom);      
3966                 me.id = Ext.id(me.dom = el);
3967                 Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
3968             return me;
3969             },
3970             
3971                 
3972                 createChild: function(config, insertBefore, returnDom){
3973                     config = config || {tag:'div'};
3974                     return insertBefore ? 
3975                            DH.insertBefore(insertBefore, config, returnDom !== true) :  
3976                            DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
3977                 },
3978                 
3979                 
3980                 wrap: function(config, returnDom){        
3981                     var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
3982                     newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
3983                     return newEl;
3984                 },
3985                 
3986                 
3987                 insertHtml : function(where, html, returnEl){
3988                     var el = DH.insertHtml(where, this.dom, html);
3989                     return returnEl ? Ext.get(el) : el;
3990                 }
3991         }
3992 }());
3993 Ext.apply(Ext.Element.prototype, function() {
3994         var GETDOM = Ext.getDom,
3995                 GET = Ext.get,
3996                 DH = Ext.DomHelper;
3997         
3998         return {        
3999                 
4000             insertSibling: function(el, where, returnDom){
4001                 var me = this,
4002                         rt,
4003                 isAfter = (where || 'before').toLowerCase() == 'after',
4004                 insertEl;
4005                         
4006                 if(Ext.isArray(el)){
4007                 insertEl = me;
4008                     Ext.each(el, function(e) {
4009                             rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
4010                     if(isAfter){
4011                         insertEl = rt;
4012                     }
4013                     });
4014                     return rt;
4015                 }
4016                         
4017                 el = el || {};
4018                 
4019             if(el.nodeType || el.dom){
4020                 rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
4021                 if (!returnDom) {
4022                     rt = GET(rt);
4023                 }
4024             }else{
4025                 if (isAfter && !me.dom.nextSibling) {
4026                     rt = DH.append(me.dom.parentNode, el, !returnDom);
4027                 } else {                    
4028                     rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
4029                 }
4030             }
4031                 return rt;
4032             }
4033     };
4034 }());
4035 Ext.Element.addMethods(function(){
4036     
4037     var propCache = {},
4038         camelRe = /(-[a-z])/gi,
4039         view = document.defaultView,
4040         propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
4041         opacityRe = /alpha\(opacity=(.*)\)/i,
4042         trimRe = /^\s+|\s+$/g,
4043         spacesRe = /\s+/,
4044         wordsRe = /\w/g,
4045         PADDING = "padding",
4046         MARGIN = "margin",
4047         BORDER = "border",
4048         LEFT = "-left",
4049         RIGHT = "-right",
4050         TOP = "-top",
4051         BOTTOM = "-bottom",
4052         WIDTH = "-width",
4053         MATH = Math,
4054         HIDDEN = 'hidden',
4055         ISCLIPPED = 'isClipped',
4056         OVERFLOW = 'overflow',
4057         OVERFLOWX = 'overflow-x',
4058         OVERFLOWY = 'overflow-y',
4059         ORIGINALCLIP = 'originalClip',
4060         
4061         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
4062         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
4063         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
4064         data = Ext.Element.data;
4065
4066
4067     
4068     function camelFn(m, a) {
4069         return a.charAt(1).toUpperCase();
4070     }
4071
4072     function chkCache(prop) {
4073         return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
4074     }
4075
4076     return {
4077         
4078         adjustWidth : function(width) {
4079             var me = this;
4080             var isNum = (typeof width == "number");
4081             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
4082                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
4083             }
4084             return (isNum && width < 0) ? 0 : width;
4085         },
4086
4087         
4088         adjustHeight : function(height) {
4089             var me = this;
4090             var isNum = (typeof height == "number");
4091             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
4092                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
4093             }
4094             return (isNum && height < 0) ? 0 : height;
4095         },
4096
4097
4098         
4099         addClass : function(className){
4100             var me = this,
4101                 i,
4102                 len,
4103                 v,
4104                 cls = [];
4105             
4106             if (!Ext.isArray(className)) {
4107                 if (typeof className == 'string' && !this.hasClass(className)) {
4108                     me.dom.className += " " + className;
4109                 }
4110             }
4111             else {
4112                 for (i = 0, len = className.length; i < len; i++) {
4113                     v = className[i];
4114                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
4115                         cls.push(v);
4116                     }
4117                 }
4118                 if (cls.length) {
4119                     me.dom.className += " " + cls.join(" ");
4120                 }
4121             }
4122             return me;
4123         },
4124
4125         
4126         removeClass : function(className){
4127             var me = this,
4128                 i,
4129                 idx,
4130                 len,
4131                 cls,
4132                 elClasses;
4133             if (!Ext.isArray(className)){
4134                 className = [className];
4135             }
4136             if (me.dom && me.dom.className) {
4137                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
4138                 for (i = 0, len = className.length; i < len; i++) {
4139                     cls = className[i];
4140                     if (typeof cls == 'string') {
4141                         cls = cls.replace(trimRe, '');
4142                         idx = elClasses.indexOf(cls);
4143                         if (idx != -1) {
4144                             elClasses.splice(idx, 1);
4145                         }
4146                     }
4147                 }
4148                 me.dom.className = elClasses.join(" ");
4149             }
4150             return me;
4151         },
4152
4153         
4154         radioClass : function(className){
4155             var cn = this.dom.parentNode.childNodes,
4156                 v,
4157                 i,
4158                 len;
4159             className = Ext.isArray(className) ? className : [className];
4160             for (i = 0, len = cn.length; i < len; i++) {
4161                 v = cn[i];
4162                 if (v && v.nodeType == 1) {
4163                     Ext.fly(v, '_internal').removeClass(className);
4164                 }
4165             };
4166             return this.addClass(className);
4167         },
4168
4169         
4170         toggleClass : function(className){
4171             return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
4172         },
4173
4174         
4175         hasClass : function(className){
4176             return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
4177         },
4178
4179         
4180         replaceClass : function(oldClassName, newClassName){
4181             return this.removeClass(oldClassName).addClass(newClassName);
4182         },
4183
4184         isStyle : function(style, val) {
4185             return this.getStyle(style) == val;
4186         },
4187
4188         
4189         getStyle : function(){
4190             return view && view.getComputedStyle ?
4191                 function(prop){
4192                     var el = this.dom,
4193                         v,
4194                         cs,
4195                         out,
4196                         display,
4197                         wk = Ext.isWebKit,
4198                         display;
4199
4200                     if(el == document){
4201                         return null;
4202                     }
4203                     prop = chkCache(prop);
4204                     
4205                     if(wk && (/marginRight/.test(prop))) {
4206                         display = this.getStyle('display');
4207                         el.style.display = 'inline-block';
4208                     }
4209                     out = (v = el.style[prop]) ? v :
4210                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
4211
4212                     
4213                     if(wk){
4214                         if(out == 'rgba(0, 0, 0, 0)'){
4215                             out = 'transparent';
4216                         }else if(display){
4217                             el.style.display = display;
4218                         }
4219                     }
4220                     return out;
4221                 } :
4222                 function(prop){
4223                     var el = this.dom,
4224                         m,
4225                         cs;
4226
4227                     if(el == document) return null;
4228                     if (prop == 'opacity') {
4229                         if (el.style.filter.match) {
4230                             if(m = el.style.filter.match(opacityRe)){
4231                                 var fv = parseFloat(m[1]);
4232                                 if(!isNaN(fv)){
4233                                     return fv ? fv / 100 : 0;
4234                                 }
4235                             }
4236                         }
4237                         return 1;
4238                     }
4239                     prop = chkCache(prop);
4240                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
4241                 };
4242         }(),
4243
4244         
4245         getColor : function(attr, defaultValue, prefix){
4246             var v = this.getStyle(attr),
4247                 color = (typeof prefix != 'undefined') ? prefix : '#',
4248                 h;
4249
4250             if(!v || (/transparent|inherit/.test(v))) {
4251                 return defaultValue;
4252             }
4253             if(/^r/.test(v)){
4254                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
4255                     h = parseInt(s, 10);
4256                     color += (h < 16 ? '0' : '') + h.toString(16);
4257                 });
4258             }else{
4259                 v = v.replace('#', '');
4260                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
4261             }
4262             return(color.length > 5 ? color.toLowerCase() : defaultValue);
4263         },
4264
4265         
4266         setStyle : function(prop, value){
4267             var tmp, style;
4268             
4269             if (typeof prop != 'object') {
4270                 tmp = {};
4271                 tmp[prop] = value;
4272                 prop = tmp;
4273             }
4274             for (style in prop) {
4275                 value = prop[style];
4276                 style == 'opacity' ?
4277                     this.setOpacity(value) :
4278                     this.dom.style[chkCache(style)] = value;
4279             }
4280             return this;
4281         },
4282
4283         
4284          setOpacity : function(opacity, animate){
4285             var me = this,
4286                 s = me.dom.style;
4287
4288             if(!animate || !me.anim){
4289                 if(Ext.isIE){
4290                     var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
4291                     val = s.filter.replace(opacityRe, '').replace(trimRe, '');
4292
4293                     s.zoom = 1;
4294                     s.filter = val + (val.length > 0 ? ' ' : '') + opac;
4295                 }else{
4296                     s.opacity = opacity;
4297                 }
4298             }else{
4299                 me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
4300             }
4301             return me;
4302         },
4303
4304         
4305         clearOpacity : function(){
4306             var style = this.dom.style;
4307             if(Ext.isIE){
4308                 if(!Ext.isEmpty(style.filter)){
4309                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
4310                 }
4311             }else{
4312                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
4313             }
4314             return this;
4315         },
4316
4317         
4318         getHeight : function(contentHeight){
4319             var me = this,
4320                 dom = me.dom,
4321                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4322                 h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
4323
4324             h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
4325             return h < 0 ? 0 : h;
4326         },
4327
4328         
4329         getWidth : function(contentWidth){
4330             var me = this,
4331                 dom = me.dom,
4332                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4333                 w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
4334             w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
4335             return w < 0 ? 0 : w;
4336         },
4337
4338         
4339         setWidth : function(width, animate){
4340             var me = this;
4341             width = me.adjustWidth(width);
4342             !animate || !me.anim ?
4343                 me.dom.style.width = me.addUnits(width) :
4344                 me.anim({width : {to : width}}, me.preanim(arguments, 1));
4345             return me;
4346         },
4347
4348         
4349          setHeight : function(height, animate){
4350             var me = this;
4351             height = me.adjustHeight(height);
4352             !animate || !me.anim ?
4353                 me.dom.style.height = me.addUnits(height) :
4354                 me.anim({height : {to : height}}, me.preanim(arguments, 1));
4355             return me;
4356         },
4357
4358         
4359         getBorderWidth : function(side){
4360             return this.addStyles(side, borders);
4361         },
4362
4363         
4364         getPadding : function(side){
4365             return this.addStyles(side, paddings);
4366         },
4367
4368         
4369         clip : function(){
4370             var me = this,
4371                 dom = me.dom;
4372
4373             if(!data(dom, ISCLIPPED)){
4374                 data(dom, ISCLIPPED, true);
4375                 data(dom, ORIGINALCLIP, {
4376                     o: me.getStyle(OVERFLOW),
4377                     x: me.getStyle(OVERFLOWX),
4378                     y: me.getStyle(OVERFLOWY)
4379                 });
4380                 me.setStyle(OVERFLOW, HIDDEN);
4381                 me.setStyle(OVERFLOWX, HIDDEN);
4382                 me.setStyle(OVERFLOWY, HIDDEN);
4383             }
4384             return me;
4385         },
4386
4387         
4388         unclip : function(){
4389             var me = this,
4390                 dom = me.dom;
4391
4392             if(data(dom, ISCLIPPED)){
4393                 data(dom, ISCLIPPED, false);
4394                 var o = data(dom, ORIGINALCLIP);
4395                 if(o.o){
4396                     me.setStyle(OVERFLOW, o.o);
4397                 }
4398                 if(o.x){
4399                     me.setStyle(OVERFLOWX, o.x);
4400                 }
4401                 if(o.y){
4402                     me.setStyle(OVERFLOWY, o.y);
4403                 }
4404             }
4405             return me;
4406         },
4407
4408         
4409         addStyles : function(sides, styles){
4410             var ttlSize = 0,
4411                 sidesArr = sides.match(wordsRe),
4412                 side,
4413                 size,
4414                 i,
4415                 len = sidesArr.length;
4416             for (i = 0; i < len; i++) {
4417                 side = sidesArr[i];
4418                 size = side && parseInt(this.getStyle(styles[side]), 10);
4419                 if (size) {
4420                     ttlSize += MATH.abs(size);
4421                 }
4422             }
4423             return ttlSize;
4424         },
4425
4426         margins : margins
4427     };
4428 }()
4429 );
4430
4431
4432
4433 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>';
4434
4435 Ext.Element.addMethods(function(){
4436     var INTERNAL = "_internal",
4437         pxMatch = /(\d+\.?\d+)px/;
4438     return {
4439         
4440         applyStyles : function(style){
4441             Ext.DomHelper.applyStyles(this.dom, style);
4442             return this;
4443         },
4444
4445         
4446         getStyles : function(){
4447             var ret = {};
4448             Ext.each(arguments, function(v) {
4449                ret[v] = this.getStyle(v);
4450             },
4451             this);
4452             return ret;
4453         },
4454
4455         
4456         setOverflow : function(v){
4457             var dom = this.dom;
4458             if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
4459                 dom.style.overflow = 'hidden';
4460                 (function(){dom.style.overflow = 'auto';}).defer(1);
4461             }else{
4462                 dom.style.overflow = v;
4463             }
4464         },
4465
4466        
4467         boxWrap : function(cls){
4468             cls = cls || 'x-box';
4469             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
4470             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
4471             return el;
4472         },
4473
4474         
4475         setSize : function(width, height, animate){
4476             var me = this;
4477             if(typeof width == 'object'){ 
4478                 height = width.height;
4479                 width = width.width;
4480             }
4481             width = me.adjustWidth(width);
4482             height = me.adjustHeight(height);
4483             if(!animate || !me.anim){
4484                 me.dom.style.width = me.addUnits(width);
4485                 me.dom.style.height = me.addUnits(height);
4486             }else{
4487                 me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
4488             }
4489             return me;
4490         },
4491
4492         
4493         getComputedHeight : function(){
4494             var me = this,
4495                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
4496             if(!h){
4497                 h = parseFloat(me.getStyle('height')) || 0;
4498                 if(!me.isBorderBox()){
4499                     h += me.getFrameWidth('tb');
4500                 }
4501             }
4502             return h;
4503         },
4504
4505         
4506         getComputedWidth : function(){
4507             var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
4508             if(!w){
4509                 w = parseFloat(this.getStyle('width')) || 0;
4510                 if(!this.isBorderBox()){
4511                     w += this.getFrameWidth('lr');
4512                 }
4513             }
4514             return w;
4515         },
4516
4517         
4518         getFrameWidth : function(sides, onlyContentBox){
4519             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
4520         },
4521
4522         
4523         addClassOnOver : function(className){
4524             this.hover(
4525                 function(){
4526                     Ext.fly(this, INTERNAL).addClass(className);
4527                 },
4528                 function(){
4529                     Ext.fly(this, INTERNAL).removeClass(className);
4530                 }
4531             );
4532             return this;
4533         },
4534
4535         
4536         addClassOnFocus : function(className){
4537             this.on("focus", function(){
4538                 Ext.fly(this, INTERNAL).addClass(className);
4539             }, this.dom);
4540             this.on("blur", function(){
4541                 Ext.fly(this, INTERNAL).removeClass(className);
4542             }, this.dom);
4543             return this;
4544         },
4545
4546         
4547         addClassOnClick : function(className){
4548             var dom = this.dom;
4549             this.on("mousedown", function(){
4550                 Ext.fly(dom, INTERNAL).addClass(className);
4551                 var d = Ext.getDoc(),
4552                     fn = function(){
4553                         Ext.fly(dom, INTERNAL).removeClass(className);
4554                         d.removeListener("mouseup", fn);
4555                     };
4556                 d.on("mouseup", fn);
4557             });
4558             return this;
4559         },
4560
4561         
4562
4563         getViewSize : function(){
4564             var doc = document,
4565                 d = this.dom,
4566                 isDoc = (d == doc || d == doc.body);
4567
4568             
4569             if (isDoc) {
4570                 var extdom = Ext.lib.Dom;
4571                 return {
4572                     width : extdom.getViewWidth(),
4573                     height : extdom.getViewHeight()
4574                 };
4575
4576             
4577             } else {
4578                 return {
4579                     width : d.clientWidth,
4580                     height : d.clientHeight
4581                 }
4582             }
4583         },
4584
4585         
4586
4587         getStyleSize : function(){
4588             var me = this,
4589                 w, h,
4590                 doc = document,
4591                 d = this.dom,
4592                 isDoc = (d == doc || d == doc.body),
4593                 s = d.style;
4594
4595             
4596             if (isDoc) {
4597                 var extdom = Ext.lib.Dom;
4598                 return {
4599                     width : extdom.getViewWidth(),
4600                     height : extdom.getViewHeight()
4601                 }
4602             }
4603             
4604             if(s.width && s.width != 'auto'){
4605                 w = parseFloat(s.width);
4606                 if(me.isBorderBox()){
4607                    w -= me.getFrameWidth('lr');
4608                 }
4609             }
4610             
4611             if(s.height && s.height != 'auto'){
4612                 h = parseFloat(s.height);
4613                 if(me.isBorderBox()){
4614                    h -= me.getFrameWidth('tb');
4615                 }
4616             }
4617             
4618             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
4619         },
4620
4621         
4622         getSize : function(contentSize){
4623             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
4624         },
4625
4626         
4627         repaint : function(){
4628             var dom = this.dom;
4629             this.addClass("x-repaint");
4630             setTimeout(function(){
4631                 Ext.fly(dom).removeClass("x-repaint");
4632             }, 1);
4633             return this;
4634         },
4635
4636         
4637         unselectable : function(){
4638             this.dom.unselectable = "on";
4639             return this.swallowEvent("selectstart", true).
4640                         applyStyles("-moz-user-select:none;-khtml-user-select:none;").
4641                         addClass("x-unselectable");
4642         },
4643
4644         
4645         getMargins : function(side){
4646             var me = this,
4647                 key,
4648                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
4649                 o = {};
4650
4651             if (!side) {
4652                 for (key in me.margins){
4653                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
4654                 }
4655                 return o;
4656             } else {
4657                 return me.addStyles.call(me, side, me.margins);
4658             }
4659         }
4660     };
4661 }());
4662
4663 (function(){
4664 var D = Ext.lib.Dom,
4665         LEFT = "left",
4666         RIGHT = "right",
4667         TOP = "top",
4668         BOTTOM = "bottom",
4669         POSITION = "position",
4670         STATIC = "static",
4671         RELATIVE = "relative",
4672         AUTO = "auto",
4673         ZINDEX = "z-index";
4674
4675 Ext.Element.addMethods({
4676         
4677     getX : function(){
4678         return D.getX(this.dom);
4679     },
4680
4681     
4682     getY : function(){
4683         return D.getY(this.dom);
4684     },
4685
4686     
4687     getXY : function(){
4688         return D.getXY(this.dom);
4689     },
4690
4691     
4692     getOffsetsTo : function(el){
4693         var o = this.getXY(),
4694                 e = Ext.fly(el, '_internal').getXY();
4695         return [o[0]-e[0],o[1]-e[1]];
4696     },
4697
4698     
4699     setX : function(x, animate){            
4700             return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
4701     },
4702
4703     
4704     setY : function(y, animate){            
4705             return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
4706     },
4707
4708     
4709     setLeft : function(left){
4710         this.setStyle(LEFT, this.addUnits(left));
4711         return this;
4712     },
4713
4714     
4715     setTop : function(top){
4716         this.setStyle(TOP, this.addUnits(top));
4717         return this;
4718     },
4719
4720     
4721     setRight : function(right){
4722         this.setStyle(RIGHT, this.addUnits(right));
4723         return this;
4724     },
4725
4726     
4727     setBottom : function(bottom){
4728         this.setStyle(BOTTOM, this.addUnits(bottom));
4729         return this;
4730     },
4731
4732     
4733     setXY : function(pos, animate){
4734             var me = this;
4735         if(!animate || !me.anim){
4736             D.setXY(me.dom, pos);
4737         }else{
4738             me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
4739         }
4740         return me;
4741     },
4742
4743     
4744     setLocation : function(x, y, animate){
4745         return this.setXY([x, y], this.animTest(arguments, animate, 2));
4746     },
4747
4748     
4749     moveTo : function(x, y, animate){
4750         return this.setXY([x, y], this.animTest(arguments, animate, 2));        
4751     },    
4752     
4753     
4754     getLeft : function(local){
4755             return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
4756     },
4757
4758     
4759     getRight : function(local){
4760             var me = this;
4761             return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
4762     },
4763
4764     
4765     getTop : function(local) {
4766             return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
4767     },
4768
4769     
4770     getBottom : function(local){
4771             var me = this;
4772             return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
4773     },
4774
4775     
4776     position : function(pos, zIndex, x, y){
4777             var me = this;
4778             
4779         if(!pos && me.isStyle(POSITION, STATIC)){           
4780             me.setStyle(POSITION, RELATIVE);           
4781         } else if(pos) {
4782             me.setStyle(POSITION, pos);
4783         }
4784         if(zIndex){
4785             me.setStyle(ZINDEX, zIndex);
4786         }
4787         if(x || y) me.setXY([x || false, y || false]);
4788     },
4789
4790     
4791     clearPositioning : function(value){
4792         value = value || '';
4793         this.setStyle({
4794             left : value,
4795             right : value,
4796             top : value,
4797             bottom : value,
4798             "z-index" : "",
4799             position : STATIC
4800         });
4801         return this;
4802     },
4803
4804     
4805     getPositioning : function(){
4806         var l = this.getStyle(LEFT);
4807         var t = this.getStyle(TOP);
4808         return {
4809             "position" : this.getStyle(POSITION),
4810             "left" : l,
4811             "right" : l ? "" : this.getStyle(RIGHT),
4812             "top" : t,
4813             "bottom" : t ? "" : this.getStyle(BOTTOM),
4814             "z-index" : this.getStyle(ZINDEX)
4815         };
4816     },
4817     
4818     
4819     setPositioning : function(pc){
4820             var me = this,
4821                 style = me.dom.style;
4822                 
4823         me.setStyle(pc);
4824         
4825         if(pc.right == AUTO){
4826             style.right = "";
4827         }
4828         if(pc.bottom == AUTO){
4829             style.bottom = "";
4830         }
4831         
4832         return me;
4833     },    
4834         
4835     
4836     translatePoints : function(x, y){                
4837             y = isNaN(x[1]) ? y : x[1];
4838         x = isNaN(x[0]) ? x : x[0];
4839         var me = this,
4840                 relative = me.isStyle(POSITION, RELATIVE),
4841                 o = me.getXY(),
4842                 l = parseInt(me.getStyle(LEFT), 10),
4843                 t = parseInt(me.getStyle(TOP), 10);
4844         
4845         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
4846         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
4847
4848         return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
4849     },
4850     
4851     animTest : function(args, animate, i) {
4852         return !!animate && this.preanim ? this.preanim(args, i) : false;
4853     }
4854 });
4855 })();
4856 Ext.Element.addMethods({
4857     
4858     setBox : function(box, adjust, animate){
4859         var me = this,
4860                 w = box.width, 
4861                 h = box.height;
4862         if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
4863            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
4864            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
4865         }
4866         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
4867         return me;
4868     },
4869
4870     
4871         getBox : function(contentBox, local) {      
4872             var me = this,
4873                 xy,
4874                 left,
4875                 top,
4876                 getBorderWidth = me.getBorderWidth,
4877                 getPadding = me.getPadding, 
4878                 l,
4879                 r,
4880                 t,
4881                 b;
4882         if(!local){
4883             xy = me.getXY();
4884         }else{
4885             left = parseInt(me.getStyle("left"), 10) || 0;
4886             top = parseInt(me.getStyle("top"), 10) || 0;
4887             xy = [left, top];
4888         }
4889         var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
4890         if(!contentBox){
4891             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
4892         }else{
4893             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
4894             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
4895             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
4896             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
4897             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)};
4898         }
4899         bx.right = bx.x + bx.width;
4900         bx.bottom = bx.y + bx.height;
4901         return bx;
4902         },
4903         
4904     
4905      move : function(direction, distance, animate){
4906         var me = this,          
4907                 xy = me.getXY(),
4908                 x = xy[0],
4909                 y = xy[1],              
4910                 left = [x - distance, y],
4911                 right = [x + distance, y],
4912                 top = [x, y - distance],
4913                 bottom = [x, y + distance],
4914                 hash = {
4915                         l :     left,
4916                         left : left,
4917                         r : right,
4918                         right : right,
4919                         t : top,
4920                         top : top,
4921                         up : top,
4922                         b : bottom, 
4923                         bottom : bottom,
4924                         down : bottom                           
4925                 };
4926         
4927             direction = direction.toLowerCase();    
4928             me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
4929     },
4930     
4931     
4932      setLeftTop : function(left, top){
4933             var me = this,
4934                 style = me.dom.style;
4935         style.left = me.addUnits(left);
4936         style.top = me.addUnits(top);
4937         return me;
4938     },
4939     
4940     
4941     getRegion : function(){
4942         return Ext.lib.Dom.getRegion(this.dom);
4943     },
4944     
4945     
4946     setBounds : function(x, y, width, height, animate){
4947             var me = this;
4948         if (!animate || !me.anim) {
4949             me.setSize(width, height);
4950             me.setLocation(x, y);
4951         } else {
4952             me.anim({points: {to: [x, y]}, 
4953                          width: {to: me.adjustWidth(width)}, 
4954                          height: {to: me.adjustHeight(height)}},
4955                      me.preanim(arguments, 4), 
4956                      'motion');
4957         }
4958         return me;
4959     },
4960
4961     
4962     setRegion : function(region, animate) {
4963         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
4964     }
4965 });
4966 Ext.Element.addMethods({
4967     
4968     isScrollable : function(){
4969         var dom = this.dom;
4970         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
4971     },
4972
4973     
4974     scrollTo : function(side, value){
4975         this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
4976         return this;
4977     },
4978
4979     
4980     getScroll : function(){
4981         var d = this.dom, 
4982             doc = document,
4983             body = doc.body,
4984             docElement = doc.documentElement,
4985             l,
4986             t,
4987             ret;
4988
4989         if(d == doc || d == body){
4990             if(Ext.isIE && Ext.isStrict){
4991                 l = docElement.scrollLeft; 
4992                 t = docElement.scrollTop;
4993             }else{
4994                 l = window.pageXOffset;
4995                 t = window.pageYOffset;
4996             }
4997             ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
4998         }else{
4999             ret = {left: d.scrollLeft, top: d.scrollTop};
5000         }
5001         return ret;
5002     }
5003 });
5004 Ext.Element.addMethods({
5005     
5006     scrollTo : function(side, value, animate) {
5007         
5008         var top = /top/i.test(side),
5009             me = this,
5010             dom = me.dom,
5011             prop;
5012         if (!animate || !me.anim) {
5013             
5014             prop = 'scroll' + (top ? 'Top' : 'Left');
5015             dom[prop] = value;
5016         }
5017         else {
5018             
5019             prop = 'scroll' + (top ? 'Left' : 'Top');
5020             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}}, me.preanim(arguments, 2), 'scroll');
5021         }
5022         return me;
5023     },
5024     
5025     
5026     scrollIntoView : function(container, hscroll) {
5027         var c = Ext.getDom(container) || Ext.getBody().dom,
5028             el = this.dom,
5029             o = this.getOffsetsTo(c),
5030             l = o[0] + c.scrollLeft,
5031             t = o[1] + c.scrollTop,
5032             b = t + el.offsetHeight,
5033             r = l + el.offsetWidth,
5034             ch = c.clientHeight,
5035             ct = parseInt(c.scrollTop, 10),
5036             cl = parseInt(c.scrollLeft, 10),
5037             cb = ct + ch,
5038             cr = cl + c.clientWidth;
5039
5040         if (el.offsetHeight > ch || t < ct) {
5041             c.scrollTop = t;
5042         }
5043         else if (b > cb) {
5044             c.scrollTop = b-ch;
5045         }
5046         
5047         c.scrollTop = c.scrollTop;
5048
5049         if (hscroll !== false) {
5050             if (el.offsetWidth > c.clientWidth || l < cl) {
5051                 c.scrollLeft = l;
5052             }
5053             else if (r > cr) {
5054                 c.scrollLeft = r - c.clientWidth;
5055             }
5056             c.scrollLeft = c.scrollLeft;
5057         }
5058         return this;
5059     },
5060
5061     
5062     scrollChildIntoView : function(child, hscroll) {
5063         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
5064     },
5065     
5066     
5067      scroll : function(direction, distance, animate) {
5068         if (!this.isScrollable()) {
5069             return false;
5070         }
5071         var el = this.dom,
5072             l = el.scrollLeft, t = el.scrollTop,
5073             w = el.scrollWidth, h = el.scrollHeight,
5074             cw = el.clientWidth, ch = el.clientHeight,
5075             scrolled = false, v,
5076             hash = {
5077                 l: Math.min(l + distance, w-cw),
5078                 r: v = Math.max(l - distance, 0),
5079                 t: Math.max(t - distance, 0),
5080                 b: Math.min(t + distance, h-ch)
5081             };
5082             hash.d = hash.b;
5083             hash.u = hash.t;
5084         
5085         direction = direction.substr(0, 1);
5086         if ((v = hash[direction]) > -1) {
5087             scrolled = true;
5088             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
5089         }
5090         return scrolled;
5091     }
5092 });
5093
5094 Ext.Element.VISIBILITY = 1;
5095
5096 Ext.Element.DISPLAY = 2;
5097
5098 Ext.Element.addMethods(function(){
5099     var VISIBILITY = "visibility",
5100         DISPLAY = "display",
5101         HIDDEN = "hidden",
5102         OFFSETS = "offsets",
5103         NONE = "none",
5104         ORIGINALDISPLAY = 'originalDisplay',
5105         VISMODE = 'visibilityMode',
5106         ELDISPLAY = Ext.Element.DISPLAY,
5107         data = Ext.Element.data,
5108         getDisplay = function(dom){
5109             var d = data(dom, ORIGINALDISPLAY);
5110             if(d === undefined){
5111                 data(dom, ORIGINALDISPLAY, d = '');
5112             }
5113             return d;
5114         },
5115         getVisMode = function(dom){
5116             var m = data(dom, VISMODE);
5117             if(m === undefined){
5118                 data(dom, VISMODE, m = 1);
5119             }
5120             return m;
5121         };
5122
5123     return {
5124         
5125         originalDisplay : "",
5126         visibilityMode : 1,
5127
5128         
5129         setVisibilityMode : function(visMode){
5130             data(this.dom, VISMODE, visMode);
5131             return this;
5132         },
5133
5134         
5135         animate : function(args, duration, onComplete, easing, animType){
5136             this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
5137             return this;
5138         },
5139
5140         
5141         anim : function(args, opt, animType, defaultDur, defaultEase, cb){
5142             animType = animType || 'run';
5143             opt = opt || {};
5144             var me = this,
5145                 anim = Ext.lib.Anim[animType](
5146                     me.dom,
5147                     args,
5148                     (opt.duration || defaultDur) || .35,
5149                     (opt.easing || defaultEase) || 'easeOut',
5150                     function(){
5151                         if(cb) cb.call(me);
5152                         if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
5153                     },
5154                     me
5155                 );
5156             opt.anim = anim;
5157             return anim;
5158         },
5159
5160         
5161         preanim : function(a, i){
5162             return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
5163         },
5164
5165         
5166         isVisible : function() {
5167             return !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
5168         },
5169
5170         
5171          setVisible : function(visible, animate){
5172             var me = this, isDisplay, isVisible, isOffsets,
5173                 dom = me.dom;
5174
5175             
5176             if (typeof animate == 'string'){
5177                 isDisplay = animate == DISPLAY;
5178                 isVisible = animate == VISIBILITY;
5179                 isOffsets = animate == OFFSETS;
5180                 animate = false;
5181             } else {
5182                 isDisplay = getVisMode(this.dom) == ELDISPLAY;
5183                 isVisible = !isDisplay;
5184             }
5185
5186             if (!animate || !me.anim) {
5187                 if (isDisplay){
5188                     me.setDisplayed(visible);
5189                 } else if (isOffsets){
5190                     if (!visible){
5191                         me.hideModeStyles = {
5192                             position: me.getStyle('position'),
5193                             top: me.getStyle('top'),
5194                             left: me.getStyle('left')
5195                         };
5196
5197                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
5198                     } else {
5199                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
5200                     }
5201                 }else{
5202                     me.fixDisplay();
5203                     dom.style.visibility = visible ? "visible" : HIDDEN;
5204                 }
5205             }else{
5206                 
5207                 if (visible){
5208                     me.setOpacity(.01);
5209                     me.setVisible(true);
5210                 }
5211                 me.anim({opacity: { to: (visible?1:0) }},
5212                         me.preanim(arguments, 1),
5213                         null,
5214                         .35,
5215                         'easeIn',
5216                         function(){
5217                              if(!visible){
5218                                  dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;
5219                                  Ext.fly(dom).setOpacity(1);
5220                              }
5221                         });
5222             }
5223             return me;
5224         },
5225
5226         
5227         toggle : function(animate){
5228             var me = this;
5229             me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
5230             return me;
5231         },
5232
5233         
5234         setDisplayed : function(value) {
5235             if(typeof value == "boolean"){
5236                value = value ? getDisplay(this.dom) : NONE;
5237             }
5238             this.setStyle(DISPLAY, value);
5239             return this;
5240         },
5241
5242         
5243         fixDisplay : function(){
5244             var me = this;
5245             if(me.isStyle(DISPLAY, NONE)){
5246                 me.setStyle(VISIBILITY, HIDDEN);
5247                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
5248                 if(me.isStyle(DISPLAY, NONE)){ 
5249                     me.setStyle(DISPLAY, "block");
5250                 }
5251             }
5252         },
5253
5254         
5255         hide : function(animate){
5256             
5257             if (typeof animate == 'string'){
5258                 this.setVisible(false, animate);
5259                 return this;
5260             }
5261             this.setVisible(false, this.preanim(arguments, 0));
5262             return this;
5263         },
5264
5265         
5266         show : function(animate){
5267             
5268             if (typeof animate == 'string'){
5269                 this.setVisible(true, animate);
5270                 return this;
5271             }
5272             this.setVisible(true, this.preanim(arguments, 0));
5273             return this;
5274         }
5275     };
5276 }());
5277
5278 Ext.Element.addMethods(
5279 function(){
5280     var VISIBILITY = "visibility",
5281         DISPLAY = "display",
5282         HIDDEN = "hidden",
5283         NONE = "none",
5284             XMASKED = "x-masked",
5285                 XMASKEDRELATIVE = "x-masked-relative",
5286         data = Ext.Element.data;
5287
5288         return {
5289                 
5290             isVisible : function(deep) {
5291                 var vis = !this.isStyle(VISIBILITY,HIDDEN) && !this.isStyle(DISPLAY,NONE),
5292                         p = this.dom.parentNode;
5293                 if(deep !== true || !vis){
5294                     return vis;
5295                 }
5296                 while(p && !/^body/i.test(p.tagName)){
5297                     if(!Ext.fly(p, '_isVisible').isVisible()){
5298                         return false;
5299                     }
5300                     p = p.parentNode;
5301                 }
5302                 return true;
5303             },
5304
5305             
5306             isDisplayed : function() {
5307                 return !this.isStyle(DISPLAY, NONE);
5308             },
5309
5310                 
5311             enableDisplayMode : function(display){
5312                 this.setVisibilityMode(Ext.Element.DISPLAY);
5313                 if(!Ext.isEmpty(display)){
5314                 data(this.dom, 'originalDisplay', display);
5315             }
5316                 return this;
5317             },
5318
5319                 
5320             mask : function(msg, msgCls){
5321                     var me = this,
5322                         dom = me.dom,
5323                         dh = Ext.DomHelper,
5324                         EXTELMASKMSG = "ext-el-mask-msg",
5325                 el,
5326                 mask;
5327
5328                 if(!/^body/i.test(dom.tagName) && me.getStyle('position') == 'static'){
5329                     me.addClass(XMASKEDRELATIVE);
5330                 }
5331                 if((el = data(dom, 'maskMsg'))){
5332                     el.remove();
5333                 }
5334                 if((el = data(dom, 'mask'))){
5335                     el.remove();
5336                 }
5337
5338             mask = dh.append(dom, {cls : "ext-el-mask"}, true);
5339                 data(dom, 'mask', mask);
5340
5341                 me.addClass(XMASKED);
5342                 mask.setDisplayed(true);
5343                 if(typeof msg == 'string'){
5344                 var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
5345                 data(dom, 'maskMsg', mm);
5346                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
5347                     mm.dom.firstChild.innerHTML = msg;
5348                     mm.setDisplayed(true);
5349                     mm.center(me);
5350                 }
5351                 if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto'){ 
5352                     mask.setSize(undefined, me.getHeight());
5353                 }
5354                 return mask;
5355             },
5356
5357             
5358             unmask : function(){
5359                     var me = this,
5360                 dom = me.dom,
5361                         mask = data(dom, 'mask'),
5362                         maskMsg = data(dom, 'maskMsg');
5363                 if(mask){
5364                     if(maskMsg){
5365                         maskMsg.remove();
5366                     data(dom, 'maskMsg', undefined);
5367                     }
5368                     mask.remove();
5369                 data(dom, 'mask', undefined);
5370                 }
5371                 if(me.isMasked()){
5372                 me.removeClass([XMASKED, XMASKEDRELATIVE]);
5373             }
5374             },
5375
5376             
5377             isMasked : function(){
5378             var m = data(this.dom, 'mask');
5379                 return m && m.isVisible();
5380             },
5381
5382             
5383             createShim : function(){
5384                 var el = document.createElement('iframe'),
5385                         shim;
5386                 el.frameBorder = '0';
5387                 el.className = 'ext-shim';
5388                 el.src = Ext.SSL_SECURE_URL;
5389                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
5390                 shim.autoBoxAdjust = false;
5391                 return shim;
5392             }
5393     };
5394 }());
5395 Ext.Element.addMethods({
5396     
5397     addKeyListener : function(key, fn, scope){
5398         var config;
5399         if(typeof key != 'object' || Ext.isArray(key)){
5400             config = {
5401                 key: key,
5402                 fn: fn,
5403                 scope: scope
5404             };
5405         }else{
5406             config = {
5407                 key : key.key,
5408                 shift : key.shift,
5409                 ctrl : key.ctrl,
5410                 alt : key.alt,
5411                 fn: fn,
5412                 scope: scope
5413             };
5414         }
5415         return new Ext.KeyMap(this, config);
5416     },
5417
5418     
5419     addKeyMap : function(config){
5420         return new Ext.KeyMap(this, config);
5421     }
5422 });
5423 (function(){
5424     
5425     var NULL = null,
5426         UNDEFINED = undefined,
5427         TRUE = true,
5428         FALSE = false,
5429         SETX = "setX",
5430         SETY = "setY",
5431         SETXY = "setXY",
5432         LEFT = "left",
5433         BOTTOM = "bottom",
5434         TOP = "top",
5435         RIGHT = "right",
5436         HEIGHT = "height",
5437         WIDTH = "width",
5438         POINTS = "points",
5439         HIDDEN = "hidden",
5440         ABSOLUTE = "absolute",
5441         VISIBLE = "visible",
5442         MOTION = "motion",
5443         POSITION = "position",
5444         EASEOUT = "easeOut",
5445         
5446         flyEl = new Ext.Element.Flyweight(),
5447         queues = {},
5448         getObject = function(o){
5449             return o || {};
5450         },
5451         fly = function(dom){
5452             flyEl.dom = dom;
5453             flyEl.id = Ext.id(dom);
5454             return flyEl;
5455         },
5456         
5457         getQueue = function(id){
5458             if(!queues[id]){
5459                 queues[id] = [];
5460             }
5461             return queues[id];
5462         },
5463         setQueue = function(id, value){
5464             queues[id] = value;
5465         };
5466         
5467
5468 Ext.enableFx = TRUE;
5469
5470
5471 Ext.Fx = {
5472     
5473     
5474     
5475     switchStatements : function(key, fn, argHash){
5476         return fn.apply(this, argHash[key]);
5477     },
5478     
5479     
5480     slideIn : function(anchor, o){ 
5481         o = getObject(o);
5482         var me = this,
5483             dom = me.dom,
5484             st = dom.style,
5485             xy,
5486             r,
5487             b,              
5488             wrap,               
5489             after,
5490             st,
5491             args, 
5492             pt,
5493             bw,
5494             bh;
5495             
5496         anchor = anchor || "t";
5497
5498         me.queueFx(o, function(){            
5499             xy = fly(dom).getXY();
5500             
5501             fly(dom).fixDisplay();            
5502             
5503             
5504             r = fly(dom).getFxRestore();      
5505             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5506             b.right = b.x + b.width;
5507             b.bottom = b.y + b.height;
5508             
5509             
5510             fly(dom).setWidth(b.width).setHeight(b.height);            
5511             
5512             
5513             wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
5514             
5515             st.visibility = VISIBLE;
5516             st.position = ABSOLUTE;
5517             
5518             
5519             function after(){
5520                  fly(dom).fxUnwrap(wrap, r.pos, o);
5521                  st.width = r.width;
5522                  st.height = r.height;
5523                  fly(dom).afterFx(o);
5524             }
5525             
5526             
5527             pt = {to: [b.x, b.y]}; 
5528             bw = {to: b.width};
5529             bh = {to: b.height};
5530                 
5531             function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
5532                 var ret = {};
5533                 fly(wrap).setWidth(ww).setHeight(wh);
5534                 if(fly(wrap)[sXY]){
5535                     fly(wrap)[sXY](sXYval);                  
5536                 }
5537                 style[s1] = style[s2] = "0";                    
5538                 if(w){
5539                     ret.width = w
5540                 };
5541                 if(h){
5542                     ret.height = h;
5543                 }
5544                 if(p){
5545                     ret.points = p;
5546                 }
5547                 return ret;
5548             };
5549
5550             args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5551                     t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
5552                     l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
5553                     r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
5554                     b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
5555                     tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
5556                     bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
5557                     br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
5558                     tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
5559                 });
5560             
5561             st.visibility = VISIBLE;
5562             fly(wrap).show();
5563
5564             arguments.callee.anim = fly(wrap).fxanim(args,
5565                 o,
5566                 MOTION,
5567                 .5,
5568                 EASEOUT, 
5569                 after);
5570         });
5571         return me;
5572     },
5573     
5574     
5575     slideOut : function(anchor, o){
5576         o = getObject(o);
5577         var me = this,
5578             dom = me.dom,
5579             st = dom.style,
5580             xy = me.getXY(),
5581             wrap,
5582             r,
5583             b,
5584             a,
5585             zero = {to: 0}; 
5586                     
5587         anchor = anchor || "t";
5588
5589         me.queueFx(o, function(){
5590             
5591             
5592             r = fly(dom).getFxRestore(); 
5593             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5594             b.right = b.x + b.width;
5595             b.bottom = b.y + b.height;
5596                 
5597             
5598             fly(dom).setWidth(b.width).setHeight(b.height);
5599
5600             
5601             wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
5602                 
5603             st.visibility = VISIBLE;
5604             st.position = ABSOLUTE;
5605             fly(wrap).setWidth(b.width).setHeight(b.height);            
5606
5607             function after(){
5608                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
5609                 fly(dom).fxUnwrap(wrap, r.pos, o);
5610                 st.width = r.width;
5611                 st.height = r.height;
5612                 fly(dom).afterFx(o);
5613             }            
5614             
5615             function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
5616                 var ret = {};
5617                 
5618                 style[s1] = style[s2] = "0";
5619                 ret[p1] = v1;               
5620                 if(p2){
5621                     ret[p2] = v2;               
5622                 }
5623                 if(p3){
5624                     ret[p3] = v3;
5625                 }
5626                 
5627                 return ret;
5628             };
5629             
5630             a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5631                 t  : [st, LEFT, BOTTOM, HEIGHT, zero],
5632                 l  : [st, RIGHT, TOP, WIDTH, zero],
5633                 r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
5634                 b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5635                 tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
5636                 bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5637                 br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
5638                 tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
5639             });
5640             
5641             arguments.callee.anim = fly(wrap).fxanim(a,
5642                 o,
5643                 MOTION,
5644                 .5,
5645                 EASEOUT, 
5646                 after);
5647         });
5648         return me;
5649     },
5650
5651     
5652     puff : function(o){
5653         o = getObject(o);
5654         var me = this,
5655             dom = me.dom,
5656             st = dom.style,
5657             width,
5658             height,
5659             r;
5660
5661         me.queueFx(o, function(){
5662             width = fly(dom).getWidth();
5663             height = fly(dom).getHeight();
5664             fly(dom).clearOpacity();
5665             fly(dom).show();
5666
5667             
5668             r = fly(dom).getFxRestore();                   
5669             
5670             function after(){
5671                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
5672                 fly(dom).clearOpacity();  
5673                 fly(dom).setPositioning(r.pos);
5674                 st.width = r.width;
5675                 st.height = r.height;
5676                 st.fontSize = '';
5677                 fly(dom).afterFx(o);
5678             }   
5679
5680             arguments.callee.anim = fly(dom).fxanim({
5681                     width : {to : fly(dom).adjustWidth(width * 2)},
5682                     height : {to : fly(dom).adjustHeight(height * 2)},
5683                     points : {by : [-width * .5, -height * .5]},
5684                     opacity : {to : 0},
5685                     fontSize: {to : 200, unit: "%"}
5686                 },
5687                 o,
5688                 MOTION,
5689                 .5,
5690                 EASEOUT,
5691                  after);
5692         });
5693         return me;
5694     },
5695
5696     
5697     switchOff : function(o){
5698         o = getObject(o);
5699         var me = this,
5700             dom = me.dom,
5701             st = dom.style,
5702             r;
5703
5704         me.queueFx(o, function(){
5705             fly(dom).clearOpacity();
5706             fly(dom).clip();
5707
5708             
5709             r = fly(dom).getFxRestore();
5710                 
5711             function after(){
5712                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
5713                 fly(dom).clearOpacity();
5714                 fly(dom).setPositioning(r.pos);
5715                 st.width = r.width;
5716                 st.height = r.height;   
5717                 fly(dom).afterFx(o);
5718             };
5719
5720             fly(dom).fxanim({opacity : {to : 0.3}}, 
5721                 NULL, 
5722                 NULL, 
5723                 .1, 
5724                 NULL, 
5725                 function(){                                 
5726                     fly(dom).clearOpacity();
5727                         (function(){                            
5728                             fly(dom).fxanim({
5729                                 height : {to : 1},
5730                                 points : {by : [0, fly(dom).getHeight() * .5]}
5731                             }, 
5732                             o, 
5733                             MOTION, 
5734                             0.3, 
5735                             'easeIn', 
5736                             after);
5737                         }).defer(100);
5738                 });
5739         });
5740         return me;
5741     },
5742
5743      
5744     highlight : function(color, o){
5745         o = getObject(o);
5746         var me = this,
5747             dom = me.dom,
5748             attr = o.attr || "backgroundColor",
5749             a = {},
5750             restore;
5751
5752         me.queueFx(o, function(){
5753             fly(dom).clearOpacity();
5754             fly(dom).show();
5755
5756             function after(){
5757                 dom.style[attr] = restore;
5758                 fly(dom).afterFx(o);
5759             }            
5760             restore = dom.style[attr];
5761             a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
5762             arguments.callee.anim = fly(dom).fxanim(a,
5763                 o,
5764                 'color',
5765                 1,
5766                 'easeIn', 
5767                 after);
5768         });
5769         return me;
5770     },
5771
5772    
5773     frame : function(color, count, o){
5774         o = getObject(o);
5775         var me = this,
5776             dom = me.dom,
5777             proxy,
5778             active;
5779
5780         me.queueFx(o, function(){
5781             color = color || '#C3DAF9';
5782             if(color.length == 6){
5783                 color = '#' + color;
5784             }            
5785             count = count || 1;
5786             fly(dom).show();
5787
5788             var xy = fly(dom).getXY(),
5789                 b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
5790                 queue = function(){
5791                     proxy = fly(document.body || document.documentElement).createChild({
5792                         style:{
5793                             position : ABSOLUTE,
5794                             'z-index': 35000, 
5795                             border : '0px solid ' + color
5796                         }
5797                     });
5798                     return proxy.queueFx({}, animFn);
5799                 };
5800             
5801             
5802             arguments.callee.anim = {
5803                 isAnimated: true,
5804                 stop: function() {
5805                     count = 0;
5806                     proxy.stopFx();
5807                 }
5808             };
5809             
5810             function animFn(){
5811                 var scale = Ext.isBorderBox ? 2 : 1;
5812                 active = proxy.anim({
5813                     top : {from : b.y, to : b.y - 20},
5814                     left : {from : b.x, to : b.x - 20},
5815                     borderWidth : {from : 0, to : 10},
5816                     opacity : {from : 1, to : 0},
5817                     height : {from : b.height, to : b.height + 20 * scale},
5818                     width : {from : b.width, to : b.width + 20 * scale}
5819                 },{
5820                     duration: o.duration || 1,
5821                     callback: function() {
5822                         proxy.remove();
5823                         --count > 0 ? queue() : fly(dom).afterFx(o);
5824                     }
5825                 });
5826                 arguments.callee.anim = {
5827                     isAnimated: true,
5828                     stop: function(){
5829                         active.stop();
5830                     }
5831                 };
5832             };
5833             queue();
5834         });
5835         return me;
5836     },
5837
5838    
5839     pause : function(seconds){        
5840         var dom = this.dom,
5841             t;
5842
5843         this.queueFx({}, function(){
5844             t = setTimeout(function(){
5845                 fly(dom).afterFx({});
5846             }, seconds * 1000);
5847             arguments.callee.anim = {
5848                 isAnimated: true,
5849                 stop: function(){
5850                     clearTimeout(t);
5851                     fly(dom).afterFx({});
5852                 }
5853             };
5854         });
5855         return this;
5856     },
5857
5858    
5859     fadeIn : function(o){
5860         o = getObject(o);
5861         var me = this,
5862             dom = me.dom,
5863             to = o.endOpacity || 1;
5864         
5865         me.queueFx(o, function(){
5866             fly(dom).setOpacity(0);
5867             fly(dom).fixDisplay();
5868             dom.style.visibility = VISIBLE;
5869             arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
5870                 o, NULL, .5, EASEOUT, function(){
5871                 if(to == 1){
5872                     fly(dom).clearOpacity();
5873                 }
5874                 fly(dom).afterFx(o);
5875             });
5876         });
5877         return me;
5878     },
5879
5880    
5881     fadeOut : function(o){
5882         o = getObject(o);
5883         var me = this,
5884             dom = me.dom,
5885             style = dom.style,
5886             to = o.endOpacity || 0;         
5887         
5888         me.queueFx(o, function(){  
5889             arguments.callee.anim = fly(dom).fxanim({ 
5890                 opacity : {to : to}},
5891                 o, 
5892                 NULL, 
5893                 .5, 
5894                 EASEOUT, 
5895                 function(){
5896                     if(to == 0){
5897                         Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
5898                             style.display = "none" :
5899                             style.visibility = HIDDEN;
5900                             
5901                         fly(dom).clearOpacity();
5902                     }
5903                     fly(dom).afterFx(o);
5904             });
5905         });
5906         return me;
5907     },
5908
5909    
5910     scale : function(w, h, o){
5911         this.shift(Ext.apply({}, o, {
5912             width: w,
5913             height: h
5914         }));
5915         return this;
5916     },
5917
5918    
5919     shift : function(o){
5920         o = getObject(o);
5921         var dom = this.dom,
5922             a = {};
5923                 
5924         this.queueFx(o, function(){
5925             for (var prop in o) {
5926                 if (o[prop] != UNDEFINED) {                                                 
5927                     a[prop] = {to : o[prop]};                   
5928                 }
5929             } 
5930             
5931             a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
5932             a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
5933             
5934             if (a.x || a.y || a.xy) {
5935                 a.points = a.xy || 
5936                            {to : [ a.x ? a.x.to : fly(dom).getX(),
5937                                    a.y ? a.y.to : fly(dom).getY()]};                  
5938             }
5939
5940             arguments.callee.anim = fly(dom).fxanim(a,
5941                 o, 
5942                 MOTION, 
5943                 .35, 
5944                 EASEOUT, 
5945                 function(){
5946                     fly(dom).afterFx(o);
5947                 });
5948         });
5949         return this;
5950     },
5951
5952     
5953     ghost : function(anchor, o){
5954         o = getObject(o);
5955         var me = this,
5956             dom = me.dom,
5957             st = dom.style,
5958             a = {opacity: {to: 0}, points: {}},
5959             pt = a.points,
5960             r,
5961             w,
5962             h;
5963             
5964         anchor = anchor || "b";
5965
5966         me.queueFx(o, function(){
5967             
5968             r = fly(dom).getFxRestore();
5969             w = fly(dom).getWidth();
5970             h = fly(dom).getHeight();
5971             
5972             function after(){
5973                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
5974                 fly(dom).clearOpacity();
5975                 fly(dom).setPositioning(r.pos);
5976                 st.width = r.width;
5977                 st.height = r.height;
5978                 fly(dom).afterFx(o);
5979             }
5980                 
5981             pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
5982                t  : [0, -h],
5983                l  : [-w, 0],
5984                r  : [w, 0],
5985                b  : [0, h],
5986                tl : [-w, -h],
5987                bl : [-w, h],
5988                br : [w, h],
5989                tr : [w, -h] 
5990             });
5991                 
5992             arguments.callee.anim = fly(dom).fxanim(a,
5993                 o,
5994                 MOTION,
5995                 .5,
5996                 EASEOUT, after);
5997         });
5998         return me;
5999     },
6000
6001     
6002     syncFx : function(){
6003         var me = this;
6004         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
6005             block : FALSE,
6006             concurrent : TRUE,
6007             stopFx : FALSE
6008         });
6009         return me;
6010     },
6011
6012     
6013     sequenceFx : function(){
6014         var me = this;
6015         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
6016             block : FALSE,
6017             concurrent : FALSE,
6018             stopFx : FALSE
6019         });
6020         return me;
6021     },
6022
6023     
6024     nextFx : function(){        
6025         var ef = getQueue(this.dom.id)[0];
6026         if(ef){
6027             ef.call(this);
6028         }
6029     },
6030
6031     
6032     hasActiveFx : function(){
6033         return getQueue(this.dom.id)[0];
6034     },
6035
6036     
6037     stopFx : function(finish){
6038         var me = this,
6039             id = me.dom.id;
6040         if(me.hasActiveFx()){
6041             var cur = getQueue(id)[0];
6042             if(cur && cur.anim){
6043                 if(cur.anim.isAnimated){
6044                     setQueue(id, [cur]); 
6045                     cur.anim.stop(finish !== undefined ? finish : TRUE);
6046                 }else{
6047                     setQueue(id, []);
6048                 }
6049             }
6050         }
6051         return me;
6052     },
6053
6054     
6055     beforeFx : function(o){
6056         if(this.hasActiveFx() && !o.concurrent){
6057            if(o.stopFx){
6058                this.stopFx();
6059                return TRUE;
6060            }
6061            return FALSE;
6062         }
6063         return TRUE;
6064     },
6065
6066     
6067     hasFxBlock : function(){
6068         var q = getQueue(this.dom.id);
6069         return q && q[0] && q[0].block;
6070     },
6071
6072     
6073     queueFx : function(o, fn){
6074         var me = fly(this.dom);
6075         if(!me.hasFxBlock()){
6076             Ext.applyIf(o, me.fxDefaults);
6077             if(!o.concurrent){
6078                 var run = me.beforeFx(o);
6079                 fn.block = o.block;
6080                 getQueue(me.dom.id).push(fn);
6081                 if(run){
6082                     me.nextFx();
6083                 }
6084             }else{
6085                 fn.call(me);
6086             }
6087         }
6088         return me;
6089     },
6090
6091     
6092     fxWrap : function(pos, o, vis){ 
6093         var dom = this.dom,
6094             wrap,
6095             wrapXY;
6096         if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
6097             if(o.fixPosition){
6098                 wrapXY = fly(dom).getXY();
6099             }
6100             var div = document.createElement("div");
6101             div.style.visibility = vis;
6102             wrap = dom.parentNode.insertBefore(div, dom);
6103             fly(wrap).setPositioning(pos);
6104             if(fly(wrap).isStyle(POSITION, "static")){
6105                 fly(wrap).position("relative");
6106             }
6107             fly(dom).clearPositioning('auto');
6108             fly(wrap).clip();
6109             wrap.appendChild(dom);
6110             if(wrapXY){
6111                 fly(wrap).setXY(wrapXY);
6112             }
6113         }
6114         return wrap;
6115     },
6116
6117     
6118     fxUnwrap : function(wrap, pos, o){      
6119         var dom = this.dom;
6120         fly(dom).clearPositioning();
6121         fly(dom).setPositioning(pos);
6122         if(!o.wrap){
6123             var pn = fly(wrap).dom.parentNode;
6124             pn.insertBefore(dom, wrap); 
6125             fly(wrap).remove();
6126         }
6127     },
6128
6129     
6130     getFxRestore : function(){
6131         var st = this.dom.style;
6132         return {pos: this.getPositioning(), width: st.width, height : st.height};
6133     },
6134
6135     
6136     afterFx : function(o){
6137         var dom = this.dom,
6138             id = dom.id;
6139         if(o.afterStyle){
6140             fly(dom).setStyle(o.afterStyle);            
6141         }
6142         if(o.afterCls){
6143             fly(dom).addClass(o.afterCls);
6144         }
6145         if(o.remove == TRUE){
6146             fly(dom).remove();
6147         }
6148         if(o.callback){
6149             o.callback.call(o.scope, fly(dom));
6150         }
6151         if(!o.concurrent){
6152             getQueue(id).shift();
6153             fly(dom).nextFx();
6154         }
6155     },
6156
6157     
6158     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
6159         animType = animType || 'run';
6160         opt = opt || {};
6161         var anim = Ext.lib.Anim[animType](
6162                 this.dom, 
6163                 args,
6164                 (opt.duration || defaultDur) || .35,
6165                 (opt.easing || defaultEase) || EASEOUT,
6166                 cb,            
6167                 this
6168             );
6169         opt.anim = anim;
6170         return anim;
6171     }
6172 };
6173
6174
6175 Ext.Fx.resize = Ext.Fx.scale;
6176
6177
6178
6179 Ext.Element.addMethods(Ext.Fx);
6180 })();
6181
6182 Ext.CompositeElementLite = function(els, root){
6183     
6184     this.elements = [];
6185     this.add(els, root);
6186     this.el = new Ext.Element.Flyweight();
6187 };
6188
6189 Ext.CompositeElementLite.prototype = {
6190     isComposite: true,
6191
6192     
6193     getElement : function(el){
6194         
6195         var e = this.el;
6196         e.dom = el;
6197         e.id = el.id;
6198         return e;
6199     },
6200
6201     
6202     transformElement : function(el){
6203         return Ext.getDom(el);
6204     },
6205
6206     
6207     getCount : function(){
6208         return this.elements.length;
6209     },
6210     
6211     add : function(els, root){
6212         var me = this,
6213             elements = me.elements;
6214         if(!els){
6215             return this;
6216         }
6217         if(typeof els == "string"){
6218             els = Ext.Element.selectorFunction(els, root);
6219         }else if(els.isComposite){
6220             els = els.elements;
6221         }else if(!Ext.isIterable(els)){
6222             els = [els];
6223         }
6224
6225         for(var i = 0, len = els.length; i < len; ++i){
6226             elements.push(me.transformElement(els[i]));
6227         }
6228         return me;
6229     },
6230
6231     invoke : function(fn, args){
6232         var me = this,
6233             els = me.elements,
6234             len = els.length,
6235             e,
6236             i;
6237
6238         for(i = 0; i < len; i++) {
6239             e = els[i];
6240             if(e){
6241                 Ext.Element.prototype[fn].apply(me.getElement(e), args);
6242             }
6243         }
6244         return me;
6245     },
6246     
6247     item : function(index){
6248         var me = this,
6249             el = me.elements[index],
6250             out = null;
6251
6252         if(el){
6253             out = me.getElement(el);
6254         }
6255         return out;
6256     },
6257
6258     
6259     addListener : function(eventName, handler, scope, opt){
6260         var els = this.elements,
6261             len = els.length,
6262             i, e;
6263
6264         for(i = 0; i<len; i++) {
6265             e = els[i];
6266             if(e) {
6267                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
6268             }
6269         }
6270         return this;
6271     },
6272     
6273     each : function(fn, scope){
6274         var me = this,
6275             els = me.elements,
6276             len = els.length,
6277             i, e;
6278
6279         for(i = 0; i<len; i++) {
6280             e = els[i];
6281             if(e){
6282                 e = this.getElement(e);
6283                 if(fn.call(scope || e, e, me, i) === false){
6284                     break;
6285                 }
6286             }
6287         }
6288         return me;
6289     },
6290
6291     
6292     fill : function(els){
6293         var me = this;
6294         me.elements = [];
6295         me.add(els);
6296         return me;
6297     },
6298
6299     
6300     filter : function(selector){
6301         var els = [],
6302             me = this,
6303             fn = Ext.isFunction(selector) ? selector
6304                 : function(el){
6305                     return el.is(selector);
6306                 };
6307
6308         me.each(function(el, self, i) {
6309             if (fn(el, i) !== false) {
6310                 els[els.length] = me.transformElement(el);
6311             }
6312         });
6313         
6314         me.elements = els;
6315         return me;
6316     },
6317
6318     
6319     indexOf : function(el){
6320         return this.elements.indexOf(this.transformElement(el));
6321     },
6322
6323     
6324     replaceElement : function(el, replacement, domReplace){
6325         var index = !isNaN(el) ? el : this.indexOf(el),
6326             d;
6327         if(index > -1){
6328             replacement = Ext.getDom(replacement);
6329             if(domReplace){
6330                 d = this.elements[index];
6331                 d.parentNode.insertBefore(replacement, d);
6332                 Ext.removeNode(d);
6333             }
6334             this.elements.splice(index, 1, replacement);
6335         }
6336         return this;
6337     },
6338
6339     
6340     clear : function(){
6341         this.elements = [];
6342     }
6343 };
6344
6345 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
6346
6347 (function(){
6348 var fnName,
6349     ElProto = Ext.Element.prototype,
6350     CelProto = Ext.CompositeElementLite.prototype;
6351
6352 for(fnName in ElProto){
6353     if(Ext.isFunction(ElProto[fnName])){
6354         (function(fnName){
6355             CelProto[fnName] = CelProto[fnName] || function(){
6356                 return this.invoke(fnName, arguments);
6357             };
6358         }).call(CelProto, fnName);
6359
6360     }
6361 }
6362 })();
6363
6364 if(Ext.DomQuery){
6365     Ext.Element.selectorFunction = Ext.DomQuery.select;
6366 }
6367
6368
6369 Ext.Element.select = function(selector, root){
6370     var els;
6371     if(typeof selector == "string"){
6372         els = Ext.Element.selectorFunction(selector, root);
6373     }else if(selector.length !== undefined){
6374         els = selector;
6375     }else{
6376         throw "Invalid selector";
6377     }
6378     return new Ext.CompositeElementLite(els);
6379 };
6380
6381 Ext.select = Ext.Element.select;
6382
6383 Ext.apply(Ext.CompositeElementLite.prototype, {
6384     addElements : function(els, root){
6385         if(!els){
6386             return this;
6387         }
6388         if(typeof els == "string"){
6389             els = Ext.Element.selectorFunction(els, root);
6390         }
6391         var yels = this.elements;
6392         Ext.each(els, function(e) {
6393             yels.push(Ext.get(e));
6394         });
6395         return this;
6396     },
6397
6398     
6399     first : function(){
6400         return this.item(0);
6401     },
6402
6403     
6404     last : function(){
6405         return this.item(this.getCount()-1);
6406     },
6407
6408     
6409     contains : function(el){
6410         return this.indexOf(el) != -1;
6411     },
6412
6413     
6414     removeElement : function(keys, removeDom){
6415         var me = this,
6416             els = this.elements,
6417             el;
6418         Ext.each(keys, function(val){
6419             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
6420                 if(removeDom){
6421                     if(el.dom){
6422                         el.remove();
6423                     }else{
6424                         Ext.removeNode(el);
6425                     }
6426                 }
6427                 els.splice(val, 1);
6428             }
6429         });
6430         return this;
6431     }
6432 });
6433
6434 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
6435     
6436     constructor : function(els, root){
6437         this.elements = [];
6438         this.add(els, root);
6439     },
6440     
6441     
6442     getElement : function(el){
6443         
6444         return el;
6445     },
6446     
6447     
6448     transformElement : function(el){
6449         return Ext.get(el);
6450     }
6451
6452     
6453
6454     
6455
6456     
6457 });
6458
6459
6460 Ext.Element.select = function(selector, unique, root){
6461     var els;
6462     if(typeof selector == "string"){
6463         els = Ext.Element.selectorFunction(selector, root);
6464     }else if(selector.length !== undefined){
6465         els = selector;
6466     }else{
6467         throw "Invalid selector";
6468     }
6469
6470     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
6471 };
6472
6473
6474 Ext.select = Ext.Element.select;(function(){
6475     var BEFOREREQUEST = "beforerequest",
6476         REQUESTCOMPLETE = "requestcomplete",
6477         REQUESTEXCEPTION = "requestexception",
6478         UNDEFINED = undefined,
6479         LOAD = 'load',
6480         POST = 'POST',
6481         GET = 'GET',
6482         WINDOW = window;
6483
6484     
6485     Ext.data.Connection = function(config){
6486         Ext.apply(this, config);
6487         this.addEvents(
6488             
6489             BEFOREREQUEST,
6490             
6491             REQUESTCOMPLETE,
6492             
6493             REQUESTEXCEPTION
6494         );
6495         Ext.data.Connection.superclass.constructor.call(this);
6496     };
6497
6498     Ext.extend(Ext.data.Connection, Ext.util.Observable, {
6499         
6500         
6501         
6502         
6503         
6504         timeout : 30000,
6505         
6506         autoAbort:false,
6507
6508         
6509         disableCaching: true,
6510
6511         
6512         disableCachingParam: '_dc',
6513
6514         
6515         request : function(o){
6516             var me = this;
6517             if(me.fireEvent(BEFOREREQUEST, me, o)){
6518                 if (o.el) {
6519                     if(!Ext.isEmpty(o.indicatorText)){
6520                         me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
6521                     }
6522                     if(me.indicatorText) {
6523                         Ext.getDom(o.el).innerHTML = me.indicatorText;
6524                     }
6525                     o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
6526                         Ext.getDom(o.el).innerHTML = response.responseText;
6527                     });
6528                 }
6529
6530                 var p = o.params,
6531                     url = o.url || me.url,
6532                     method,
6533                     cb = {success: me.handleResponse,
6534                           failure: me.handleFailure,
6535                           scope: me,
6536                           argument: {options: o},
6537                           timeout : o.timeout || me.timeout
6538                     },
6539                     form,
6540                     serForm;
6541
6542
6543                 if (Ext.isFunction(p)) {
6544                     p = p.call(o.scope||WINDOW, o);
6545                 }
6546
6547                 p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
6548
6549                 if (Ext.isFunction(url)) {
6550                     url = url.call(o.scope || WINDOW, o);
6551                 }
6552
6553                 if((form = Ext.getDom(o.form))){
6554                     url = url || form.action;
6555                      if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) {
6556                          return me.doFormUpload.call(me, o, p, url);
6557                      }
6558                     serForm = Ext.lib.Ajax.serializeForm(form);
6559                     p = p ? (p + '&' + serForm) : serForm;
6560                 }
6561
6562                 method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
6563
6564                 if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
6565                     var dcp = o.disableCachingParam || me.disableCachingParam;
6566                     url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
6567                 }
6568
6569                 o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
6570
6571                 if(o.autoAbort === true || me.autoAbort) {
6572                     me.abort();
6573                 }
6574
6575                 if((method == GET || o.xmlData || o.jsonData) && p){
6576                     url = Ext.urlAppend(url, p);
6577                     p = '';
6578                 }
6579                 return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
6580             }else{
6581                 return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
6582             }
6583         },
6584
6585         
6586         isLoading : function(transId){
6587             return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
6588         },
6589
6590         
6591         abort : function(transId){
6592             if(transId || this.isLoading()){
6593                 Ext.lib.Ajax.abort(transId || this.transId);
6594             }
6595         },
6596
6597         
6598         handleResponse : function(response){
6599             this.transId = false;
6600             var options = response.argument.options;
6601             response.argument = options ? options.argument : null;
6602             this.fireEvent(REQUESTCOMPLETE, this, response, options);
6603             if(options.success){
6604                 options.success.call(options.scope, response, options);
6605             }
6606             if(options.callback){
6607                 options.callback.call(options.scope, options, true, response);
6608             }
6609         },
6610
6611         
6612         handleFailure : function(response, e){
6613             this.transId = false;
6614             var options = response.argument.options;
6615             response.argument = options ? options.argument : null;
6616             this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
6617             if(options.failure){
6618                 options.failure.call(options.scope, response, options);
6619             }
6620             if(options.callback){
6621                 options.callback.call(options.scope, options, false, response);
6622             }
6623         },
6624
6625         
6626         doFormUpload : function(o, ps, url){
6627             var id = Ext.id(),
6628                 doc = document,
6629                 frame = doc.createElement('iframe'),
6630                 form = Ext.getDom(o.form),
6631                 hiddens = [],
6632                 hd,
6633                 encoding = 'multipart/form-data',
6634                 buf = {
6635                     target: form.target,
6636                     method: form.method,
6637                     encoding: form.encoding,
6638                     enctype: form.enctype,
6639                     action: form.action
6640                 };
6641
6642             
6643             Ext.fly(frame).set({
6644                 id: id,
6645                 name: id,
6646                 cls: 'x-hidden',
6647                 src: Ext.SSL_SECURE_URL
6648             }); 
6649
6650             doc.body.appendChild(frame);
6651
6652             
6653             if(Ext.isIE){
6654                document.frames[id].name = id;
6655             }
6656
6657
6658             Ext.fly(form).set({
6659                 target: id,
6660                 method: POST,
6661                 enctype: encoding,
6662                 encoding: encoding,
6663                 action: url || buf.action
6664             });
6665
6666             
6667             Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
6668                 hd = doc.createElement('input');
6669                 Ext.fly(hd).set({
6670                     type: 'hidden',
6671                     value: v,
6672                     name: k
6673                 });
6674                 form.appendChild(hd);
6675                 hiddens.push(hd);
6676             });
6677
6678             function cb(){
6679                 var me = this,
6680                     
6681                     r = {responseText : '',
6682                          responseXML : null,
6683                          argument : o.argument},
6684                     doc,
6685                     firstChild;
6686
6687                 try{
6688                     doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
6689                     if(doc){
6690                         if(doc.body){
6691                             if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
6692                                 r.responseText = firstChild.value;
6693                             }else{
6694                                 r.responseText = doc.body.innerHTML;
6695                             }
6696                         }
6697                         
6698                         r.responseXML = doc.XMLDocument || doc;
6699                     }
6700                 }
6701                 catch(e) {}
6702
6703                 Ext.EventManager.removeListener(frame, LOAD, cb, me);
6704
6705                 me.fireEvent(REQUESTCOMPLETE, me, r, o);
6706
6707                 function runCallback(fn, scope, args){
6708                     if(Ext.isFunction(fn)){
6709                         fn.apply(scope, args);
6710                     }
6711                 }
6712
6713                 runCallback(o.success, o.scope, [r, o]);
6714                 runCallback(o.callback, o.scope, [o, true, r]);
6715
6716                 if(!me.debugUploads){
6717                     setTimeout(function(){Ext.removeNode(frame);}, 100);
6718                 }
6719             }
6720
6721             Ext.EventManager.on(frame, LOAD, cb, this);
6722             form.submit();
6723
6724             Ext.fly(form).set(buf);
6725             Ext.each(hiddens, function(h) {
6726                 Ext.removeNode(h);
6727             });
6728         }
6729     });
6730 })();
6731
6732
6733 Ext.Ajax = new Ext.data.Connection({
6734     
6735     
6736     
6737     
6738     
6739     
6740
6741     
6742
6743     
6744     
6745     
6746     
6747     
6748     
6749
6750     
6751     autoAbort : false,
6752
6753     
6754     serializeForm : function(form){
6755         return Ext.lib.Ajax.serializeForm(form);
6756     }
6757 });
6758
6759 Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
6760 function() {
6761     var BEFOREUPDATE = "beforeupdate",
6762         UPDATE = "update",
6763         FAILURE = "failure";
6764
6765     
6766     function processSuccess(response){
6767         var me = this;
6768         me.transaction = null;
6769         if (response.argument.form && response.argument.reset) {
6770             try { 
6771                 response.argument.form.reset();
6772             } catch(e){}
6773         }
6774         if (me.loadScripts) {
6775             me.renderer.render(me.el, response, me,
6776                updateComplete.createDelegate(me, [response]));
6777         } else {
6778             me.renderer.render(me.el, response, me);
6779             updateComplete.call(me, response);
6780         }
6781     }
6782
6783     
6784     function updateComplete(response, type, success){
6785         this.fireEvent(type || UPDATE, this.el, response);
6786         if(Ext.isFunction(response.argument.callback)){
6787             response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
6788         }
6789     }
6790
6791     
6792     function processFailure(response){
6793         updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
6794     }
6795
6796     return {
6797         constructor: function(el, forceNew){
6798             var me = this;
6799             el = Ext.get(el);
6800             if(!forceNew && el.updateManager){
6801                 return el.updateManager;
6802             }
6803             
6804             me.el = el;
6805             
6806             me.defaultUrl = null;
6807
6808             me.addEvents(
6809                 
6810                 BEFOREUPDATE,
6811                 
6812                 UPDATE,
6813                 
6814                 FAILURE
6815             );
6816
6817             Ext.apply(me, Ext.Updater.defaults);
6818             
6819             
6820             
6821             
6822             
6823             
6824
6825             
6826             me.transaction = null;
6827             
6828             me.refreshDelegate = me.refresh.createDelegate(me);
6829             
6830             me.updateDelegate = me.update.createDelegate(me);
6831             
6832             me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
6833
6834             
6835             me.renderer = me.renderer || me.getDefaultRenderer();
6836
6837             Ext.Updater.superclass.constructor.call(me);
6838         },
6839
6840         
6841         setRenderer : function(renderer){
6842             this.renderer = renderer;
6843         },
6844
6845         
6846         getRenderer : function(){
6847            return this.renderer;
6848         },
6849
6850         
6851         getDefaultRenderer: function() {
6852             return new Ext.Updater.BasicRenderer();
6853         },
6854
6855         
6856         setDefaultUrl : function(defaultUrl){
6857             this.defaultUrl = defaultUrl;
6858         },
6859
6860         
6861         getEl : function(){
6862             return this.el;
6863         },
6864
6865         
6866         update : function(url, params, callback, discardUrl){
6867             var me = this,
6868                 cfg,
6869                 callerScope;
6870
6871             if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
6872                 if(Ext.isObject(url)){ 
6873                     cfg = url;
6874                     url = cfg.url;
6875                     params = params || cfg.params;
6876                     callback = callback || cfg.callback;
6877                     discardUrl = discardUrl || cfg.discardUrl;
6878                     callerScope = cfg.scope;
6879                     if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
6880                     if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
6881                     if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
6882                     if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
6883                 }
6884                 me.showLoading();
6885
6886                 if(!discardUrl){
6887                     me.defaultUrl = url;
6888                 }
6889                 if(Ext.isFunction(url)){
6890                     url = url.call(me);
6891                 }
6892
6893                 var o = Ext.apply({}, {
6894                     url : url,
6895                     params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
6896                     success: processSuccess,
6897                     failure: processFailure,
6898                     scope: me,
6899                     callback: undefined,
6900                     timeout: (me.timeout*1000),
6901                     disableCaching: me.disableCaching,
6902                     argument: {
6903                         "options": cfg,
6904                         "url": url,
6905                         "form": null,
6906                         "callback": callback,
6907                         "scope": callerScope || window,
6908                         "params": params
6909                     }
6910                 }, cfg);
6911
6912                 me.transaction = Ext.Ajax.request(o);
6913             }
6914         },
6915
6916         
6917         formUpdate : function(form, url, reset, callback){
6918             var me = this;
6919             if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
6920                 if(Ext.isFunction(url)){
6921                     url = url.call(me);
6922                 }
6923                 form = Ext.getDom(form);
6924                 me.transaction = Ext.Ajax.request({
6925                     form: form,
6926                     url:url,
6927                     success: processSuccess,
6928                     failure: processFailure,
6929                     scope: me,
6930                     timeout: (me.timeout*1000),
6931                     argument: {
6932                         "url": url,
6933                         "form": form,
6934                         "callback": callback,
6935                         "reset": reset
6936                     }
6937                 });
6938                 me.showLoading.defer(1, me);
6939             }
6940         },
6941
6942         
6943         startAutoRefresh : function(interval, url, params, callback, refreshNow){
6944             var me = this;
6945             if(refreshNow){
6946                 me.update(url || me.defaultUrl, params, callback, true);
6947             }
6948             if(me.autoRefreshProcId){
6949                 clearInterval(me.autoRefreshProcId);
6950             }
6951             me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
6952         },
6953
6954         
6955         stopAutoRefresh : function(){
6956             if(this.autoRefreshProcId){
6957                 clearInterval(this.autoRefreshProcId);
6958                 delete this.autoRefreshProcId;
6959             }
6960         },
6961
6962         
6963         isAutoRefreshing : function(){
6964            return !!this.autoRefreshProcId;
6965         },
6966
6967         
6968         showLoading : function(){
6969             if(this.showLoadIndicator){
6970                 this.el.dom.innerHTML = this.indicatorText;
6971             }
6972         },
6973
6974         
6975         abort : function(){
6976             if(this.transaction){
6977                 Ext.Ajax.abort(this.transaction);
6978             }
6979         },
6980
6981         
6982         isUpdating : function(){
6983             return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
6984         },
6985
6986         
6987         refresh : function(callback){
6988             if(this.defaultUrl){
6989                 this.update(this.defaultUrl, null, callback, true);
6990             }
6991         }
6992     }
6993 }());
6994
6995
6996 Ext.Updater.defaults = {
6997    
6998     timeout : 30,
6999     
7000     disableCaching : false,
7001     
7002     showLoadIndicator : true,
7003     
7004     indicatorText : '<div class="loading-indicator">Loading...</div>',
7005      
7006     loadScripts : false,
7007     
7008     sslBlankUrl : Ext.SSL_SECURE_URL
7009 };
7010
7011
7012
7013 Ext.Updater.updateElement = function(el, url, params, options){
7014     var um = Ext.get(el).getUpdater();
7015     Ext.apply(um, options);
7016     um.update(url, params, options ? options.callback : null);
7017 };
7018
7019
7020 Ext.Updater.BasicRenderer = function(){};
7021
7022 Ext.Updater.BasicRenderer.prototype = {
7023     
7024      render : function(el, response, updateManager, callback){
7025         el.update(response.responseText, updateManager.loadScripts, callback);
7026     }
7027 };
7028
7029
7030
7031 (function() {
7032
7033
7034 Date.useStrict = false;
7035
7036
7037
7038
7039
7040 function xf(format) {
7041     var args = Array.prototype.slice.call(arguments, 1);
7042     return format.replace(/\{(\d+)\}/g, function(m, i) {
7043         return args[i];
7044     });
7045 }
7046
7047
7048
7049 Date.formatCodeToRegex = function(character, currentGroup) {
7050     
7051     var p = Date.parseCodes[character];
7052
7053     if (p) {
7054       p = typeof p == 'function'? p() : p;
7055       Date.parseCodes[character] = p; 
7056     }
7057
7058     return p ? Ext.applyIf({
7059       c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
7060     }, p) : {
7061         g:0,
7062         c:null,
7063         s:Ext.escapeRe(character) 
7064     }
7065 };
7066
7067
7068 var $f = Date.formatCodeToRegex;
7069
7070 Ext.apply(Date, {
7071     
7072     parseFunctions: {
7073         "M$": function(input, strict) {
7074             
7075             
7076             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
7077             var r = (input || '').match(re);
7078             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
7079         }
7080     },
7081     parseRegexes: [],
7082
7083     
7084     formatFunctions: {
7085         "M$": function() {
7086             
7087             return '\\/Date(' + this.getTime() + ')\\/';
7088         }
7089     },
7090
7091     y2kYear : 50,
7092
7093     
7094     MILLI : "ms",
7095
7096     
7097     SECOND : "s",
7098
7099     
7100     MINUTE : "mi",
7101
7102     
7103     HOUR : "h",
7104
7105     
7106     DAY : "d",
7107
7108     
7109     MONTH : "mo",
7110
7111     
7112     YEAR : "y",
7113
7114     
7115     defaults: {},
7116
7117     
7118     dayNames : [
7119         "Sunday",
7120         "Monday",
7121         "Tuesday",
7122         "Wednesday",
7123         "Thursday",
7124         "Friday",
7125         "Saturday"
7126     ],
7127
7128     
7129     monthNames : [
7130         "January",
7131         "February",
7132         "March",
7133         "April",
7134         "May",
7135         "June",
7136         "July",
7137         "August",
7138         "September",
7139         "October",
7140         "November",
7141         "December"
7142     ],
7143
7144     
7145     monthNumbers : {
7146         Jan:0,
7147         Feb:1,
7148         Mar:2,
7149         Apr:3,
7150         May:4,
7151         Jun:5,
7152         Jul:6,
7153         Aug:7,
7154         Sep:8,
7155         Oct:9,
7156         Nov:10,
7157         Dec:11
7158     },
7159
7160     
7161     getShortMonthName : function(month) {
7162         return Date.monthNames[month].substring(0, 3);
7163     },
7164
7165     
7166     getShortDayName : function(day) {
7167         return Date.dayNames[day].substring(0, 3);
7168     },
7169
7170     
7171     getMonthNumber : function(name) {
7172         
7173         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
7174     },
7175
7176     
7177     formatCodes : {
7178         d: "String.leftPad(this.getDate(), 2, '0')",
7179         D: "Date.getShortDayName(this.getDay())", 
7180         j: "this.getDate()",
7181         l: "Date.dayNames[this.getDay()]",
7182         N: "(this.getDay() ? this.getDay() : 7)",
7183         S: "this.getSuffix()",
7184         w: "this.getDay()",
7185         z: "this.getDayOfYear()",
7186         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
7187         F: "Date.monthNames[this.getMonth()]",
7188         m: "String.leftPad(this.getMonth() + 1, 2, '0')",
7189         M: "Date.getShortMonthName(this.getMonth())", 
7190         n: "(this.getMonth() + 1)",
7191         t: "this.getDaysInMonth()",
7192         L: "(this.isLeapYear() ? 1 : 0)",
7193         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
7194         Y: "this.getFullYear()",
7195         y: "('' + this.getFullYear()).substring(2, 4)",
7196         a: "(this.getHours() < 12 ? 'am' : 'pm')",
7197         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
7198         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
7199         G: "this.getHours()",
7200         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
7201         H: "String.leftPad(this.getHours(), 2, '0')",
7202         i: "String.leftPad(this.getMinutes(), 2, '0')",
7203         s: "String.leftPad(this.getSeconds(), 2, '0')",
7204         u: "String.leftPad(this.getMilliseconds(), 3, '0')",
7205         O: "this.getGMTOffset()",
7206         P: "this.getGMTOffset(true)",
7207         T: "this.getTimezone()",
7208         Z: "(this.getTimezoneOffset() * -60)",
7209
7210         c: function() { 
7211             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
7212                 var e = c.charAt(i);
7213                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
7214             }
7215             return code.join(" + ");
7216         },
7217         
7218
7219         U: "Math.round(this.getTime() / 1000)"
7220     },
7221
7222     
7223     isValid : function(y, m, d, h, i, s, ms) {
7224         
7225         h = h || 0;
7226         i = i || 0;
7227         s = s || 0;
7228         ms = ms || 0;
7229
7230         var dt = new Date(y, m - 1, d, h, i, s, ms);
7231
7232         return y == dt.getFullYear() &&
7233             m == dt.getMonth() + 1 &&
7234             d == dt.getDate() &&
7235             h == dt.getHours() &&
7236             i == dt.getMinutes() &&
7237             s == dt.getSeconds() &&
7238             ms == dt.getMilliseconds();
7239     },
7240
7241     
7242     parseDate : function(input, format, strict) {
7243         var p = Date.parseFunctions;
7244         if (p[format] == null) {
7245             Date.createParser(format);
7246         }
7247         return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
7248     },
7249
7250     
7251     getFormatCode : function(character) {
7252         var f = Date.formatCodes[character];
7253
7254         if (f) {
7255           f = typeof f == 'function'? f() : f;
7256           Date.formatCodes[character] = f; 
7257         }
7258
7259         
7260         return f || ("'" + String.escape(character) + "'");
7261     },
7262
7263     
7264     createFormat : function(format) {
7265         var code = [],
7266             special = false,
7267             ch = '';
7268
7269         for (var i = 0; i < format.length; ++i) {
7270             ch = format.charAt(i);
7271             if (!special && ch == "\\") {
7272                 special = true;
7273             } else if (special) {
7274                 special = false;
7275                 code.push("'" + String.escape(ch) + "'");
7276             } else {
7277                 code.push(Date.getFormatCode(ch))
7278             }
7279         }
7280         Date.formatFunctions[format] = new Function("return " + code.join('+'));
7281     },
7282
7283     
7284     createParser : function() {
7285         var code = [
7286             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
7287                 "def = Date.defaults,",
7288                 "results = String(input).match(Date.parseRegexes[{0}]);", 
7289
7290             "if(results){",
7291                 "{1}",
7292
7293                 "if(u != null){", 
7294                     "v = new Date(u * 1000);", 
7295                 "}else{",
7296                     
7297                     
7298                     
7299                     "dt = (new Date()).clearTime();",
7300
7301                     
7302                     "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
7303                     "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
7304                     "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
7305
7306                     
7307                     "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
7308                     "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
7309                     "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
7310                     "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
7311
7312                     "if(z >= 0 && y >= 0){",
7313                         
7314                         
7315
7316                         
7317                         "v = new Date(y, 0, 1, h, i, s, ms);",
7318
7319                         
7320                         "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
7321                     "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
7322                         "v = null;", 
7323                     "}else{",
7324                         
7325                         "v = new Date(y, m, d, h, i, s, ms);",
7326                     "}",
7327                 "}",
7328             "}",
7329
7330             "if(v){",
7331                 
7332                 "if(zz != null){",
7333                     
7334                     "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
7335                 "}else if(o){",
7336                     
7337                     "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
7338                 "}",
7339             "}",
7340
7341             "return v;"
7342         ].join('\n');
7343
7344         return function(format) {
7345             var regexNum = Date.parseRegexes.length,
7346                 currentGroup = 1,
7347                 calc = [],
7348                 regex = [],
7349                 special = false,
7350                 ch = "";
7351
7352             for (var i = 0; i < format.length; ++i) {
7353                 ch = format.charAt(i);
7354                 if (!special && ch == "\\") {
7355                     special = true;
7356                 } else if (special) {
7357                     special = false;
7358                     regex.push(String.escape(ch));
7359                 } else {
7360                     var obj = $f(ch, currentGroup);
7361                     currentGroup += obj.g;
7362                     regex.push(obj.s);
7363                     if (obj.g && obj.c) {
7364                         calc.push(obj.c);
7365                     }
7366                 }
7367             }
7368
7369             Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$");
7370             Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
7371         }
7372     }(),
7373
7374     
7375     parseCodes : {
7376         
7377         d: {
7378             g:1,
7379             c:"d = parseInt(results[{0}], 10);\n",
7380             s:"(\\d{2})" 
7381         },
7382         j: {
7383             g:1,
7384             c:"d = parseInt(results[{0}], 10);\n",
7385             s:"(\\d{1,2})" 
7386         },
7387         D: function() {
7388             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
7389             return {
7390                 g:0,
7391                 c:null,
7392                 s:"(?:" + a.join("|") +")"
7393             }
7394         },
7395         l: function() {
7396             return {
7397                 g:0,
7398                 c:null,
7399                 s:"(?:" + Date.dayNames.join("|") + ")"
7400             }
7401         },
7402         N: {
7403             g:0,
7404             c:null,
7405             s:"[1-7]" 
7406         },
7407         S: {
7408             g:0,
7409             c:null,
7410             s:"(?:st|nd|rd|th)"
7411         },
7412         w: {
7413             g:0,
7414             c:null,
7415             s:"[0-6]" 
7416         },
7417         z: {
7418             g:1,
7419             c:"z = parseInt(results[{0}], 10);\n",
7420             s:"(\\d{1,3})" 
7421         },
7422         W: {
7423             g:0,
7424             c:null,
7425             s:"(?:\\d{2})" 
7426         },
7427         F: function() {
7428             return {
7429                 g:1,
7430                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
7431                 s:"(" + Date.monthNames.join("|") + ")"
7432             }
7433         },
7434         M: function() {
7435             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
7436             return Ext.applyIf({
7437                 s:"(" + a.join("|") + ")"
7438             }, $f("F"));
7439         },
7440         m: {
7441             g:1,
7442             c:"m = parseInt(results[{0}], 10) - 1;\n",
7443             s:"(\\d{2})" 
7444         },
7445         n: {
7446             g:1,
7447             c:"m = parseInt(results[{0}], 10) - 1;\n",
7448             s:"(\\d{1,2})" 
7449         },
7450         t: {
7451             g:0,
7452             c:null,
7453             s:"(?:\\d{2})" 
7454         },
7455         L: {
7456             g:0,
7457             c:null,
7458             s:"(?:1|0)"
7459         },
7460         o: function() {
7461             return $f("Y");
7462         },
7463         Y: {
7464             g:1,
7465             c:"y = parseInt(results[{0}], 10);\n",
7466             s:"(\\d{4})" 
7467         },
7468         y: {
7469             g:1,
7470             c:"var ty = parseInt(results[{0}], 10);\n"
7471                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
7472             s:"(\\d{1,2})"
7473         },
7474         a: {
7475             g:1,
7476             c:"if (results[{0}] == 'am') {\n"
7477                 + "if (!h || h == 12) { h = 0; }\n"
7478                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7479             s:"(am|pm)"
7480         },
7481         A: {
7482             g:1,
7483             c:"if (results[{0}] == 'AM') {\n"
7484                 + "if (!h || h == 12) { h = 0; }\n"
7485                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7486             s:"(AM|PM)"
7487         },
7488         g: function() {
7489             return $f("G");
7490         },
7491         G: {
7492             g:1,
7493             c:"h = parseInt(results[{0}], 10);\n",
7494             s:"(\\d{1,2})" 
7495         },
7496         h: function() {
7497             return $f("H");
7498         },
7499         H: {
7500             g:1,
7501             c:"h = parseInt(results[{0}], 10);\n",
7502             s:"(\\d{2})" 
7503         },
7504         i: {
7505             g:1,
7506             c:"i = parseInt(results[{0}], 10);\n",
7507             s:"(\\d{2})" 
7508         },
7509         s: {
7510             g:1,
7511             c:"s = parseInt(results[{0}], 10);\n",
7512             s:"(\\d{2})" 
7513         },
7514         u: {
7515             g:1,
7516             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
7517             s:"(\\d+)" 
7518         },
7519         O: {
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(3,5) / 60),", 
7525                     "mn = o.substring(3,5) % 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{4})" 
7529         },
7530         P: {
7531             g:1,
7532             c:[
7533                 "o = results[{0}];",
7534                 "var sn = o.substring(0,1),", 
7535                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
7536                     "mn = o.substring(4,6) % 60;", 
7537                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
7538             ].join("\n"),
7539             s: "([+\-]\\d{2}:\\d{2})" 
7540         },
7541         T: {
7542             g:0,
7543             c:null,
7544             s:"[A-Z]{1,4}" 
7545         },
7546         Z: {
7547             g:1,
7548             c:"zz = results[{0}] * 1;\n" 
7549                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
7550             s:"([+\-]?\\d{1,5})" 
7551         },
7552         c: function() {
7553             var calc = [],
7554                 arr = [
7555                     $f("Y", 1), 
7556                     $f("m", 2), 
7557                     $f("d", 3), 
7558                     $f("h", 4), 
7559                     $f("i", 5), 
7560                     $f("s", 6), 
7561                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
7562                     {c:[ 
7563                         "if(results[8]) {", 
7564                             "if(results[8] == 'Z'){",
7565                                 "zz = 0;", 
7566                             "}else if (results[8].indexOf(':') > -1){",
7567                                 $f("P", 8).c, 
7568                             "}else{",
7569                                 $f("O", 8).c, 
7570                             "}",
7571                         "}"
7572                     ].join('\n')}
7573                 ];
7574
7575             for (var i = 0, l = arr.length; i < l; ++i) {
7576                 calc.push(arr[i].c);
7577             }
7578
7579             return {
7580                 g:1,
7581                 c:calc.join(""),
7582                 s:[
7583                     arr[0].s, 
7584                     "(?:", "-", arr[1].s, 
7585                         "(?:", "-", arr[2].s, 
7586                             "(?:",
7587                                 "(?:T| )?", 
7588                                 arr[3].s, ":", arr[4].s,  
7589                                 "(?::", arr[5].s, ")?", 
7590                                 "(?:(?:\\.|,)(\\d+))?", 
7591                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
7592                             ")?",
7593                         ")?",
7594                     ")?"
7595                 ].join("")
7596             }
7597         },
7598         U: {
7599             g:1,
7600             c:"u = parseInt(results[{0}], 10);\n",
7601             s:"(-?\\d+)" 
7602         }
7603     }
7604 });
7605
7606 }());
7607
7608 Ext.apply(Date.prototype, {
7609     
7610     dateFormat : function(format) {
7611         if (Date.formatFunctions[format] == null) {
7612             Date.createFormat(format);
7613         }
7614         return Date.formatFunctions[format].call(this);
7615     },
7616
7617     
7618     getTimezone : function() {
7619         
7620         
7621         
7622         
7623         
7624         
7625         
7626         
7627         
7628         
7629         
7630         
7631         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
7632     },
7633
7634     
7635     getGMTOffset : function(colon) {
7636         return (this.getTimezoneOffset() > 0 ? "-" : "+")
7637             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
7638             + (colon ? ":" : "")
7639             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
7640     },
7641
7642     
7643     getDayOfYear: function() {
7644         var num = 0,
7645             d = this.clone(),
7646             m = this.getMonth(),
7647             i;
7648
7649         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
7650             num += d.getDaysInMonth();
7651         }
7652         return num + this.getDate() - 1;
7653     },
7654
7655     
7656     getWeekOfYear : function() {
7657         
7658         var ms1d = 864e5, 
7659             ms7d = 7 * ms1d; 
7660
7661         return function() { 
7662             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
7663                 AWN = Math.floor(DC3 / 7), 
7664                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
7665
7666             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
7667         }
7668     }(),
7669
7670     
7671     isLeapYear : function() {
7672         var year = this.getFullYear();
7673         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
7674     },
7675
7676     
7677     getFirstDayOfMonth : function() {
7678         var day = (this.getDay() - (this.getDate() - 1)) % 7;
7679         return (day < 0) ? (day + 7) : day;
7680     },
7681
7682     
7683     getLastDayOfMonth : function() {
7684         return this.getLastDateOfMonth().getDay();
7685     },
7686
7687
7688     
7689     getFirstDateOfMonth : function() {
7690         return new Date(this.getFullYear(), this.getMonth(), 1);
7691     },
7692
7693     
7694     getLastDateOfMonth : function() {
7695         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
7696     },
7697
7698     
7699     getDaysInMonth: function() {
7700         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
7701
7702         return function() { 
7703             var m = this.getMonth();
7704
7705             return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
7706         }
7707     }(),
7708
7709     
7710     getSuffix : function() {
7711         switch (this.getDate()) {
7712             case 1:
7713             case 21:
7714             case 31:
7715                 return "st";
7716             case 2:
7717             case 22:
7718                 return "nd";
7719             case 3:
7720             case 23:
7721                 return "rd";
7722             default:
7723                 return "th";
7724         }
7725     },
7726
7727     
7728     clone : function() {
7729         return new Date(this.getTime());
7730     },
7731
7732     
7733     isDST : function() {
7734         
7735         
7736         return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
7737     },
7738
7739     
7740     clearTime : function(clone) {
7741         if (clone) {
7742             return this.clone().clearTime();
7743         }
7744
7745         
7746         var d = this.getDate();
7747
7748         
7749         this.setHours(0);
7750         this.setMinutes(0);
7751         this.setSeconds(0);
7752         this.setMilliseconds(0);
7753
7754         if (this.getDate() != d) { 
7755             
7756             
7757
7758             
7759             for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
7760
7761             this.setDate(d);
7762             this.setHours(c.getHours());
7763         }
7764
7765         return this;
7766     },
7767
7768     
7769     add : function(interval, value) {
7770         var d = this.clone();
7771         if (!interval || value === 0) return d;
7772
7773         switch(interval.toLowerCase()) {
7774             case Date.MILLI:
7775                 d.setMilliseconds(this.getMilliseconds() + value);
7776                 break;
7777             case Date.SECOND:
7778                 d.setSeconds(this.getSeconds() + value);
7779                 break;
7780             case Date.MINUTE:
7781                 d.setMinutes(this.getMinutes() + value);
7782                 break;
7783             case Date.HOUR:
7784                 d.setHours(this.getHours() + value);
7785                 break;
7786             case Date.DAY:
7787                 d.setDate(this.getDate() + value);
7788                 break;
7789             case Date.MONTH:
7790                 var day = this.getDate();
7791                 if (day > 28) {
7792                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
7793                 }
7794                 d.setDate(day);
7795                 d.setMonth(this.getMonth() + value);
7796                 break;
7797             case Date.YEAR:
7798                 d.setFullYear(this.getFullYear() + value);
7799                 break;
7800         }
7801         return d;
7802     },
7803
7804     
7805     between : function(start, end) {
7806         var t = this.getTime();
7807         return start.getTime() <= t && t <= end.getTime();
7808     }
7809 });
7810
7811
7812
7813 Date.prototype.format = Date.prototype.dateFormat;
7814
7815
7816
7817 if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
7818     Ext.apply(Date.prototype, {
7819         _xMonth : Date.prototype.setMonth,
7820         _xDate  : Date.prototype.setDate,
7821
7822         
7823         
7824         setMonth : function(num) {
7825             if (num <= -1) {
7826                 var n = Math.ceil(-num),
7827                     back_year = Math.ceil(n / 12),
7828                     month = (n % 12) ? 12 - n % 12 : 0;
7829
7830                 this.setFullYear(this.getFullYear() - back_year);
7831
7832                 return this._xMonth(month);
7833             } else {
7834                 return this._xMonth(num);
7835             }
7836         },
7837
7838         
7839         
7840         
7841         setDate : function(d) {
7842             
7843             
7844             return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
7845         }
7846     });
7847 }
7848
7849
7850
7851
7852
7853 Ext.util.MixedCollection = function(allowFunctions, keyFn){
7854     this.items = [];
7855     this.map = {};
7856     this.keys = [];
7857     this.length = 0;
7858     this.addEvents(
7859         
7860         'clear',
7861         
7862         'add',
7863         
7864         'replace',
7865         
7866         'remove',
7867         'sort'
7868     );
7869     this.allowFunctions = allowFunctions === true;
7870     if(keyFn){
7871         this.getKey = keyFn;
7872     }
7873     Ext.util.MixedCollection.superclass.constructor.call(this);
7874 };
7875
7876 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
7877
7878     
7879     allowFunctions : false,
7880
7881     
7882     add : function(key, o){
7883         if(arguments.length == 1){
7884             o = arguments[0];
7885             key = this.getKey(o);
7886         }
7887         if(typeof key != 'undefined' && key !== null){
7888             var old = this.map[key];
7889             if(typeof old != 'undefined'){
7890                 return this.replace(key, o);
7891             }
7892             this.map[key] = o;
7893         }
7894         this.length++;
7895         this.items.push(o);
7896         this.keys.push(key);
7897         this.fireEvent('add', this.length-1, o, key);
7898         return o;
7899     },
7900
7901     
7902     getKey : function(o){
7903          return o.id;
7904     },
7905
7906     
7907     replace : function(key, o){
7908         if(arguments.length == 1){
7909             o = arguments[0];
7910             key = this.getKey(o);
7911         }
7912         var old = this.map[key];
7913         if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
7914              return this.add(key, o);
7915         }
7916         var index = this.indexOfKey(key);
7917         this.items[index] = o;
7918         this.map[key] = o;
7919         this.fireEvent('replace', key, old, o);
7920         return o;
7921     },
7922
7923     
7924     addAll : function(objs){
7925         if(arguments.length > 1 || Ext.isArray(objs)){
7926             var args = arguments.length > 1 ? arguments : objs;
7927             for(var i = 0, len = args.length; i < len; i++){
7928                 this.add(args[i]);
7929             }
7930         }else{
7931             for(var key in objs){
7932                 if(this.allowFunctions || typeof objs[key] != 'function'){
7933                     this.add(key, objs[key]);
7934                 }
7935             }
7936         }
7937     },
7938
7939     
7940     each : function(fn, scope){
7941         var items = [].concat(this.items); 
7942         for(var i = 0, len = items.length; i < len; i++){
7943             if(fn.call(scope || items[i], items[i], i, len) === false){
7944                 break;
7945             }
7946         }
7947     },
7948
7949     
7950     eachKey : function(fn, scope){
7951         for(var i = 0, len = this.keys.length; i < len; i++){
7952             fn.call(scope || window, this.keys[i], this.items[i], i, len);
7953         }
7954     },
7955
7956     
7957     find : function(fn, scope){
7958         for(var i = 0, len = this.items.length; i < len; i++){
7959             if(fn.call(scope || window, this.items[i], this.keys[i])){
7960                 return this.items[i];
7961             }
7962         }
7963         return null;
7964     },
7965
7966     
7967     insert : function(index, key, o){
7968         if(arguments.length == 2){
7969             o = arguments[1];
7970             key = this.getKey(o);
7971         }
7972         if(this.containsKey(key)){
7973             this.suspendEvents();
7974             this.removeKey(key);
7975             this.resumeEvents();
7976         }
7977         if(index >= this.length){
7978             return this.add(key, o);
7979         }
7980         this.length++;
7981         this.items.splice(index, 0, o);
7982         if(typeof key != 'undefined' && key !== null){
7983             this.map[key] = o;
7984         }
7985         this.keys.splice(index, 0, key);
7986         this.fireEvent('add', index, o, key);
7987         return o;
7988     },
7989
7990     
7991     remove : function(o){
7992         return this.removeAt(this.indexOf(o));
7993     },
7994
7995     
7996     removeAt : function(index){
7997         if(index < this.length && index >= 0){
7998             this.length--;
7999             var o = this.items[index];
8000             this.items.splice(index, 1);
8001             var key = this.keys[index];
8002             if(typeof key != 'undefined'){
8003                 delete this.map[key];
8004             }
8005             this.keys.splice(index, 1);
8006             this.fireEvent('remove', o, key);
8007             return o;
8008         }
8009         return false;
8010     },
8011
8012     
8013     removeKey : function(key){
8014         return this.removeAt(this.indexOfKey(key));
8015     },
8016
8017     
8018     getCount : function(){
8019         return this.length;
8020     },
8021
8022     
8023     indexOf : function(o){
8024         return this.items.indexOf(o);
8025     },
8026
8027     
8028     indexOfKey : function(key){
8029         return this.keys.indexOf(key);
8030     },
8031
8032     
8033     item : function(key){
8034         var mk = this.map[key],
8035             item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
8036         return typeof item != 'function' || this.allowFunctions ? item : null; 
8037     },
8038
8039     
8040     itemAt : function(index){
8041         return this.items[index];
8042     },
8043
8044     
8045     key : function(key){
8046         return this.map[key];
8047     },
8048
8049     
8050     contains : function(o){
8051         return this.indexOf(o) != -1;
8052     },
8053
8054     
8055     containsKey : function(key){
8056         return typeof this.map[key] != 'undefined';
8057     },
8058
8059     
8060     clear : function(){
8061         this.length = 0;
8062         this.items = [];
8063         this.keys = [];
8064         this.map = {};
8065         this.fireEvent('clear');
8066     },
8067
8068     
8069     first : function(){
8070         return this.items[0];
8071     },
8072
8073     
8074     last : function(){
8075         return this.items[this.length-1];
8076     },
8077
8078     
8079     _sort : function(property, dir, fn){
8080         var i, len,
8081             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
8082
8083             
8084             c     = [],
8085             keys  = this.keys,
8086             items = this.items;
8087
8088         
8089         fn = fn || function(a, b) {
8090             return a - b;
8091         };
8092
8093         
8094         for(i = 0, len = items.length; i < len; i++){
8095             c[c.length] = {
8096                 key  : keys[i],
8097                 value: items[i],
8098                 index: i
8099             };
8100         }
8101
8102         
8103         c.sort(function(a, b){
8104             var v = fn(a[property], b[property]) * dsc;
8105             if(v === 0){
8106                 v = (a.index < b.index ? -1 : 1);
8107             }
8108             return v;
8109         });
8110
8111         
8112         for(i = 0, len = c.length; i < len; i++){
8113             items[i] = c[i].value;
8114             keys[i]  = c[i].key;
8115         }
8116
8117         this.fireEvent('sort', this);
8118     },
8119
8120     
8121     sort : function(dir, fn){
8122         this._sort('value', dir, fn);
8123     },
8124
8125     
8126     reorder: function(mapping) {
8127         this.suspendEvents();
8128
8129         var items = this.items,
8130             index = 0,
8131             length = items.length,
8132             order = [],
8133             remaining = [],
8134             oldIndex;
8135
8136         
8137         for (oldIndex in mapping) {
8138             order[mapping[oldIndex]] = items[oldIndex];
8139         }
8140
8141         for (index = 0; index < length; index++) {
8142             if (mapping[index] == undefined) {
8143                 remaining.push(items[index]);
8144             }
8145         }
8146
8147         for (index = 0; index < length; index++) {
8148             if (order[index] == undefined) {
8149                 order[index] = remaining.shift();
8150             }
8151         }
8152
8153         this.clear();
8154         this.addAll(order);
8155
8156         this.resumeEvents();
8157         this.fireEvent('sort', this);
8158     },
8159
8160     
8161     keySort : function(dir, fn){
8162         this._sort('key', dir, fn || function(a, b){
8163             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
8164             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
8165         });
8166     },
8167
8168     
8169     getRange : function(start, end){
8170         var items = this.items;
8171         if(items.length < 1){
8172             return [];
8173         }
8174         start = start || 0;
8175         end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
8176         var i, r = [];
8177         if(start <= end){
8178             for(i = start; i <= end; i++) {
8179                 r[r.length] = items[i];
8180             }
8181         }else{
8182             for(i = start; i >= end; i--) {
8183                 r[r.length] = items[i];
8184             }
8185         }
8186         return r;
8187     },
8188
8189     
8190     filter : function(property, value, anyMatch, caseSensitive){
8191         if(Ext.isEmpty(value, false)){
8192             return this.clone();
8193         }
8194         value = this.createValueMatcher(value, anyMatch, caseSensitive);
8195         return this.filterBy(function(o){
8196             return o && value.test(o[property]);
8197         });
8198     },
8199
8200     
8201     filterBy : function(fn, scope){
8202         var r = new Ext.util.MixedCollection();
8203         r.getKey = this.getKey;
8204         var k = this.keys, it = this.items;
8205         for(var i = 0, len = it.length; i < len; i++){
8206             if(fn.call(scope||this, it[i], k[i])){
8207                 r.add(k[i], it[i]);
8208             }
8209         }
8210         return r;
8211     },
8212
8213     
8214     findIndex : function(property, value, start, anyMatch, caseSensitive){
8215         if(Ext.isEmpty(value, false)){
8216             return -1;
8217         }
8218         value = this.createValueMatcher(value, anyMatch, caseSensitive);
8219         return this.findIndexBy(function(o){
8220             return o && value.test(o[property]);
8221         }, null, start);
8222     },
8223
8224     
8225     findIndexBy : function(fn, scope, start){
8226         var k = this.keys, it = this.items;
8227         for(var i = (start||0), len = it.length; i < len; i++){
8228             if(fn.call(scope||this, it[i], k[i])){
8229                 return i;
8230             }
8231         }
8232         return -1;
8233     },
8234
8235     
8236     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
8237         if (!value.exec) { 
8238             var er = Ext.escapeRe;
8239             value = String(value);
8240
8241             if (anyMatch === true) {
8242                 value = er(value);
8243             } else {
8244                 value = '^' + er(value);
8245                 if (exactMatch === true) {
8246                     value += '$';
8247                 }
8248             }
8249             value = new RegExp(value, caseSensitive ? '' : 'i');
8250          }
8251          return value;
8252     },
8253
8254     
8255     clone : function(){
8256         var r = new Ext.util.MixedCollection();
8257         var k = this.keys, it = this.items;
8258         for(var i = 0, len = it.length; i < len; i++){
8259             r.add(k[i], it[i]);
8260         }
8261         r.getKey = this.getKey;
8262         return r;
8263     }
8264 });
8265
8266 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
8267
8268 Ext.util.JSON = new (function(){
8269     var useHasOwn = !!{}.hasOwnProperty,
8270         isNative = function() {
8271             var useNative = null;
8272
8273             return function() {
8274                 if (useNative === null) {
8275                     useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
8276                 }
8277         
8278                 return useNative;
8279             };
8280         }(),
8281         pad = function(n) {
8282             return n < 10 ? "0" + n : n;
8283         },
8284         doDecode = function(json){
8285             return eval("(" + json + ')');    
8286         },
8287         doEncode = function(o){
8288             if(!Ext.isDefined(o) || o === null){
8289                 return "null";
8290             }else if(Ext.isArray(o)){
8291                 return encodeArray(o);
8292             }else if(Ext.isDate(o)){
8293                 return Ext.util.JSON.encodeDate(o);
8294             }else if(Ext.isString(o)){
8295                 return encodeString(o);
8296             }else if(typeof o == "number"){
8297                 
8298                 return isFinite(o) ? String(o) : "null";
8299             }else if(Ext.isBoolean(o)){
8300                 return String(o);
8301             }else {
8302                 var a = ["{"], b, i, v;
8303                 for (i in o) {
8304                     
8305                     if(!o.getElementsByTagName){
8306                         if(!useHasOwn || o.hasOwnProperty(i)) {
8307                             v = o[i];
8308                             switch (typeof v) {
8309                             case "undefined":
8310                             case "function":
8311                             case "unknown":
8312                                 break;
8313                             default:
8314                                 if(b){
8315                                     a.push(',');
8316                                 }
8317                                 a.push(doEncode(i), ":",
8318                                         v === null ? "null" : doEncode(v));
8319                                 b = true;
8320                             }
8321                         }
8322                     }
8323                 }
8324                 a.push("}");
8325                 return a.join("");
8326             }    
8327         },
8328         m = {
8329             "\b": '\\b',
8330             "\t": '\\t',
8331             "\n": '\\n',
8332             "\f": '\\f',
8333             "\r": '\\r',
8334             '"' : '\\"',
8335             "\\": '\\\\'
8336         },
8337         encodeString = function(s){
8338             if (/["\\\x00-\x1f]/.test(s)) {
8339                 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
8340                     var c = m[b];
8341                     if(c){
8342                         return c;
8343                     }
8344                     c = b.charCodeAt();
8345                     return "\\u00" +
8346                         Math.floor(c / 16).toString(16) +
8347                         (c % 16).toString(16);
8348                 }) + '"';
8349             }
8350             return '"' + s + '"';
8351         },
8352         encodeArray = function(o){
8353             var a = ["["], b, i, l = o.length, v;
8354                 for (i = 0; i < l; i += 1) {
8355                     v = o[i];
8356                     switch (typeof v) {
8357                         case "undefined":
8358                         case "function":
8359                         case "unknown":
8360                             break;
8361                         default:
8362                             if (b) {
8363                                 a.push(',');
8364                             }
8365                             a.push(v === null ? "null" : Ext.util.JSON.encode(v));
8366                             b = true;
8367                     }
8368                 }
8369                 a.push("]");
8370                 return a.join("");
8371         };
8372
8373     
8374     this.encodeDate = function(o){
8375         return '"' + o.getFullYear() + "-" +
8376                 pad(o.getMonth() + 1) + "-" +
8377                 pad(o.getDate()) + "T" +
8378                 pad(o.getHours()) + ":" +
8379                 pad(o.getMinutes()) + ":" +
8380                 pad(o.getSeconds()) + '"';
8381     };
8382
8383     
8384     this.encode = function() {
8385         var ec;
8386         return function(o) {
8387             if (!ec) {
8388                 
8389                 ec = isNative() ? JSON.stringify : doEncode;
8390             }
8391             return ec(o);
8392         };
8393     }();
8394
8395
8396     
8397     this.decode = function() {
8398         var dc;
8399         return function(json) {
8400             if (!dc) {
8401                 
8402                 dc = isNative() ? JSON.parse : doDecode;
8403             }
8404             return dc(json);
8405         };
8406     }();
8407
8408 })();
8409
8410 Ext.encode = Ext.util.JSON.encode;
8411
8412 Ext.decode = Ext.util.JSON.decode;
8413
8414 Ext.util.Format = function(){
8415     var trimRe = /^\s+|\s+$/g,
8416         stripTagsRE = /<\/?[^>]+>/gi,
8417         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
8418         nl2brRe = /\r?\n/g;
8419
8420     return {
8421         
8422         ellipsis : function(value, len, word){
8423             if(value && value.length > len){
8424                 if(word){
8425                     var vs = value.substr(0, len - 2),
8426                         index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
8427                     if(index == -1 || index < (len - 15)){
8428                         return value.substr(0, len - 3) + "...";
8429                     }else{
8430                         return vs.substr(0, index) + "...";
8431                     }
8432                 } else{
8433                     return value.substr(0, len - 3) + "...";
8434                 }
8435             }
8436             return value;
8437         },
8438
8439         
8440         undef : function(value){
8441             return value !== undefined ? value : "";
8442         },
8443
8444         
8445         defaultValue : function(value, defaultValue){
8446             return value !== undefined && value !== '' ? value : defaultValue;
8447         },
8448
8449         
8450         htmlEncode : function(value){
8451             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
8452         },
8453
8454         
8455         htmlDecode : function(value){
8456             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
8457         },
8458
8459         
8460         trim : function(value){
8461             return String(value).replace(trimRe, "");
8462         },
8463
8464         
8465         substr : function(value, start, length){
8466             return String(value).substr(start, length);
8467         },
8468
8469         
8470         lowercase : function(value){
8471             return String(value).toLowerCase();
8472         },
8473
8474         
8475         uppercase : function(value){
8476             return String(value).toUpperCase();
8477         },
8478
8479         
8480         capitalize : function(value){
8481             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
8482         },
8483
8484         
8485         call : function(value, fn){
8486             if(arguments.length > 2){
8487                 var args = Array.prototype.slice.call(arguments, 2);
8488                 args.unshift(value);
8489                 return eval(fn).apply(window, args);
8490             }else{
8491                 return eval(fn).call(window, value);
8492             }
8493         },
8494
8495         
8496         usMoney : function(v){
8497             v = (Math.round((v-0)*100))/100;
8498             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
8499             v = String(v);
8500             var ps = v.split('.'),
8501                 whole = ps[0],
8502                 sub = ps[1] ? '.'+ ps[1] : '.00',
8503                 r = /(\d+)(\d{3})/;
8504             while (r.test(whole)) {
8505                 whole = whole.replace(r, '$1' + ',' + '$2');
8506             }
8507             v = whole + sub;
8508             if(v.charAt(0) == '-'){
8509                 return '-$' + v.substr(1);
8510             }
8511             return "$" +  v;
8512         },
8513
8514         
8515         date : function(v, format){
8516             if(!v){
8517                 return "";
8518             }
8519             if(!Ext.isDate(v)){
8520                 v = new Date(Date.parse(v));
8521             }
8522             return v.dateFormat(format || "m/d/Y");
8523         },
8524
8525         
8526         dateRenderer : function(format){
8527             return function(v){
8528                 return Ext.util.Format.date(v, format);
8529             };
8530         },
8531
8532         
8533         stripTags : function(v){
8534             return !v ? v : String(v).replace(stripTagsRE, "");
8535         },
8536
8537         
8538         stripScripts : function(v){
8539             return !v ? v : String(v).replace(stripScriptsRe, "");
8540         },
8541
8542         
8543         fileSize : function(size){
8544             if(size < 1024) {
8545                 return size + " bytes";
8546             } else if(size < 1048576) {
8547                 return (Math.round(((size*10) / 1024))/10) + " KB";
8548             } else {
8549                 return (Math.round(((size*10) / 1048576))/10) + " MB";
8550             }
8551         },
8552
8553         
8554         math : function(){
8555             var fns = {};
8556             return function(v, a){
8557                 if(!fns[a]){
8558                     fns[a] = new Function('v', 'return v ' + a + ';');
8559                 }
8560                 return fns[a](v);
8561             }
8562         }(),
8563
8564         
8565         round : function(value, precision) {
8566             var result = Number(value);
8567             if (typeof precision == 'number') {
8568                 precision = Math.pow(10, precision);
8569                 result = Math.round(value * precision) / precision;
8570             }
8571             return result;
8572         },
8573
8574         
8575         number: function(v, format) {
8576             if(!format){
8577                 return v;
8578             }
8579             v = Ext.num(v, NaN);
8580             if (isNaN(v)){
8581                 return '';
8582             }
8583             var comma = ',',
8584                 dec = '.',
8585                 i18n = false,
8586                 neg = v < 0;
8587
8588             v = Math.abs(v);
8589             if(format.substr(format.length - 2) == '/i'){
8590                 format = format.substr(0, format.length - 2);
8591                 i18n = true;
8592                 comma = '.';
8593                 dec = ',';
8594             }
8595
8596             var hasComma = format.indexOf(comma) != -1,
8597                 psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
8598
8599             if(1 < psplit.length){
8600                 v = v.toFixed(psplit[1].length);
8601             }else if(2 < psplit.length){
8602                 throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
8603             }else{
8604                 v = v.toFixed(0);
8605             }
8606
8607             var fnum = v.toString();
8608
8609             psplit = fnum.split('.');
8610
8611             if (hasComma) {
8612                 var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3;
8613
8614                 for (var i = 0; i < j; i += n) {
8615                     if (i != 0) {
8616                         n = 3;
8617                     }
8618                     parr[parr.length] = cnum.substr(i, n);
8619                     m -= 1;
8620                 }
8621                 fnum = parr.join(comma);
8622                 if (psplit[1]) {
8623                     fnum += dec + psplit[1];
8624                 }
8625             } else {
8626                 if (psplit[1]) {
8627                     fnum = psplit[0] + dec + psplit[1];
8628                 }
8629             }
8630
8631             return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
8632         },
8633
8634         
8635         numberRenderer : function(format){
8636             return function(v){
8637                 return Ext.util.Format.number(v, format);
8638             };
8639         },
8640
8641         
8642         plural : function(v, s, p){
8643             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
8644         },
8645
8646         
8647         nl2br : function(v){
8648             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
8649         }
8650     }
8651 }();
8652
8653 Ext.XTemplate = function(){
8654     Ext.XTemplate.superclass.constructor.apply(this, arguments);
8655
8656     var me = this,
8657         s = me.html,
8658         re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
8659         nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
8660         ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
8661         execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
8662         m,
8663         id = 0,
8664         tpls = [],
8665         VALUES = 'values',
8666         PARENT = 'parent',
8667         XINDEX = 'xindex',
8668         XCOUNT = 'xcount',
8669         RETURN = 'return ',
8670         WITHVALUES = 'with(values){ ';
8671
8672     s = ['<tpl>', s, '</tpl>'].join('');
8673
8674     while((m = s.match(re))){
8675         var m2 = m[0].match(nameRe),
8676             m3 = m[0].match(ifRe),
8677             m4 = m[0].match(execRe),
8678             exp = null,
8679             fn = null,
8680             exec = null,
8681             name = m2 && m2[1] ? m2[1] : '';
8682
8683        if (m3) {
8684            exp = m3 && m3[1] ? m3[1] : null;
8685            if(exp){
8686                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
8687            }
8688        }
8689        if (m4) {
8690            exp = m4 && m4[1] ? m4[1] : null;
8691            if(exp){
8692                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
8693            }
8694        }
8695        if(name){
8696            switch(name){
8697                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
8698                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
8699                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
8700            }
8701        }
8702        tpls.push({
8703             id: id,
8704             target: name,
8705             exec: exec,
8706             test: fn,
8707             body: m[1]||''
8708         });
8709        s = s.replace(m[0], '{xtpl'+ id + '}');
8710        ++id;
8711     }
8712     for(var i = tpls.length-1; i >= 0; --i){
8713         me.compileTpl(tpls[i]);
8714     }
8715     me.master = tpls[tpls.length-1];
8716     me.tpls = tpls;
8717 };
8718 Ext.extend(Ext.XTemplate, Ext.Template, {
8719     
8720     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
8721     
8722     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
8723
8724     
8725     applySubTemplate : function(id, values, parent, xindex, xcount){
8726         var me = this,
8727             len,
8728             t = me.tpls[id],
8729             vs,
8730             buf = [];
8731         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
8732             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
8733             return '';
8734         }
8735         vs = t.target ? t.target.call(me, values, parent) : values;
8736         len = vs.length;
8737         parent = t.target ? values : parent;
8738         if(t.target && Ext.isArray(vs)){
8739             for(var i = 0, len = vs.length; i < len; i++){
8740                 buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
8741             }
8742             return buf.join('');
8743         }
8744         return t.compiled.call(me, vs, parent, xindex, xcount);
8745     },
8746
8747     
8748     compileTpl : function(tpl){
8749         var fm = Ext.util.Format,
8750             useF = this.disableFormats !== true,
8751             sep = Ext.isGecko ? "+" : ",",
8752             body;
8753
8754         function fn(m, name, format, args, math){
8755             if(name.substr(0, 4) == 'xtpl'){
8756                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
8757             }
8758             var v;
8759             if(name === '.'){
8760                 v = 'values';
8761             }else if(name === '#'){
8762                 v = 'xindex';
8763             }else if(name.indexOf('.') != -1){
8764                 v = name;
8765             }else{
8766                 v = "values['" + name + "']";
8767             }
8768             if(math){
8769                 v = '(' + v + math + ')';
8770             }
8771             if (format && useF) {
8772                 args = args ? ',' + args : "";
8773                 if(format.substr(0, 5) != "this."){
8774                     format = "fm." + format + '(';
8775                 }else{
8776                     format = 'this.call("'+ format.substr(5) + '", ';
8777                     args = ", values";
8778                 }
8779             } else {
8780                 args= ''; format = "("+v+" === undefined ? '' : ";
8781             }
8782             return "'"+ sep + format + v + args + ")"+sep+"'";
8783         }
8784
8785         function codeFn(m, code){
8786             
8787             return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
8788         }
8789
8790         
8791         if(Ext.isGecko){
8792             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
8793                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
8794                     "';};";
8795         }else{
8796             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
8797             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
8798             body.push("'].join('');};");
8799             body = body.join('');
8800         }
8801         eval(body);
8802         return this;
8803     },
8804
8805     
8806     applyTemplate : function(values){
8807         return this.master.compiled.call(this, values, {}, 1, 1);
8808     },
8809
8810     
8811     compile : function(){return this;}
8812
8813     
8814     
8815     
8816
8817 });
8818
8819 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
8820
8821
8822 Ext.XTemplate.from = function(el){
8823     el = Ext.getDom(el);
8824     return new Ext.XTemplate(el.value || el.innerHTML);
8825 };
8826
8827 Ext.util.CSS = function(){
8828         var rules = null;
8829         var doc = document;
8830
8831     var camelRe = /(-[a-z])/gi;
8832     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
8833
8834    return {
8835    
8836    createStyleSheet : function(cssText, id){
8837        var ss;
8838        var head = doc.getElementsByTagName("head")[0];
8839        var rules = doc.createElement("style");
8840        rules.setAttribute("type", "text/css");
8841        if(id){
8842            rules.setAttribute("id", id);
8843        }
8844        if(Ext.isIE){
8845            head.appendChild(rules);
8846            ss = rules.styleSheet;
8847            ss.cssText = cssText;
8848        }else{
8849            try{
8850                 rules.appendChild(doc.createTextNode(cssText));
8851            }catch(e){
8852                rules.cssText = cssText;
8853            }
8854            head.appendChild(rules);
8855            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
8856        }
8857        this.cacheStyleSheet(ss);
8858        return ss;
8859    },
8860
8861    
8862    removeStyleSheet : function(id){
8863        var existing = doc.getElementById(id);
8864        if(existing){
8865            existing.parentNode.removeChild(existing);
8866        }
8867    },
8868
8869    
8870    swapStyleSheet : function(id, url){
8871        this.removeStyleSheet(id);
8872        var ss = doc.createElement("link");
8873        ss.setAttribute("rel", "stylesheet");
8874        ss.setAttribute("type", "text/css");
8875        ss.setAttribute("id", id);
8876        ss.setAttribute("href", url);
8877        doc.getElementsByTagName("head")[0].appendChild(ss);
8878    },
8879    
8880    
8881    refreshCache : function(){
8882        return this.getRules(true);
8883    },
8884
8885    
8886    cacheStyleSheet : function(ss){
8887        if(!rules){
8888            rules = {};
8889        }
8890        try{
8891            var ssRules = ss.cssRules || ss.rules;
8892            for(var j = ssRules.length-1; j >= 0; --j){
8893                rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
8894            }
8895        }catch(e){}
8896    },
8897    
8898    
8899    getRules : function(refreshCache){
8900                 if(rules === null || refreshCache){
8901                         rules = {};
8902                         var ds = doc.styleSheets;
8903                         for(var i =0, len = ds.length; i < len; i++){
8904                             try{
8905                         this.cacheStyleSheet(ds[i]);
8906                     }catch(e){} 
8907                 }
8908                 }
8909                 return rules;
8910         },
8911         
8912         
8913    getRule : function(selector, refreshCache){
8914                 var rs = this.getRules(refreshCache);
8915                 if(!Ext.isArray(selector)){
8916                     return rs[selector.toLowerCase()];
8917                 }
8918                 for(var i = 0; i < selector.length; i++){
8919                         if(rs[selector[i]]){
8920                                 return rs[selector[i].toLowerCase()];
8921                         }
8922                 }
8923                 return null;
8924         },
8925         
8926         
8927         
8928    updateRule : function(selector, property, value){
8929                 if(!Ext.isArray(selector)){
8930                         var rule = this.getRule(selector);
8931                         if(rule){
8932                                 rule.style[property.replace(camelRe, camelFn)] = value;
8933                                 return true;
8934                         }
8935                 }else{
8936                         for(var i = 0; i < selector.length; i++){
8937                                 if(this.updateRule(selector[i], property, value)){
8938                                         return true;
8939                                 }
8940                         }
8941                 }
8942                 return false;
8943         }
8944    };   
8945 }();
8946 Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {
8947     
8948     constructor : function(el, config){
8949         this.el = Ext.get(el);
8950         this.el.unselectable();
8951
8952         Ext.apply(this, config);
8953
8954         this.addEvents(
8955         
8956         "mousedown",
8957         
8958         "click",
8959         
8960         "mouseup"
8961         );
8962
8963         if(!this.disabled){
8964             this.disabled = true;
8965             this.enable();
8966         }
8967
8968         
8969         if(this.handler){
8970             this.on("click", this.handler,  this.scope || this);
8971         }
8972
8973         Ext.util.ClickRepeater.superclass.constructor.call(this);        
8974     },
8975     
8976     interval : 20,
8977     delay: 250,
8978     preventDefault : true,
8979     stopDefault : false,
8980     timer : 0,
8981
8982     
8983     enable: function(){
8984         if(this.disabled){
8985             this.el.on('mousedown', this.handleMouseDown, this);
8986             if (Ext.isIE){
8987                 this.el.on('dblclick', this.handleDblClick, this);
8988             }
8989             if(this.preventDefault || this.stopDefault){
8990                 this.el.on('click', this.eventOptions, this);
8991             }
8992         }
8993         this.disabled = false;
8994     },
8995
8996     
8997     disable: function( force){
8998         if(force || !this.disabled){
8999             clearTimeout(this.timer);
9000             if(this.pressClass){
9001                 this.el.removeClass(this.pressClass);
9002             }
9003             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
9004             this.el.removeAllListeners();
9005         }
9006         this.disabled = true;
9007     },
9008
9009     
9010     setDisabled: function(disabled){
9011         this[disabled ? 'disable' : 'enable']();
9012     },
9013
9014     eventOptions: function(e){
9015         if(this.preventDefault){
9016             e.preventDefault();
9017         }
9018         if(this.stopDefault){
9019             e.stopEvent();
9020         }
9021     },
9022
9023     
9024     destroy : function() {
9025         this.disable(true);
9026         Ext.destroy(this.el);
9027         this.purgeListeners();
9028     },
9029
9030     handleDblClick : function(e){
9031         clearTimeout(this.timer);
9032         this.el.blur();
9033
9034         this.fireEvent("mousedown", this, e);
9035         this.fireEvent("click", this, e);
9036     },
9037
9038     
9039     handleMouseDown : function(e){
9040         clearTimeout(this.timer);
9041         this.el.blur();
9042         if(this.pressClass){
9043             this.el.addClass(this.pressClass);
9044         }
9045         this.mousedownTime = new Date();
9046
9047         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
9048         this.el.on("mouseout", this.handleMouseOut, this);
9049
9050         this.fireEvent("mousedown", this, e);
9051         this.fireEvent("click", this, e);
9052
9053         
9054         if (this.accelerate) {
9055             this.delay = 400;
9056         }
9057         this.timer = this.click.defer(this.delay || this.interval, this, [e]);
9058     },
9059
9060     
9061     click : function(e){
9062         this.fireEvent("click", this, e);
9063         this.timer = this.click.defer(this.accelerate ?
9064             this.easeOutExpo(this.mousedownTime.getElapsed(),
9065                 400,
9066                 -390,
9067                 12000) :
9068             this.interval, this, [e]);
9069     },
9070
9071     easeOutExpo : function (t, b, c, d) {
9072         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
9073     },
9074
9075     
9076     handleMouseOut : function(){
9077         clearTimeout(this.timer);
9078         if(this.pressClass){
9079             this.el.removeClass(this.pressClass);
9080         }
9081         this.el.on("mouseover", this.handleMouseReturn, this);
9082     },
9083
9084     
9085     handleMouseReturn : function(){
9086         this.el.un("mouseover", this.handleMouseReturn, this);
9087         if(this.pressClass){
9088             this.el.addClass(this.pressClass);
9089         }
9090         this.click();
9091     },
9092
9093     
9094     handleMouseUp : function(e){
9095         clearTimeout(this.timer);
9096         this.el.un("mouseover", this.handleMouseReturn, this);
9097         this.el.un("mouseout", this.handleMouseOut, this);
9098         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
9099         this.el.removeClass(this.pressClass);
9100         this.fireEvent("mouseup", this, e);
9101     }
9102 });
9103 Ext.KeyNav = function(el, config){
9104     this.el = Ext.get(el);
9105     Ext.apply(this, config);
9106     if(!this.disabled){
9107         this.disabled = true;
9108         this.enable();
9109     }
9110 };
9111
9112 Ext.KeyNav.prototype = {
9113     
9114     disabled : false,
9115     
9116     defaultEventAction: "stopEvent",
9117     
9118     forceKeyDown : false,
9119
9120     
9121     relay : function(e){
9122         var k = e.getKey();
9123         var h = this.keyToHandler[k];
9124         if(h && this[h]){
9125             if(this.doRelay(e, this[h], h) !== true){
9126                 e[this.defaultEventAction]();
9127             }
9128         }
9129     },
9130
9131     
9132     doRelay : function(e, h, hname){
9133         return h.call(this.scope || this, e);
9134     },
9135
9136     
9137     enter : false,
9138     left : false,
9139     right : false,
9140     up : false,
9141     down : false,
9142     tab : false,
9143     esc : false,
9144     pageUp : false,
9145     pageDown : false,
9146     del : false,
9147     home : false,
9148     end : false,
9149
9150     
9151     keyToHandler : {
9152         37 : "left",
9153         39 : "right",
9154         38 : "up",
9155         40 : "down",
9156         33 : "pageUp",
9157         34 : "pageDown",
9158         46 : "del",
9159         36 : "home",
9160         35 : "end",
9161         13 : "enter",
9162         27 : "esc",
9163         9  : "tab"
9164     },
9165     
9166     stopKeyUp: function(e) {
9167         var k = e.getKey();
9168
9169         if (k >= 37 && k <= 40) {
9170             
9171             
9172             e.stopEvent();
9173         }
9174     },
9175     
9176     
9177     destroy: function(){
9178         this.disable();    
9179     },
9180
9181         
9182         enable: function() {
9183         if (this.disabled) {
9184             if (Ext.isSafari2) {
9185                 
9186                 this.el.on('keyup', this.stopKeyUp, this);
9187             }
9188
9189             this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
9190             this.disabled = false;
9191         }
9192     },
9193
9194         
9195         disable: function() {
9196         if (!this.disabled) {
9197             if (Ext.isSafari2) {
9198                 
9199                 this.el.un('keyup', this.stopKeyUp, this);
9200             }
9201
9202             this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
9203             this.disabled = true;
9204         }
9205     },
9206     
9207     
9208     setDisabled : function(disabled){
9209         this[disabled ? "disable" : "enable"]();
9210     },
9211     
9212     
9213     isKeydown: function(){
9214         return this.forceKeyDown || Ext.EventManager.useKeydown;
9215     }
9216 };
9217
9218 Ext.KeyMap = function(el, config, eventName){
9219     this.el  = Ext.get(el);
9220     this.eventName = eventName || "keydown";
9221     this.bindings = [];
9222     if(config){
9223         this.addBinding(config);
9224     }
9225     this.enable();
9226 };
9227
9228 Ext.KeyMap.prototype = {
9229     
9230     stopEvent : false,
9231
9232     
9233         addBinding : function(config){
9234         if(Ext.isArray(config)){
9235             Ext.each(config, function(c){
9236                 this.addBinding(c);
9237             }, this);
9238             return;
9239         }
9240         var keyCode = config.key,
9241             fn = config.fn || config.handler,
9242             scope = config.scope;
9243
9244         if (config.stopEvent) {
9245             this.stopEvent = config.stopEvent;    
9246         }       
9247
9248         if(typeof keyCode == "string"){
9249             var ks = [];
9250             var keyString = keyCode.toUpperCase();
9251             for(var j = 0, len = keyString.length; j < len; j++){
9252                 ks.push(keyString.charCodeAt(j));
9253             }
9254             keyCode = ks;
9255         }
9256         var keyArray = Ext.isArray(keyCode);
9257         
9258         var handler = function(e){
9259             if(this.checkModifiers(config, e)){
9260                 var k = e.getKey();
9261                 if(keyArray){
9262                     for(var i = 0, len = keyCode.length; i < len; i++){
9263                         if(keyCode[i] == k){
9264                           if(this.stopEvent){
9265                               e.stopEvent();
9266                           }
9267                           fn.call(scope || window, k, e);
9268                           return;
9269                         }
9270                     }
9271                 }else{
9272                     if(k == keyCode){
9273                         if(this.stopEvent){
9274                            e.stopEvent();
9275                         }
9276                         fn.call(scope || window, k, e);
9277                     }
9278                 }
9279             }
9280         };
9281         this.bindings.push(handler);
9282         },
9283     
9284     
9285     checkModifiers: function(config, e){
9286         var val, key, keys = ['shift', 'ctrl', 'alt'];
9287         for (var i = 0, len = keys.length; i < len; ++i){
9288             key = keys[i];
9289             val = config[key];
9290             if(!(val === undefined || (val === e[key + 'Key']))){
9291                 return false;
9292             }
9293         }
9294         return true;
9295     },
9296
9297     
9298     on : function(key, fn, scope){
9299         var keyCode, shift, ctrl, alt;
9300         if(typeof key == "object" && !Ext.isArray(key)){
9301             keyCode = key.key;
9302             shift = key.shift;
9303             ctrl = key.ctrl;
9304             alt = key.alt;
9305         }else{
9306             keyCode = key;
9307         }
9308         this.addBinding({
9309             key: keyCode,
9310             shift: shift,
9311             ctrl: ctrl,
9312             alt: alt,
9313             fn: fn,
9314             scope: scope
9315         });
9316     },
9317
9318     
9319     handleKeyDown : function(e){
9320             if(this.enabled){ 
9321             var b = this.bindings;
9322             for(var i = 0, len = b.length; i < len; i++){
9323                 b[i].call(this, e);
9324             }
9325             }
9326         },
9327
9328         
9329         isEnabled : function(){
9330             return this.enabled;
9331         },
9332
9333         
9334         enable: function(){
9335                 if(!this.enabled){
9336                     this.el.on(this.eventName, this.handleKeyDown, this);
9337                     this.enabled = true;
9338                 }
9339         },
9340
9341         
9342         disable: function(){
9343                 if(this.enabled){
9344                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
9345                     this.enabled = false;
9346                 }
9347         },
9348     
9349     
9350     setDisabled : function(disabled){
9351         this[disabled ? "disable" : "enable"]();
9352     }
9353 };
9354 Ext.util.TextMetrics = function(){
9355     var shared;
9356     return {
9357         
9358         measure : function(el, text, fixedWidth){
9359             if(!shared){
9360                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
9361             }
9362             shared.bind(el);
9363             shared.setFixedWidth(fixedWidth || 'auto');
9364             return shared.getSize(text);
9365         },
9366
9367         
9368         createInstance : function(el, fixedWidth){
9369             return Ext.util.TextMetrics.Instance(el, fixedWidth);
9370         }
9371     };
9372 }();
9373
9374 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
9375     var ml = new Ext.Element(document.createElement('div'));
9376     document.body.appendChild(ml.dom);
9377     ml.position('absolute');
9378     ml.setLeftTop(-1000, -1000);
9379     ml.hide();
9380
9381     if(fixedWidth){
9382         ml.setWidth(fixedWidth);
9383     }
9384
9385     var instance = {
9386         
9387         getSize : function(text){
9388             ml.update(text);
9389             var s = ml.getSize();
9390             ml.update('');
9391             return s;
9392         },
9393
9394         
9395         bind : function(el){
9396             ml.setStyle(
9397                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
9398             );
9399         },
9400
9401         
9402         setFixedWidth : function(width){
9403             ml.setWidth(width);
9404         },
9405
9406         
9407         getWidth : function(text){
9408             ml.dom.style.width = 'auto';
9409             return this.getSize(text).width;
9410         },
9411
9412         
9413         getHeight : function(text){
9414             return this.getSize(text).height;
9415         }
9416     };
9417
9418     instance.bind(bindTo);
9419
9420     return instance;
9421 };
9422
9423 Ext.Element.addMethods({
9424     
9425     getTextWidth : function(text, min, max){
9426         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
9427     }
9428 });
9429
9430 Ext.util.Cookies = {
9431     
9432     set : function(name, value){
9433         var argv = arguments;
9434         var argc = arguments.length;
9435         var expires = (argc > 2) ? argv[2] : null;
9436         var path = (argc > 3) ? argv[3] : '/';
9437         var domain = (argc > 4) ? argv[4] : null;
9438         var secure = (argc > 5) ? argv[5] : false;
9439         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
9440     },
9441
9442     
9443     get : function(name){
9444         var arg = name + "=";
9445         var alen = arg.length;
9446         var clen = document.cookie.length;
9447         var i = 0;
9448         var j = 0;
9449         while(i < clen){
9450             j = i + alen;
9451             if(document.cookie.substring(i, j) == arg){
9452                 return Ext.util.Cookies.getCookieVal(j);
9453             }
9454             i = document.cookie.indexOf(" ", i) + 1;
9455             if(i === 0){
9456                 break;
9457             }
9458         }
9459         return null;
9460     },
9461
9462     
9463     clear : function(name){
9464         if(Ext.util.Cookies.get(name)){
9465             document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
9466         }
9467     },
9468     
9469     getCookieVal : function(offset){
9470         var endstr = document.cookie.indexOf(";", offset);
9471         if(endstr == -1){
9472             endstr = document.cookie.length;
9473         }
9474         return unescape(document.cookie.substring(offset, endstr));
9475     }
9476 };
9477 Ext.handleError = function(e) {
9478     throw e;
9479 };
9480
9481
9482 Ext.Error = function(message) {
9483     
9484     this.message = (this.lang[message]) ? this.lang[message] : message;
9485 };
9486
9487 Ext.Error.prototype = new Error();
9488 Ext.apply(Ext.Error.prototype, {
9489     
9490     lang: {},
9491
9492     name: 'Ext.Error',
9493     
9494     getName : function() {
9495         return this.name;
9496     },
9497     
9498     getMessage : function() {
9499         return this.message;
9500     },
9501     
9502     toJson : function() {
9503         return Ext.encode(this);
9504     }
9505 });
9506
9507 Ext.ComponentMgr = function(){
9508     var all = new Ext.util.MixedCollection();
9509     var types = {};
9510     var ptypes = {};
9511
9512     return {
9513         
9514         register : function(c){
9515             all.add(c);
9516         },
9517
9518         
9519         unregister : function(c){
9520             all.remove(c);
9521         },
9522
9523         
9524         get : function(id){
9525             return all.get(id);
9526         },
9527
9528         
9529         onAvailable : function(id, fn, scope){
9530             all.on("add", function(index, o){
9531                 if(o.id == id){
9532                     fn.call(scope || o, o);
9533                     all.un("add", fn, scope);
9534                 }
9535             });
9536         },
9537
9538         
9539         all : all,
9540         
9541         
9542         types : types,
9543         
9544         
9545         ptypes: ptypes,
9546         
9547         
9548         isRegistered : function(xtype){
9549             return types[xtype] !== undefined;    
9550         },
9551         
9552         
9553         isPluginRegistered : function(ptype){
9554             return ptypes[ptype] !== undefined;    
9555         },        
9556
9557         
9558         registerType : function(xtype, cls){
9559             types[xtype] = cls;
9560             cls.xtype = xtype;
9561         },
9562
9563         
9564         create : function(config, defaultType){
9565             return config.render ? config : new types[config.xtype || defaultType](config);
9566         },
9567
9568         
9569         registerPlugin : function(ptype, cls){
9570             ptypes[ptype] = cls;
9571             cls.ptype = ptype;
9572         },
9573
9574         
9575         createPlugin : function(config, defaultType){
9576             var PluginCls = ptypes[config.ptype || defaultType];
9577             if (PluginCls.init) {
9578                 return PluginCls;                
9579             } else {
9580                 return new PluginCls(config);
9581             }            
9582         }
9583     };
9584 }();
9585
9586
9587 Ext.reg = Ext.ComponentMgr.registerType; 
9588
9589 Ext.preg = Ext.ComponentMgr.registerPlugin;
9590
9591 Ext.create = Ext.ComponentMgr.create;
9592 Ext.Component = function(config){
9593     config = config || {};
9594     if(config.initialConfig){
9595         if(config.isAction){           
9596             this.baseAction = config;
9597         }
9598         config = config.initialConfig; 
9599     }else if(config.tagName || config.dom || Ext.isString(config)){ 
9600         config = {applyTo: config, id: config.id || config};
9601     }
9602
9603     
9604     this.initialConfig = config;
9605
9606     Ext.apply(this, config);
9607     this.addEvents(
9608         
9609         'added',
9610         
9611         'disable',
9612         
9613         'enable',
9614         
9615         'beforeshow',
9616         
9617         'show',
9618         
9619         'beforehide',
9620         
9621         'hide',
9622         
9623         'removed',
9624         
9625         'beforerender',
9626         
9627         'render',
9628         
9629         'afterrender',
9630         
9631         'beforedestroy',
9632         
9633         'destroy',
9634         
9635         'beforestaterestore',
9636         
9637         'staterestore',
9638         
9639         'beforestatesave',
9640         
9641         'statesave'
9642     );
9643     this.getId();
9644     Ext.ComponentMgr.register(this);
9645     Ext.Component.superclass.constructor.call(this);
9646
9647     if(this.baseAction){
9648         this.baseAction.addComponent(this);
9649     }
9650
9651     this.initComponent();
9652
9653     if(this.plugins){
9654         if(Ext.isArray(this.plugins)){
9655             for(var i = 0, len = this.plugins.length; i < len; i++){
9656                 this.plugins[i] = this.initPlugin(this.plugins[i]);
9657             }
9658         }else{
9659             this.plugins = this.initPlugin(this.plugins);
9660         }
9661     }
9662
9663     if(this.stateful !== false){
9664         this.initState();
9665     }
9666
9667     if(this.applyTo){
9668         this.applyToMarkup(this.applyTo);
9669         delete this.applyTo;
9670     }else if(this.renderTo){
9671         this.render(this.renderTo);
9672         delete this.renderTo;
9673     }
9674 };
9675
9676
9677 Ext.Component.AUTO_ID = 1000;
9678
9679 Ext.extend(Ext.Component, Ext.util.Observable, {
9680     
9681     
9682     
9683     
9684     
9685     
9686     
9687
9688     
9689     
9690     
9691     
9692     
9693     
9694     
9695     
9696     
9697     disabled : false,
9698     
9699     hidden : false,
9700     
9701     
9702     
9703     
9704     
9705     
9706     
9707     autoEl : 'div',
9708
9709     
9710     disabledClass : 'x-item-disabled',
9711     
9712     allowDomMove : true,
9713     
9714     autoShow : false,
9715     
9716     hideMode : 'display',
9717     
9718     hideParent : false,
9719     
9720     
9721     
9722     
9723     
9724     rendered : false,
9725
9726     
9727     
9728
9729     
9730
9731     
9732     tplWriteMode : 'overwrite',
9733
9734     
9735     
9736     
9737     bubbleEvents: [],
9738
9739
9740     
9741     ctype : 'Ext.Component',
9742
9743     
9744     actionMode : 'el',
9745
9746     
9747     getActionEl : function(){
9748         return this[this.actionMode];
9749     },
9750
9751     initPlugin : function(p){
9752         if(p.ptype && !Ext.isFunction(p.init)){
9753             p = Ext.ComponentMgr.createPlugin(p);
9754         }else if(Ext.isString(p)){
9755             p = Ext.ComponentMgr.createPlugin({
9756                 ptype: p
9757             });
9758         }
9759         p.init(this);
9760         return p;
9761     },
9762
9763     
9764     initComponent : function(){
9765         
9766         if(this.listeners){
9767             this.on(this.listeners);
9768             delete this.listeners;
9769         }
9770         this.enableBubble(this.bubbleEvents);
9771     },
9772
9773     
9774     render : function(container, position){
9775         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
9776             if(!container && this.el){
9777                 this.el = Ext.get(this.el);
9778                 container = this.el.dom.parentNode;
9779                 this.allowDomMove = false;
9780             }
9781             this.container = Ext.get(container);
9782             if(this.ctCls){
9783                 this.container.addClass(this.ctCls);
9784             }
9785             this.rendered = true;
9786             if(position !== undefined){
9787                 if(Ext.isNumber(position)){
9788                     position = this.container.dom.childNodes[position];
9789                 }else{
9790                     position = Ext.getDom(position);
9791                 }
9792             }
9793             this.onRender(this.container, position || null);
9794             if(this.autoShow){
9795                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
9796             }
9797             if(this.cls){
9798                 this.el.addClass(this.cls);
9799                 delete this.cls;
9800             }
9801             if(this.style){
9802                 this.el.applyStyles(this.style);
9803                 delete this.style;
9804             }
9805             if(this.overCls){
9806                 this.el.addClassOnOver(this.overCls);
9807             }
9808             this.fireEvent('render', this);
9809
9810
9811             
9812             
9813             var contentTarget = this.getContentTarget();
9814             if (this.html){
9815                 contentTarget.update(Ext.DomHelper.markup(this.html));
9816                 delete this.html;
9817             }
9818             if (this.contentEl){
9819                 var ce = Ext.getDom(this.contentEl);
9820                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
9821                 contentTarget.appendChild(ce);
9822             }
9823             if (this.tpl) {
9824                 if (!this.tpl.compile) {
9825                     this.tpl = new Ext.XTemplate(this.tpl);
9826                 }
9827                 if (this.data) {
9828                     this.tpl[this.tplWriteMode](contentTarget, this.data);
9829                     delete this.data;
9830                 }
9831             }
9832             this.afterRender(this.container);
9833
9834
9835             if(this.hidden){
9836                 
9837                 this.doHide();
9838             }
9839             if(this.disabled){
9840                 
9841                 this.disable(true);
9842             }
9843
9844             if(this.stateful !== false){
9845                 this.initStateEvents();
9846             }
9847             this.fireEvent('afterrender', this);
9848         }
9849         return this;
9850     },
9851
9852
9853     
9854     update: function(htmlOrData, loadScripts, cb) {
9855         var contentTarget = this.getContentTarget();
9856         if (this.tpl && typeof htmlOrData !== "string") {
9857             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
9858         } else {
9859             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
9860             contentTarget.update(html, loadScripts, cb);
9861         }
9862     },
9863
9864
9865     
9866     onAdded : function(container, pos) {
9867         this.ownerCt = container;
9868         this.initRef();
9869         this.fireEvent('added', this, container, pos);
9870     },
9871
9872     
9873     onRemoved : function() {
9874         this.removeRef();
9875         this.fireEvent('removed', this, this.ownerCt);
9876         delete this.ownerCt;
9877     },
9878
9879     
9880     initRef : function() {
9881         
9882         if(this.ref && !this.refOwner){
9883             var levels = this.ref.split('/'),
9884                 last = levels.length,
9885                 i = 0,
9886                 t = this;
9887
9888             while(t && i < last){
9889                 t = t.ownerCt;
9890                 ++i;
9891             }
9892             if(t){
9893                 t[this.refName = levels[--i]] = this;
9894                 
9895                 this.refOwner = t;
9896             }
9897         }
9898     },
9899
9900     removeRef : function() {
9901         if (this.refOwner && this.refName) {
9902             delete this.refOwner[this.refName];
9903             delete this.refOwner;
9904         }
9905     },
9906
9907     
9908     initState : function(){
9909         if(Ext.state.Manager){
9910             var id = this.getStateId();
9911             if(id){
9912                 var state = Ext.state.Manager.get(id);
9913                 if(state){
9914                     if(this.fireEvent('beforestaterestore', this, state) !== false){
9915                         this.applyState(Ext.apply({}, state));
9916                         this.fireEvent('staterestore', this, state);
9917                     }
9918                 }
9919             }
9920         }
9921     },
9922
9923     
9924     getStateId : function(){
9925         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
9926     },
9927
9928     
9929     initStateEvents : function(){
9930         if(this.stateEvents){
9931             for(var i = 0, e; e = this.stateEvents[i]; i++){
9932                 this.on(e, this.saveState, this, {delay:100});
9933             }
9934         }
9935     },
9936
9937     
9938     applyState : function(state){
9939         if(state){
9940             Ext.apply(this, state);
9941         }
9942     },
9943
9944     
9945     getState : function(){
9946         return null;
9947     },
9948
9949     
9950     saveState : function(){
9951         if(Ext.state.Manager && this.stateful !== false){
9952             var id = this.getStateId();
9953             if(id){
9954                 var state = this.getState();
9955                 if(this.fireEvent('beforestatesave', this, state) !== false){
9956                     Ext.state.Manager.set(id, state);
9957                     this.fireEvent('statesave', this, state);
9958                 }
9959             }
9960         }
9961     },
9962
9963     
9964     applyToMarkup : function(el){
9965         this.allowDomMove = false;
9966         this.el = Ext.get(el);
9967         this.render(this.el.dom.parentNode);
9968     },
9969
9970     
9971     addClass : function(cls){
9972         if(this.el){
9973             this.el.addClass(cls);
9974         }else{
9975             this.cls = this.cls ? this.cls + ' ' + cls : cls;
9976         }
9977         return this;
9978     },
9979
9980     
9981     removeClass : function(cls){
9982         if(this.el){
9983             this.el.removeClass(cls);
9984         }else if(this.cls){
9985             this.cls = this.cls.split(' ').remove(cls).join(' ');
9986         }
9987         return this;
9988     },
9989
9990     
9991     
9992     onRender : function(ct, position){
9993         if(!this.el && this.autoEl){
9994             if(Ext.isString(this.autoEl)){
9995                 this.el = document.createElement(this.autoEl);
9996             }else{
9997                 var div = document.createElement('div');
9998                 Ext.DomHelper.overwrite(div, this.autoEl);
9999                 this.el = div.firstChild;
10000             }
10001             if (!this.el.id) {
10002                 this.el.id = this.getId();
10003             }
10004         }
10005         if(this.el){
10006             this.el = Ext.get(this.el);
10007             if(this.allowDomMove !== false){
10008                 ct.dom.insertBefore(this.el.dom, position);
10009                 if (div) {
10010                     Ext.removeNode(div);
10011                     div = null;
10012                 }
10013             }
10014         }
10015     },
10016
10017     
10018     getAutoCreate : function(){
10019         var cfg = Ext.isObject(this.autoCreate) ?
10020                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
10021         if(this.id && !cfg.id){
10022             cfg.id = this.id;
10023         }
10024         return cfg;
10025     },
10026
10027     
10028     afterRender : Ext.emptyFn,
10029
10030     
10031     destroy : function(){
10032         if(!this.isDestroyed){
10033             if(this.fireEvent('beforedestroy', this) !== false){
10034                 this.destroying = true;
10035                 this.beforeDestroy();
10036                 if(this.ownerCt && this.ownerCt.remove){
10037                     this.ownerCt.remove(this, false);
10038                 }
10039                 if(this.rendered){
10040                     this.el.remove();
10041                     if(this.actionMode == 'container' || this.removeMode == 'container'){
10042                         this.container.remove();
10043                     }
10044                 }
10045                 
10046                 if(this.focusTask && this.focusTask.cancel){
10047                     this.focusTask.cancel();
10048                 }
10049                 this.onDestroy();
10050                 Ext.ComponentMgr.unregister(this);
10051                 this.fireEvent('destroy', this);
10052                 this.purgeListeners();
10053                 this.destroying = false;
10054                 this.isDestroyed = true;
10055             }
10056         }
10057     },
10058
10059     deleteMembers : function(){
10060         var args = arguments;
10061         for(var i = 0, len = args.length; i < len; ++i){
10062             delete this[args[i]];
10063         }
10064     },
10065
10066     
10067     beforeDestroy : Ext.emptyFn,
10068
10069     
10070     onDestroy  : Ext.emptyFn,
10071
10072     
10073     getEl : function(){
10074         return this.el;
10075     },
10076
10077     
10078     getContentTarget : function(){
10079         return this.el;
10080     },
10081
10082     
10083     getId : function(){
10084         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
10085     },
10086
10087     
10088     getItemId : function(){
10089         return this.itemId || this.getId();
10090     },
10091
10092     
10093     focus : function(selectText, delay){
10094         if(delay){
10095             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
10096             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
10097             return;
10098         }
10099         if(this.rendered && !this.isDestroyed){
10100             this.el.focus();
10101             if(selectText === true){
10102                 this.el.dom.select();
10103             }
10104         }
10105         return this;
10106     },
10107
10108     
10109     blur : function(){
10110         if(this.rendered){
10111             this.el.blur();
10112         }
10113         return this;
10114     },
10115
10116     
10117     disable : function( silent){
10118         if(this.rendered){
10119             this.onDisable();
10120         }
10121         this.disabled = true;
10122         if(silent !== true){
10123             this.fireEvent('disable', this);
10124         }
10125         return this;
10126     },
10127
10128     
10129     onDisable : function(){
10130         this.getActionEl().addClass(this.disabledClass);
10131         this.el.dom.disabled = true;
10132     },
10133
10134     
10135     enable : function(){
10136         if(this.rendered){
10137             this.onEnable();
10138         }
10139         this.disabled = false;
10140         this.fireEvent('enable', this);
10141         return this;
10142     },
10143
10144     
10145     onEnable : function(){
10146         this.getActionEl().removeClass(this.disabledClass);
10147         this.el.dom.disabled = false;
10148     },
10149
10150     
10151     setDisabled : function(disabled){
10152         return this[disabled ? 'disable' : 'enable']();
10153     },
10154
10155     
10156     show : function(){
10157         if(this.fireEvent('beforeshow', this) !== false){
10158             this.hidden = false;
10159             if(this.autoRender){
10160                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
10161             }
10162             if(this.rendered){
10163                 this.onShow();
10164             }
10165             this.fireEvent('show', this);
10166         }
10167         return this;
10168     },
10169
10170     
10171     onShow : function(){
10172         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
10173     },
10174
10175     
10176     hide : function(){
10177         if(this.fireEvent('beforehide', this) !== false){
10178             this.doHide();
10179             this.fireEvent('hide', this);
10180         }
10181         return this;
10182     },
10183
10184     
10185     doHide: function(){
10186         this.hidden = true;
10187         if(this.rendered){
10188             this.onHide();
10189         }
10190     },
10191
10192     
10193     onHide : function(){
10194         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
10195     },
10196
10197     
10198     getVisibilityEl : function(){
10199         return this.hideParent ? this.container : this.getActionEl();
10200     },
10201
10202     
10203     setVisible : function(visible){
10204         return this[visible ? 'show' : 'hide']();
10205     },
10206
10207     
10208     isVisible : function(){
10209         return this.rendered && this.getVisibilityEl().isVisible();
10210     },
10211
10212     
10213     cloneConfig : function(overrides){
10214         overrides = overrides || {};
10215         var id = overrides.id || Ext.id();
10216         var cfg = Ext.applyIf(overrides, this.initialConfig);
10217         cfg.id = id; 
10218         return new this.constructor(cfg);
10219     },
10220
10221     
10222     getXType : function(){
10223         return this.constructor.xtype;
10224     },
10225
10226     
10227     isXType : function(xtype, shallow){
10228         
10229         if (Ext.isFunction(xtype)){
10230             xtype = xtype.xtype; 
10231         }else if (Ext.isObject(xtype)){
10232             xtype = xtype.constructor.xtype; 
10233         }
10234
10235         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
10236     },
10237
10238     
10239     getXTypes : function(){
10240         var tc = this.constructor;
10241         if(!tc.xtypes){
10242             var c = [], sc = this;
10243             while(sc && sc.constructor.xtype){
10244                 c.unshift(sc.constructor.xtype);
10245                 sc = sc.constructor.superclass;
10246             }
10247             tc.xtypeChain = c;
10248             tc.xtypes = c.join('/');
10249         }
10250         return tc.xtypes;
10251     },
10252
10253     
10254     findParentBy : function(fn) {
10255         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
10256         return p || null;
10257     },
10258
10259     
10260     findParentByType : function(xtype) {
10261         return Ext.isFunction(xtype) ?
10262             this.findParentBy(function(p){
10263                 return p.constructor === xtype;
10264             }) :
10265             this.findParentBy(function(p){
10266                 return p.constructor.xtype === xtype;
10267             });
10268     },
10269
10270     
10271     getPositionEl : function(){
10272         return this.positionEl || this.el;
10273     },
10274
10275     
10276     purgeListeners : function(){
10277         Ext.Component.superclass.purgeListeners.call(this);
10278         if(this.mons){
10279             this.on('beforedestroy', this.clearMons, this, {single: true});
10280         }
10281     },
10282
10283     
10284     clearMons : function(){
10285         Ext.each(this.mons, function(m){
10286             m.item.un(m.ename, m.fn, m.scope);
10287         }, this);
10288         this.mons = [];
10289     },
10290
10291     
10292     createMons: function(){
10293         if(!this.mons){
10294             this.mons = [];
10295             this.on('beforedestroy', this.clearMons, this, {single: true});
10296         }
10297     },
10298
10299     
10300     mon : function(item, ename, fn, scope, opt){
10301         this.createMons();
10302         if(Ext.isObject(ename)){
10303             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
10304
10305             var o = ename;
10306             for(var e in o){
10307                 if(propRe.test(e)){
10308                     continue;
10309                 }
10310                 if(Ext.isFunction(o[e])){
10311                     
10312                     this.mons.push({
10313                         item: item, ename: e, fn: o[e], scope: o.scope
10314                     });
10315                     item.on(e, o[e], o.scope, o);
10316                 }else{
10317                     
10318                     this.mons.push({
10319                         item: item, ename: e, fn: o[e], scope: o.scope
10320                     });
10321                     item.on(e, o[e]);
10322                 }
10323             }
10324             return;
10325         }
10326
10327         this.mons.push({
10328             item: item, ename: ename, fn: fn, scope: scope
10329         });
10330         item.on(ename, fn, scope, opt);
10331     },
10332
10333     
10334     mun : function(item, ename, fn, scope){
10335         var found, mon;
10336         this.createMons();
10337         for(var i = 0, len = this.mons.length; i < len; ++i){
10338             mon = this.mons[i];
10339             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
10340                 this.mons.splice(i, 1);
10341                 item.un(ename, fn, scope);
10342                 found = true;
10343                 break;
10344             }
10345         }
10346         return found;
10347     },
10348
10349     
10350     nextSibling : function(){
10351         if(this.ownerCt){
10352             var index = this.ownerCt.items.indexOf(this);
10353             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
10354                 return this.ownerCt.items.itemAt(index+1);
10355             }
10356         }
10357         return null;
10358     },
10359
10360     
10361     previousSibling : function(){
10362         if(this.ownerCt){
10363             var index = this.ownerCt.items.indexOf(this);
10364             if(index > 0){
10365                 return this.ownerCt.items.itemAt(index-1);
10366             }
10367         }
10368         return null;
10369     },
10370
10371     
10372     getBubbleTarget : function(){
10373         return this.ownerCt;
10374     }
10375 });
10376
10377 Ext.reg('component', Ext.Component);
10378 Ext.Action = Ext.extend(Object, {
10379     
10380     
10381     
10382     
10383     
10384     
10385     
10386
10387     constructor : function(config){
10388         this.initialConfig = config;
10389         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
10390         this.items = [];
10391     },
10392     
10393     
10394     isAction : true,
10395
10396     
10397     setText : function(text){
10398         this.initialConfig.text = text;
10399         this.callEach('setText', [text]);
10400     },
10401
10402     
10403     getText : function(){
10404         return this.initialConfig.text;
10405     },
10406
10407     
10408     setIconClass : function(cls){
10409         this.initialConfig.iconCls = cls;
10410         this.callEach('setIconClass', [cls]);
10411     },
10412
10413     
10414     getIconClass : function(){
10415         return this.initialConfig.iconCls;
10416     },
10417
10418     
10419     setDisabled : function(v){
10420         this.initialConfig.disabled = v;
10421         this.callEach('setDisabled', [v]);
10422     },
10423
10424     
10425     enable : function(){
10426         this.setDisabled(false);
10427     },
10428
10429     
10430     disable : function(){
10431         this.setDisabled(true);
10432     },
10433
10434     
10435     isDisabled : function(){
10436         return this.initialConfig.disabled;
10437     },
10438
10439     
10440     setHidden : function(v){
10441         this.initialConfig.hidden = v;
10442         this.callEach('setVisible', [!v]);
10443     },
10444
10445     
10446     show : function(){
10447         this.setHidden(false);
10448     },
10449
10450     
10451     hide : function(){
10452         this.setHidden(true);
10453     },
10454
10455     
10456     isHidden : function(){
10457         return this.initialConfig.hidden;
10458     },
10459
10460     
10461     setHandler : function(fn, scope){
10462         this.initialConfig.handler = fn;
10463         this.initialConfig.scope = scope;
10464         this.callEach('setHandler', [fn, scope]);
10465     },
10466
10467     
10468     each : function(fn, scope){
10469         Ext.each(this.items, fn, scope);
10470     },
10471
10472     
10473     callEach : function(fnName, args){
10474         var cs = this.items;
10475         for(var i = 0, len = cs.length; i < len; i++){
10476             cs[i][fnName].apply(cs[i], args);
10477         }
10478     },
10479
10480     
10481     addComponent : function(comp){
10482         this.items.push(comp);
10483         comp.on('destroy', this.removeComponent, this);
10484     },
10485
10486     
10487     removeComponent : function(comp){
10488         this.items.remove(comp);
10489     },
10490
10491     
10492     execute : function(){
10493         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
10494     }
10495 });
10496
10497 (function(){
10498 Ext.Layer = function(config, existingEl){
10499     config = config || {};
10500     var dh = Ext.DomHelper;
10501     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
10502     if(existingEl){
10503         this.dom = Ext.getDom(existingEl);
10504     }
10505     if(!this.dom){
10506         var o = config.dh || {tag: 'div', cls: 'x-layer'};
10507         this.dom = dh.append(pel, o);
10508     }
10509     if(config.cls){
10510         this.addClass(config.cls);
10511     }
10512     this.constrain = config.constrain !== false;
10513     this.setVisibilityMode(Ext.Element.VISIBILITY);
10514     if(config.id){
10515         this.id = this.dom.id = config.id;
10516     }else{
10517         this.id = Ext.id(this.dom);
10518     }
10519     this.zindex = config.zindex || this.getZIndex();
10520     this.position('absolute', this.zindex);
10521     if(config.shadow){
10522         this.shadowOffset = config.shadowOffset || 4;
10523         this.shadow = new Ext.Shadow({
10524             offset : this.shadowOffset,
10525             mode : config.shadow
10526         });
10527     }else{
10528         this.shadowOffset = 0;
10529     }
10530     this.useShim = config.shim !== false && Ext.useShims;
10531     this.useDisplay = config.useDisplay;
10532     this.hide();
10533 };
10534
10535 var supr = Ext.Element.prototype;
10536
10537
10538 var shims = [];
10539
10540 Ext.extend(Ext.Layer, Ext.Element, {
10541
10542     getZIndex : function(){
10543         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
10544     },
10545
10546     getShim : function(){
10547         if(!this.useShim){
10548             return null;
10549         }
10550         if(this.shim){
10551             return this.shim;
10552         }
10553         var shim = shims.shift();
10554         if(!shim){
10555             shim = this.createShim();
10556             shim.enableDisplayMode('block');
10557             shim.dom.style.display = 'none';
10558             shim.dom.style.visibility = 'visible';
10559         }
10560         var pn = this.dom.parentNode;
10561         if(shim.dom.parentNode != pn){
10562             pn.insertBefore(shim.dom, this.dom);
10563         }
10564         shim.setStyle('z-index', this.getZIndex()-2);
10565         this.shim = shim;
10566         return shim;
10567     },
10568
10569     hideShim : function(){
10570         if(this.shim){
10571             this.shim.setDisplayed(false);
10572             shims.push(this.shim);
10573             delete this.shim;
10574         }
10575     },
10576
10577     disableShadow : function(){
10578         if(this.shadow){
10579             this.shadowDisabled = true;
10580             this.shadow.hide();
10581             this.lastShadowOffset = this.shadowOffset;
10582             this.shadowOffset = 0;
10583         }
10584     },
10585
10586     enableShadow : function(show){
10587         if(this.shadow){
10588             this.shadowDisabled = false;
10589             this.shadowOffset = this.lastShadowOffset;
10590             delete this.lastShadowOffset;
10591             if(show){
10592                 this.sync(true);
10593             }
10594         }
10595     },
10596
10597     
10598     
10599     
10600     sync : function(doShow){
10601         var shadow = this.shadow;
10602         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
10603             var shim = this.getShim(),
10604                 w = this.getWidth(),
10605                 h = this.getHeight(),
10606                 l = this.getLeft(true),
10607                 t = this.getTop(true);
10608
10609             if(shadow && !this.shadowDisabled){
10610                 if(doShow && !shadow.isVisible()){
10611                     shadow.show(this);
10612                 }else{
10613                     shadow.realign(l, t, w, h);
10614                 }
10615                 if(shim){
10616                     if(doShow){
10617                        shim.show();
10618                     }
10619                     
10620                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
10621                         shadowSize = shadow.el.getSize();
10622                     shimStyle.left = (shadowAdj[0])+'px';
10623                     shimStyle.top = (shadowAdj[1])+'px';
10624                     shimStyle.width = (shadowSize.width)+'px';
10625                     shimStyle.height = (shadowSize.height)+'px';
10626                 }
10627             }else if(shim){
10628                 if(doShow){
10629                    shim.show();
10630                 }
10631                 shim.setSize(w, h);
10632                 shim.setLeftTop(l, t);
10633             }
10634         }
10635     },
10636
10637     
10638     destroy : function(){
10639         this.hideShim();
10640         if(this.shadow){
10641             this.shadow.hide();
10642         }
10643         this.removeAllListeners();
10644         Ext.removeNode(this.dom);
10645         delete this.dom;
10646     },
10647
10648     remove : function(){
10649         this.destroy();
10650     },
10651
10652     
10653     beginUpdate : function(){
10654         this.updating = true;
10655     },
10656
10657     
10658     endUpdate : function(){
10659         this.updating = false;
10660         this.sync(true);
10661     },
10662
10663     
10664     hideUnders : function(negOffset){
10665         if(this.shadow){
10666             this.shadow.hide();
10667         }
10668         this.hideShim();
10669     },
10670
10671     
10672     constrainXY : function(){
10673         if(this.constrain){
10674             var vw = Ext.lib.Dom.getViewWidth(),
10675                 vh = Ext.lib.Dom.getViewHeight();
10676             var s = Ext.getDoc().getScroll();
10677
10678             var xy = this.getXY();
10679             var x = xy[0], y = xy[1];
10680             var so = this.shadowOffset;
10681             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
10682             
10683             var moved = false;
10684             
10685             if((x + w) > vw+s.left){
10686                 x = vw - w - so;
10687                 moved = true;
10688             }
10689             if((y + h) > vh+s.top){
10690                 y = vh - h - so;
10691                 moved = true;
10692             }
10693             
10694             if(x < s.left){
10695                 x = s.left;
10696                 moved = true;
10697             }
10698             if(y < s.top){
10699                 y = s.top;
10700                 moved = true;
10701             }
10702             if(moved){
10703                 if(this.avoidY){
10704                     var ay = this.avoidY;
10705                     if(y <= ay && (y+h) >= ay){
10706                         y = ay-h-5;
10707                     }
10708                 }
10709                 xy = [x, y];
10710                 this.storeXY(xy);
10711                 supr.setXY.call(this, xy);
10712                 this.sync();
10713             }
10714         }
10715         return this;
10716     },
10717     
10718     getConstrainOffset : function(){
10719         return this.shadowOffset;    
10720     },
10721
10722     isVisible : function(){
10723         return this.visible;
10724     },
10725
10726     
10727     showAction : function(){
10728         this.visible = true; 
10729         if(this.useDisplay === true){
10730             this.setDisplayed('');
10731         }else if(this.lastXY){
10732             supr.setXY.call(this, this.lastXY);
10733         }else if(this.lastLT){
10734             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
10735         }
10736     },
10737
10738     
10739     hideAction : function(){
10740         this.visible = false;
10741         if(this.useDisplay === true){
10742             this.setDisplayed(false);
10743         }else{
10744             this.setLeftTop(-10000,-10000);
10745         }
10746     },
10747
10748     
10749     setVisible : function(v, a, d, c, e){
10750         if(v){
10751             this.showAction();
10752         }
10753         if(a && v){
10754             var cb = function(){
10755                 this.sync(true);
10756                 if(c){
10757                     c();
10758                 }
10759             }.createDelegate(this);
10760             supr.setVisible.call(this, true, true, d, cb, e);
10761         }else{
10762             if(!v){
10763                 this.hideUnders(true);
10764             }
10765             var cb = c;
10766             if(a){
10767                 cb = function(){
10768                     this.hideAction();
10769                     if(c){
10770                         c();
10771                     }
10772                 }.createDelegate(this);
10773             }
10774             supr.setVisible.call(this, v, a, d, cb, e);
10775             if(v){
10776                 this.sync(true);
10777             }else if(!a){
10778                 this.hideAction();
10779             }
10780         }
10781         return this;
10782     },
10783
10784     storeXY : function(xy){
10785         delete this.lastLT;
10786         this.lastXY = xy;
10787     },
10788
10789     storeLeftTop : function(left, top){
10790         delete this.lastXY;
10791         this.lastLT = [left, top];
10792     },
10793
10794     
10795     beforeFx : function(){
10796         this.beforeAction();
10797         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
10798     },
10799
10800     
10801     afterFx : function(){
10802         Ext.Layer.superclass.afterFx.apply(this, arguments);
10803         this.sync(this.isVisible());
10804     },
10805
10806     
10807     beforeAction : function(){
10808         if(!this.updating && this.shadow){
10809             this.shadow.hide();
10810         }
10811     },
10812
10813     
10814     setLeft : function(left){
10815         this.storeLeftTop(left, this.getTop(true));
10816         supr.setLeft.apply(this, arguments);
10817         this.sync();
10818         return this;
10819     },
10820
10821     setTop : function(top){
10822         this.storeLeftTop(this.getLeft(true), top);
10823         supr.setTop.apply(this, arguments);
10824         this.sync();
10825         return this;
10826     },
10827
10828     setLeftTop : function(left, top){
10829         this.storeLeftTop(left, top);
10830         supr.setLeftTop.apply(this, arguments);
10831         this.sync();
10832         return this;
10833     },
10834
10835     setXY : function(xy, a, d, c, e){
10836         this.fixDisplay();
10837         this.beforeAction();
10838         this.storeXY(xy);
10839         var cb = this.createCB(c);
10840         supr.setXY.call(this, xy, a, d, cb, e);
10841         if(!a){
10842             cb();
10843         }
10844         return this;
10845     },
10846
10847     
10848     createCB : function(c){
10849         var el = this;
10850         return function(){
10851             el.constrainXY();
10852             el.sync(true);
10853             if(c){
10854                 c();
10855             }
10856         };
10857     },
10858
10859     
10860     setX : function(x, a, d, c, e){
10861         this.setXY([x, this.getY()], a, d, c, e);
10862         return this;
10863     },
10864
10865     
10866     setY : function(y, a, d, c, e){
10867         this.setXY([this.getX(), y], a, d, c, e);
10868         return this;
10869     },
10870
10871     
10872     setSize : function(w, h, a, d, c, e){
10873         this.beforeAction();
10874         var cb = this.createCB(c);
10875         supr.setSize.call(this, w, h, a, d, cb, e);
10876         if(!a){
10877             cb();
10878         }
10879         return this;
10880     },
10881
10882     
10883     setWidth : function(w, a, d, c, e){
10884         this.beforeAction();
10885         var cb = this.createCB(c);
10886         supr.setWidth.call(this, w, a, d, cb, e);
10887         if(!a){
10888             cb();
10889         }
10890         return this;
10891     },
10892
10893     
10894     setHeight : function(h, a, d, c, e){
10895         this.beforeAction();
10896         var cb = this.createCB(c);
10897         supr.setHeight.call(this, h, a, d, cb, e);
10898         if(!a){
10899             cb();
10900         }
10901         return this;
10902     },
10903
10904     
10905     setBounds : function(x, y, w, h, a, d, c, e){
10906         this.beforeAction();
10907         var cb = this.createCB(c);
10908         if(!a){
10909             this.storeXY([x, y]);
10910             supr.setXY.call(this, [x, y]);
10911             supr.setSize.call(this, w, h, a, d, cb, e);
10912             cb();
10913         }else{
10914             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
10915         }
10916         return this;
10917     },
10918
10919     
10920     setZIndex : function(zindex){
10921         this.zindex = zindex;
10922         this.setStyle('z-index', zindex + 2);
10923         if(this.shadow){
10924             this.shadow.setZIndex(zindex + 1);
10925         }
10926         if(this.shim){
10927             this.shim.setStyle('z-index', zindex);
10928         }
10929         return this;
10930     }
10931 });
10932 })();
10933
10934 Ext.Shadow = function(config){
10935     Ext.apply(this, config);
10936     if(typeof this.mode != "string"){
10937         this.mode = this.defaultMode;
10938     }
10939     var o = this.offset, a = {h: 0};
10940     var rad = Math.floor(this.offset/2);
10941     switch(this.mode.toLowerCase()){ 
10942         case "drop":
10943             a.w = 0;
10944             a.l = a.t = o;
10945             a.t -= 1;
10946             if(Ext.isIE){
10947                 a.l -= this.offset + rad;
10948                 a.t -= this.offset + rad;
10949                 a.w -= rad;
10950                 a.h -= rad;
10951                 a.t += 1;
10952             }
10953         break;
10954         case "sides":
10955             a.w = (o*2);
10956             a.l = -o;
10957             a.t = o-1;
10958             if(Ext.isIE){
10959                 a.l -= (this.offset - rad);
10960                 a.t -= this.offset + rad;
10961                 a.l += 1;
10962                 a.w -= (this.offset - rad)*2;
10963                 a.w -= rad + 1;
10964                 a.h -= 1;
10965             }
10966         break;
10967         case "frame":
10968             a.w = a.h = (o*2);
10969             a.l = a.t = -o;
10970             a.t += 1;
10971             a.h -= 2;
10972             if(Ext.isIE){
10973                 a.l -= (this.offset - rad);
10974                 a.t -= (this.offset - rad);
10975                 a.l += 1;
10976                 a.w -= (this.offset + rad + 1);
10977                 a.h -= (this.offset + rad);
10978                 a.h += 1;
10979             }
10980         break;
10981     };
10982
10983     this.adjusts = a;
10984 };
10985
10986 Ext.Shadow.prototype = {
10987     
10988     
10989     offset: 4,
10990
10991     
10992     defaultMode: "drop",
10993
10994     
10995     show : function(target){
10996         target = Ext.get(target);
10997         if(!this.el){
10998             this.el = Ext.Shadow.Pool.pull();
10999             if(this.el.dom.nextSibling != target.dom){
11000                 this.el.insertBefore(target);
11001             }
11002         }
11003         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
11004         if(Ext.isIE){
11005             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
11006         }
11007         this.realign(
11008             target.getLeft(true),
11009             target.getTop(true),
11010             target.getWidth(),
11011             target.getHeight()
11012         );
11013         this.el.dom.style.display = "block";
11014     },
11015
11016     
11017     isVisible : function(){
11018         return this.el ? true : false;  
11019     },
11020
11021     
11022     realign : function(l, t, w, h){
11023         if(!this.el){
11024             return;
11025         }
11026         var a = this.adjusts, d = this.el.dom, s = d.style;
11027         var iea = 0;
11028         s.left = (l+a.l)+"px";
11029         s.top = (t+a.t)+"px";
11030         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
11031         if(s.width != sws || s.height != shs){
11032             s.width = sws;
11033             s.height = shs;
11034             if(!Ext.isIE){
11035                 var cn = d.childNodes;
11036                 var sww = Math.max(0, (sw-12))+"px";
11037                 cn[0].childNodes[1].style.width = sww;
11038                 cn[1].childNodes[1].style.width = sww;
11039                 cn[2].childNodes[1].style.width = sww;
11040                 cn[1].style.height = Math.max(0, (sh-12))+"px";
11041             }
11042         }
11043     },
11044
11045     
11046     hide : function(){
11047         if(this.el){
11048             this.el.dom.style.display = "none";
11049             Ext.Shadow.Pool.push(this.el);
11050             delete this.el;
11051         }
11052     },
11053
11054     
11055     setZIndex : function(z){
11056         this.zIndex = z;
11057         if(this.el){
11058             this.el.setStyle("z-index", z);
11059         }
11060     }
11061 };
11062
11063
11064 Ext.Shadow.Pool = function(){
11065     var p = [];
11066     var markup = Ext.isIE ?
11067                  '<div class="x-ie-shadow"></div>' :
11068                  '<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>';
11069     return {
11070         pull : function(){
11071             var sh = p.shift();
11072             if(!sh){
11073                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
11074                 sh.autoBoxAdjust = false;
11075             }
11076             return sh;
11077         },
11078
11079         push : function(sh){
11080             p.push(sh);
11081         }
11082     };
11083 }();
11084 Ext.BoxComponent = Ext.extend(Ext.Component, {
11085
11086     
11087     
11088     
11089     
11090     
11091     
11092     
11093     
11094     
11095     
11096     
11097     
11098     
11099     
11100     
11101     
11102     
11103     
11104     
11105     
11106     
11107     
11108     
11109
11110     
11111
11112     
11113     initComponent : function(){
11114         Ext.BoxComponent.superclass.initComponent.call(this);
11115         this.addEvents(
11116             
11117             'resize',
11118             
11119             'move'
11120         );
11121     },
11122
11123     
11124     boxReady : false,
11125     
11126     deferHeight: false,
11127
11128     
11129     setSize : function(w, h){
11130
11131         
11132         if(typeof w == 'object'){
11133             h = w.height;
11134             w = w.width;
11135         }
11136         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
11137             w = this.boxMinWidth;
11138         }
11139         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
11140             h = this.boxMinHeight;
11141         }
11142         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
11143             w = this.boxMaxWidth;
11144         }
11145         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
11146             h = this.boxMaxHeight;
11147         }
11148         
11149         if(!this.boxReady){
11150             this.width  = w;
11151             this.height = h;
11152             return this;
11153         }
11154
11155         
11156         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
11157             return this;
11158         }
11159         this.lastSize = {width: w, height: h};
11160         var adj = this.adjustSize(w, h),
11161             aw = adj.width,
11162             ah = adj.height,
11163             rz;
11164         if(aw !== undefined || ah !== undefined){ 
11165             rz = this.getResizeEl();
11166             if(!this.deferHeight && aw !== undefined && ah !== undefined){
11167                 rz.setSize(aw, ah);
11168             }else if(!this.deferHeight && ah !== undefined){
11169                 rz.setHeight(ah);
11170             }else if(aw !== undefined){
11171                 rz.setWidth(aw);
11172             }
11173             this.onResize(aw, ah, w, h);
11174             this.fireEvent('resize', this, aw, ah, w, h);
11175         }
11176         return this;
11177     },
11178
11179     
11180     setWidth : function(width){
11181         return this.setSize(width);
11182     },
11183
11184     
11185     setHeight : function(height){
11186         return this.setSize(undefined, height);
11187     },
11188
11189     
11190     getSize : function(){
11191         return this.getResizeEl().getSize();
11192     },
11193
11194     
11195     getWidth : function(){
11196         return this.getResizeEl().getWidth();
11197     },
11198
11199     
11200     getHeight : function(){
11201         return this.getResizeEl().getHeight();
11202     },
11203
11204     
11205     getOuterSize : function(){
11206         var el = this.getResizeEl();
11207         return {width: el.getWidth() + el.getMargins('lr'),
11208                 height: el.getHeight() + el.getMargins('tb')};
11209     },
11210
11211     
11212     getPosition : function(local){
11213         var el = this.getPositionEl();
11214         if(local === true){
11215             return [el.getLeft(true), el.getTop(true)];
11216         }
11217         return this.xy || el.getXY();
11218     },
11219
11220     
11221     getBox : function(local){
11222         var pos = this.getPosition(local);
11223         var s = this.getSize();
11224         s.x = pos[0];
11225         s.y = pos[1];
11226         return s;
11227     },
11228
11229     
11230     updateBox : function(box){
11231         this.setSize(box.width, box.height);
11232         this.setPagePosition(box.x, box.y);
11233         return this;
11234     },
11235
11236     
11237     getResizeEl : function(){
11238         return this.resizeEl || this.el;
11239     },
11240
11241     
11242     setAutoScroll : function(scroll){
11243         if(this.rendered){
11244             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
11245         }
11246         this.autoScroll = scroll;
11247         return this;
11248     },
11249
11250     
11251     setPosition : function(x, y){
11252         if(x && typeof x[1] == 'number'){
11253             y = x[1];
11254             x = x[0];
11255         }
11256         this.x = x;
11257         this.y = y;
11258         if(!this.boxReady){
11259             return this;
11260         }
11261         var adj = this.adjustPosition(x, y);
11262         var ax = adj.x, ay = adj.y;
11263
11264         var el = this.getPositionEl();
11265         if(ax !== undefined || ay !== undefined){
11266             if(ax !== undefined && ay !== undefined){
11267                 el.setLeftTop(ax, ay);
11268             }else if(ax !== undefined){
11269                 el.setLeft(ax);
11270             }else if(ay !== undefined){
11271                 el.setTop(ay);
11272             }
11273             this.onPosition(ax, ay);
11274             this.fireEvent('move', this, ax, ay);
11275         }
11276         return this;
11277     },
11278
11279     
11280     setPagePosition : function(x, y){
11281         if(x && typeof x[1] == 'number'){
11282             y = x[1];
11283             x = x[0];
11284         }
11285         this.pageX = x;
11286         this.pageY = y;
11287         if(!this.boxReady){
11288             return;
11289         }
11290         if(x === undefined || y === undefined){ 
11291             return;
11292         }
11293         var p = this.getPositionEl().translatePoints(x, y);
11294         this.setPosition(p.left, p.top);
11295         return this;
11296     },
11297
11298     
11299     afterRender : function(){
11300         Ext.BoxComponent.superclass.afterRender.call(this);
11301         if(this.resizeEl){
11302             this.resizeEl = Ext.get(this.resizeEl);
11303         }
11304         if(this.positionEl){
11305             this.positionEl = Ext.get(this.positionEl);
11306         }
11307         this.boxReady = true;
11308         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
11309         this.setSize(this.width, this.height);
11310         if(this.x || this.y){
11311             this.setPosition(this.x, this.y);
11312         }else if(this.pageX || this.pageY){
11313             this.setPagePosition(this.pageX, this.pageY);
11314         }
11315     },
11316
11317     
11318     syncSize : function(){
11319         delete this.lastSize;
11320         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
11321         return this;
11322     },
11323
11324     
11325     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
11326     },
11327
11328     
11329     onPosition : function(x, y){
11330
11331     },
11332
11333     
11334     adjustSize : function(w, h){
11335         if(this.autoWidth){
11336             w = 'auto';
11337         }
11338         if(this.autoHeight){
11339             h = 'auto';
11340         }
11341         return {width : w, height: h};
11342     },
11343
11344     
11345     adjustPosition : function(x, y){
11346         return {x : x, y: y};
11347     }
11348 });
11349 Ext.reg('box', Ext.BoxComponent);
11350
11351
11352
11353 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
11354     autoEl:'div'
11355 });
11356 Ext.reg('spacer', Ext.Spacer);
11357 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
11358
11359     
11360     this.el = Ext.get(dragElement, true);
11361     this.el.dom.unselectable = "on";
11362     
11363     this.resizingEl = Ext.get(resizingElement, true);
11364
11365     
11366     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
11367
11368     
11369     
11370     this.minSize = 0;
11371
11372     
11373     this.maxSize = 2000;
11374
11375     
11376     this.animate = false;
11377
11378     
11379     this.useShim = false;
11380
11381     
11382     this.shim = null;
11383
11384     if(!existingProxy){
11385         
11386         this.proxy = Ext.SplitBar.createProxy(this.orientation);
11387     }else{
11388         this.proxy = Ext.get(existingProxy).dom;
11389     }
11390     
11391     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
11392
11393     
11394     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
11395
11396     
11397     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
11398
11399     
11400     this.dragSpecs = {};
11401
11402     
11403     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
11404     this.adapter.init(this);
11405
11406     if(this.orientation == Ext.SplitBar.HORIZONTAL){
11407         
11408         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
11409         this.el.addClass("x-splitbar-h");
11410     }else{
11411         
11412         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
11413         this.el.addClass("x-splitbar-v");
11414     }
11415
11416     this.addEvents(
11417         
11418         "resize",
11419         
11420         "moved",
11421         
11422         "beforeresize",
11423
11424         "beforeapply"
11425     );
11426
11427     Ext.SplitBar.superclass.constructor.call(this);
11428 };
11429
11430 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
11431     onStartProxyDrag : function(x, y){
11432         this.fireEvent("beforeresize", this);
11433         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
11434         this.overlay.unselectable();
11435         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
11436         this.overlay.show();
11437         Ext.get(this.proxy).setDisplayed("block");
11438         var size = this.adapter.getElementSize(this);
11439         this.activeMinSize = this.getMinimumSize();
11440         this.activeMaxSize = this.getMaximumSize();
11441         var c1 = size - this.activeMinSize;
11442         var c2 = Math.max(this.activeMaxSize - size, 0);
11443         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11444             this.dd.resetConstraints();
11445             this.dd.setXConstraint(
11446                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
11447                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
11448                 this.tickSize
11449             );
11450             this.dd.setYConstraint(0, 0);
11451         }else{
11452             this.dd.resetConstraints();
11453             this.dd.setXConstraint(0, 0);
11454             this.dd.setYConstraint(
11455                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
11456                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
11457                 this.tickSize
11458             );
11459          }
11460         this.dragSpecs.startSize = size;
11461         this.dragSpecs.startPoint = [x, y];
11462         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
11463     },
11464
11465     
11466     onEndProxyDrag : function(e){
11467         Ext.get(this.proxy).setDisplayed(false);
11468         var endPoint = Ext.lib.Event.getXY(e);
11469         if(this.overlay){
11470             Ext.destroy(this.overlay);
11471             delete this.overlay;
11472         }
11473         var newSize;
11474         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11475             newSize = this.dragSpecs.startSize +
11476                 (this.placement == Ext.SplitBar.LEFT ?
11477                     endPoint[0] - this.dragSpecs.startPoint[0] :
11478                     this.dragSpecs.startPoint[0] - endPoint[0]
11479                 );
11480         }else{
11481             newSize = this.dragSpecs.startSize +
11482                 (this.placement == Ext.SplitBar.TOP ?
11483                     endPoint[1] - this.dragSpecs.startPoint[1] :
11484                     this.dragSpecs.startPoint[1] - endPoint[1]
11485                 );
11486         }
11487         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
11488         if(newSize != this.dragSpecs.startSize){
11489             if(this.fireEvent('beforeapply', this, newSize) !== false){
11490                 this.adapter.setElementSize(this, newSize);
11491                 this.fireEvent("moved", this, newSize);
11492                 this.fireEvent("resize", this, newSize);
11493             }
11494         }
11495     },
11496
11497     
11498     getAdapter : function(){
11499         return this.adapter;
11500     },
11501
11502     
11503     setAdapter : function(adapter){
11504         this.adapter = adapter;
11505         this.adapter.init(this);
11506     },
11507
11508     
11509     getMinimumSize : function(){
11510         return this.minSize;
11511     },
11512
11513     
11514     setMinimumSize : function(minSize){
11515         this.minSize = minSize;
11516     },
11517
11518     
11519     getMaximumSize : function(){
11520         return this.maxSize;
11521     },
11522
11523     
11524     setMaximumSize : function(maxSize){
11525         this.maxSize = maxSize;
11526     },
11527
11528     
11529     setCurrentSize : function(size){
11530         var oldAnimate = this.animate;
11531         this.animate = false;
11532         this.adapter.setElementSize(this, size);
11533         this.animate = oldAnimate;
11534     },
11535
11536     
11537     destroy : function(removeEl){
11538         Ext.destroy(this.shim, Ext.get(this.proxy));
11539         this.dd.unreg();
11540         if(removeEl){
11541             this.el.remove();
11542         }
11543         this.purgeListeners();
11544     }
11545 });
11546
11547
11548 Ext.SplitBar.createProxy = function(dir){
11549     var proxy = new Ext.Element(document.createElement("div"));
11550     document.body.appendChild(proxy.dom);
11551     proxy.unselectable();
11552     var cls = 'x-splitbar-proxy';
11553     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
11554     return proxy.dom;
11555 };
11556
11557
11558 Ext.SplitBar.BasicLayoutAdapter = function(){
11559 };
11560
11561 Ext.SplitBar.BasicLayoutAdapter.prototype = {
11562     
11563     init : function(s){
11564
11565     },
11566     
11567      getElementSize : function(s){
11568         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11569             return s.resizingEl.getWidth();
11570         }else{
11571             return s.resizingEl.getHeight();
11572         }
11573     },
11574
11575     
11576     setElementSize : function(s, newSize, onComplete){
11577         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11578             if(!s.animate){
11579                 s.resizingEl.setWidth(newSize);
11580                 if(onComplete){
11581                     onComplete(s, newSize);
11582                 }
11583             }else{
11584                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
11585             }
11586         }else{
11587
11588             if(!s.animate){
11589                 s.resizingEl.setHeight(newSize);
11590                 if(onComplete){
11591                     onComplete(s, newSize);
11592                 }
11593             }else{
11594                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
11595             }
11596         }
11597     }
11598 };
11599
11600
11601 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
11602     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
11603     this.container = Ext.get(container);
11604 };
11605
11606 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
11607     init : function(s){
11608         this.basic.init(s);
11609     },
11610
11611     getElementSize : function(s){
11612         return this.basic.getElementSize(s);
11613     },
11614
11615     setElementSize : function(s, newSize, onComplete){
11616         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
11617     },
11618
11619     moveSplitter : function(s){
11620         var yes = Ext.SplitBar;
11621         switch(s.placement){
11622             case yes.LEFT:
11623                 s.el.setX(s.resizingEl.getRight());
11624                 break;
11625             case yes.RIGHT:
11626                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
11627                 break;
11628             case yes.TOP:
11629                 s.el.setY(s.resizingEl.getBottom());
11630                 break;
11631             case yes.BOTTOM:
11632                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
11633                 break;
11634         }
11635     }
11636 };
11637
11638
11639 Ext.SplitBar.VERTICAL = 1;
11640
11641
11642 Ext.SplitBar.HORIZONTAL = 2;
11643
11644
11645 Ext.SplitBar.LEFT = 1;
11646
11647
11648 Ext.SplitBar.RIGHT = 2;
11649
11650
11651 Ext.SplitBar.TOP = 3;
11652
11653
11654 Ext.SplitBar.BOTTOM = 4;
11655
11656 Ext.Container = Ext.extend(Ext.BoxComponent, {
11657     
11658     
11659     
11660     
11661     bufferResize: 50,
11662
11663     
11664     
11665     
11666
11667
11668     
11669     autoDestroy : true,
11670
11671     
11672     forceLayout: false,
11673
11674     
11675     
11676     defaultType : 'panel',
11677
11678     
11679     resizeEvent: 'resize',
11680
11681     
11682     bubbleEvents: ['add', 'remove'],
11683
11684     
11685     initComponent : function(){
11686         Ext.Container.superclass.initComponent.call(this);
11687
11688         this.addEvents(
11689             
11690             'afterlayout',
11691             
11692             'beforeadd',
11693             
11694             'beforeremove',
11695             
11696             'add',
11697             
11698             'remove'
11699         );
11700
11701         
11702         var items = this.items;
11703         if(items){
11704             delete this.items;
11705             this.add(items);
11706         }
11707     },
11708
11709     
11710     initItems : function(){
11711         if(!this.items){
11712             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
11713             this.getLayout(); 
11714         }
11715     },
11716
11717     
11718     setLayout : function(layout){
11719         if(this.layout && this.layout != layout){
11720             this.layout.setContainer(null);
11721         }
11722         this.layout = layout;
11723         this.initItems();
11724         layout.setContainer(this);
11725     },
11726
11727     afterRender: function(){
11728         
11729         
11730         Ext.Container.superclass.afterRender.call(this);
11731         if(!this.layout){
11732             this.layout = 'auto';
11733         }
11734         if(Ext.isObject(this.layout) && !this.layout.layout){
11735             this.layoutConfig = this.layout;
11736             this.layout = this.layoutConfig.type;
11737         }
11738         if(Ext.isString(this.layout)){
11739             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
11740         }
11741         this.setLayout(this.layout);
11742
11743         
11744         if(this.activeItem !== undefined){
11745             var item = this.activeItem;
11746             delete this.activeItem;
11747             this.layout.setActiveItem(item);
11748         }
11749
11750         
11751         if(!this.ownerCt){
11752             this.doLayout(false, true);
11753         }
11754
11755         
11756         
11757         if(this.monitorResize === true){
11758             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
11759         }
11760     },
11761
11762     
11763     getLayoutTarget : function(){
11764         return this.el;
11765     },
11766
11767     
11768     getComponentId : function(comp){
11769         return comp.getItemId();
11770     },
11771
11772     
11773     add : function(comp){
11774         this.initItems();
11775         var args = arguments.length > 1;
11776         if(args || Ext.isArray(comp)){
11777             var result = [];
11778             Ext.each(args ? arguments : comp, function(c){
11779                 result.push(this.add(c));
11780             }, this);
11781             return result;
11782         }
11783         var c = this.lookupComponent(this.applyDefaults(comp));
11784         var index = this.items.length;
11785         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11786             this.items.add(c);
11787             
11788             c.onAdded(this, index);
11789             this.onAdd(c);
11790             this.fireEvent('add', this, c, index);
11791         }
11792         return c;
11793     },
11794
11795     onAdd : function(c){
11796         
11797     },
11798
11799     
11800     onAdded : function(container, pos) {
11801         
11802         this.ownerCt = container;
11803         this.initRef();
11804         
11805         this.cascade(function(c){
11806             c.initRef();
11807         });
11808         this.fireEvent('added', this, container, pos);
11809     },
11810
11811     
11812     insert : function(index, comp){
11813         this.initItems();
11814         var a = arguments, len = a.length;
11815         if(len > 2){
11816             var result = [];
11817             for(var i = len-1; i >= 1; --i) {
11818                 result.push(this.insert(index, a[i]));
11819             }
11820             return result;
11821         }
11822         var c = this.lookupComponent(this.applyDefaults(comp));
11823         index = Math.min(index, this.items.length);
11824         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11825             if(c.ownerCt == this){
11826                 this.items.remove(c);
11827             }
11828             this.items.insert(index, c);
11829             c.onAdded(this, index);
11830             this.onAdd(c);
11831             this.fireEvent('add', this, c, index);
11832         }
11833         return c;
11834     },
11835
11836     
11837     applyDefaults : function(c){
11838         var d = this.defaults;
11839         if(d){
11840             if(Ext.isFunction(d)){
11841                 d = d.call(this, c);
11842             }
11843             if(Ext.isString(c)){
11844                 c = Ext.ComponentMgr.get(c);
11845                 Ext.apply(c, d);
11846             }else if(!c.events){
11847                 Ext.applyIf(c, d);
11848             }else{
11849                 Ext.apply(c, d);
11850             }
11851         }
11852         return c;
11853     },
11854
11855     
11856     onBeforeAdd : function(item){
11857         if(item.ownerCt){
11858             item.ownerCt.remove(item, false);
11859         }
11860         if(this.hideBorders === true){
11861             item.border = (item.border === true);
11862         }
11863     },
11864
11865     
11866     remove : function(comp, autoDestroy){
11867         this.initItems();
11868         var c = this.getComponent(comp);
11869         if(c && this.fireEvent('beforeremove', this, c) !== false){
11870             this.doRemove(c, autoDestroy);
11871             this.fireEvent('remove', this, c);
11872         }
11873         return c;
11874     },
11875
11876     onRemove: function(c){
11877         
11878     },
11879
11880     
11881     doRemove: function(c, autoDestroy){
11882         var l = this.layout,
11883             hasLayout = l && this.rendered;
11884
11885         if(hasLayout){
11886             l.onRemove(c);
11887         }
11888         this.items.remove(c);
11889         c.onRemoved();
11890         this.onRemove(c);
11891         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
11892             c.destroy();
11893         }
11894         if(hasLayout){
11895             l.afterRemove(c);
11896         }
11897     },
11898
11899     
11900     removeAll: function(autoDestroy){
11901         this.initItems();
11902         var item, rem = [], items = [];
11903         this.items.each(function(i){
11904             rem.push(i);
11905         });
11906         for (var i = 0, len = rem.length; i < len; ++i){
11907             item = rem[i];
11908             this.remove(item, autoDestroy);
11909             if(item.ownerCt !== this){
11910                 items.push(item);
11911             }
11912         }
11913         return items;
11914     },
11915
11916     
11917     getComponent : function(comp){
11918         if(Ext.isObject(comp)){
11919             comp = comp.getItemId();
11920         }
11921         return this.items.get(comp);
11922     },
11923
11924     
11925     lookupComponent : function(comp){
11926         if(Ext.isString(comp)){
11927             return Ext.ComponentMgr.get(comp);
11928         }else if(!comp.events){
11929             return this.createComponent(comp);
11930         }
11931         return comp;
11932     },
11933
11934     
11935     createComponent : function(config, defaultType){
11936         if (config.render) {
11937             return config;
11938         }
11939         
11940         
11941         var c = Ext.create(Ext.apply({
11942             ownerCt: this
11943         }, config), defaultType || this.defaultType);
11944         delete c.initialConfig.ownerCt;
11945         delete c.ownerCt;
11946         return c;
11947     },
11948
11949     
11950     canLayout : function() {
11951         var el = this.getVisibilityEl();
11952         return el && el.dom && !el.isStyle("display", "none");
11953     },
11954
11955     
11956
11957     doLayout : function(shallow, force){
11958         var rendered = this.rendered,
11959             forceLayout = force || this.forceLayout;
11960
11961         if(this.collapsed || !this.canLayout()){
11962             this.deferLayout = this.deferLayout || !shallow;
11963             if(!forceLayout){
11964                 return;
11965             }
11966             shallow = shallow && !this.deferLayout;
11967         } else {
11968             delete this.deferLayout;
11969         }
11970         if(rendered && this.layout){
11971             this.layout.layout();
11972         }
11973         if(shallow !== true && this.items){
11974             var cs = this.items.items;
11975             for(var i = 0, len = cs.length; i < len; i++){
11976                 var c = cs[i];
11977                 if(c.doLayout){
11978                     c.doLayout(false, forceLayout);
11979                 }
11980             }
11981         }
11982         if(rendered){
11983             this.onLayout(shallow, forceLayout);
11984         }
11985         
11986         this.hasLayout = true;
11987         delete this.forceLayout;
11988     },
11989
11990     onLayout : Ext.emptyFn,
11991
11992     
11993     shouldBufferLayout: function(){
11994         
11995         var hl = this.hasLayout;
11996         if(this.ownerCt){
11997             
11998             return hl ? !this.hasLayoutPending() : false;
11999         }
12000         
12001         return hl;
12002     },
12003
12004     
12005     hasLayoutPending: function(){
12006         
12007         var pending = false;
12008         this.ownerCt.bubble(function(c){
12009             if(c.layoutPending){
12010                 pending = true;
12011                 return false;
12012             }
12013         });
12014         return pending;
12015     },
12016
12017     onShow : function(){
12018         
12019         Ext.Container.superclass.onShow.call(this);
12020         
12021         if(Ext.isDefined(this.deferLayout)){
12022             delete this.deferLayout;
12023             this.doLayout(true);
12024         }
12025     },
12026
12027     
12028     getLayout : function(){
12029         if(!this.layout){
12030             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
12031             this.setLayout(layout);
12032         }
12033         return this.layout;
12034     },
12035
12036     
12037     beforeDestroy : function(){
12038         var c;
12039         if(this.items){
12040             while(c = this.items.first()){
12041                 this.doRemove(c, true);
12042             }
12043         }
12044         if(this.monitorResize){
12045             Ext.EventManager.removeResizeListener(this.doLayout, this);
12046         }
12047         Ext.destroy(this.layout);
12048         Ext.Container.superclass.beforeDestroy.call(this);
12049     },
12050
12051     
12052     bubble : function(fn, scope, args){
12053         var p = this;
12054         while(p){
12055             if(fn.apply(scope || p, args || [p]) === false){
12056                 break;
12057             }
12058             p = p.ownerCt;
12059         }
12060         return this;
12061     },
12062
12063     
12064     cascade : function(fn, scope, args){
12065         if(fn.apply(scope || this, args || [this]) !== false){
12066             if(this.items){
12067                 var cs = this.items.items;
12068                 for(var i = 0, len = cs.length; i < len; i++){
12069                     if(cs[i].cascade){
12070                         cs[i].cascade(fn, scope, args);
12071                     }else{
12072                         fn.apply(scope || cs[i], args || [cs[i]]);
12073                     }
12074                 }
12075             }
12076         }
12077         return this;
12078     },
12079
12080     
12081     findById : function(id){
12082         var m, ct = this;
12083         this.cascade(function(c){
12084             if(ct != c && c.id === id){
12085                 m = c;
12086                 return false;
12087             }
12088         });
12089         return m || null;
12090     },
12091
12092     
12093     findByType : function(xtype, shallow){
12094         return this.findBy(function(c){
12095             return c.isXType(xtype, shallow);
12096         });
12097     },
12098
12099     
12100     find : function(prop, value){
12101         return this.findBy(function(c){
12102             return c[prop] === value;
12103         });
12104     },
12105
12106     
12107     findBy : function(fn, scope){
12108         var m = [], ct = this;
12109         this.cascade(function(c){
12110             if(ct != c && fn.call(scope || c, c, ct) === true){
12111                 m.push(c);
12112             }
12113         });
12114         return m;
12115     },
12116
12117     
12118     get : function(key){
12119         return this.items.get(key);
12120     }
12121 });
12122
12123 Ext.Container.LAYOUTS = {};
12124 Ext.reg('container', Ext.Container);
12125
12126 Ext.layout.ContainerLayout = Ext.extend(Object, {
12127     
12128     
12129
12130     
12131
12132     
12133     monitorResize:false,
12134     
12135     activeItem : null,
12136
12137     constructor : function(config){
12138         this.id = Ext.id(null, 'ext-layout-');
12139         Ext.apply(this, config);
12140     },
12141
12142     type: 'container',
12143
12144     
12145     IEMeasureHack : function(target, viewFlag) {
12146         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
12147         for (i = 0 ; i < tLen ; i++) {
12148             c = tChildren[i];
12149             e = Ext.get(c);
12150             if (e) {
12151                 d[i] = e.getStyle('display');
12152                 e.setStyle({display: 'none'});
12153             }
12154         }
12155         ret = target ? target.getViewSize(viewFlag) : {};
12156         for (i = 0 ; i < tLen ; i++) {
12157             c = tChildren[i];
12158             e = Ext.get(c);
12159             if (e) {
12160                 e.setStyle({display: d[i]});
12161             }
12162         }
12163         return ret;
12164     },
12165
12166     
12167     getLayoutTargetSize : Ext.EmptyFn,
12168
12169     
12170     layout : function(){
12171         var ct = this.container, target = ct.getLayoutTarget();
12172         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
12173             target.addClass(this.targetCls);
12174         }
12175         this.onLayout(ct, target);
12176         ct.fireEvent('afterlayout', ct, this);
12177     },
12178
12179     
12180     onLayout : function(ct, target){
12181         this.renderAll(ct, target);
12182     },
12183
12184     
12185     isValidParent : function(c, target){
12186         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
12187     },
12188
12189     
12190     renderAll : function(ct, target){
12191         var items = ct.items.items, i, c, len = items.length;
12192         for(i = 0; i < len; i++) {
12193             c = items[i];
12194             if(c && (!c.rendered || !this.isValidParent(c, target))){
12195                 this.renderItem(c, i, target);
12196             }
12197         }
12198     },
12199
12200     
12201     renderItem : function(c, position, target){
12202         if (c) {
12203             if (!c.rendered) {
12204                 c.render(target, position);
12205                 this.configureItem(c, position);
12206             } else if (!this.isValidParent(c, target)) {
12207                 if (Ext.isNumber(position)) {
12208                     position = target.dom.childNodes[position];
12209                 }
12210                 
12211                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
12212                 c.container = target;
12213                 this.configureItem(c, position);
12214             }
12215         }
12216     },
12217
12218     
12219     
12220     getRenderedItems: function(ct){
12221         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
12222         for (i = 0; i < len; i++) {
12223             if((c = cti[i]).rendered && this.isValidParent(c, t)){
12224                 items.push(c);
12225             }
12226         };
12227         return items;
12228     },
12229
12230     
12231     configureItem: function(c, position){
12232         if (this.extraCls) {
12233             var t = c.getPositionEl ? c.getPositionEl() : c;
12234             t.addClass(this.extraCls);
12235         }
12236         
12237         
12238         if (c.doLayout && this.forceLayout) {
12239             c.doLayout();
12240         }
12241         if (this.renderHidden && c != this.activeItem) {
12242             c.hide();
12243         }
12244     },
12245
12246     onRemove: function(c){
12247         if(this.activeItem == c){
12248             delete this.activeItem;
12249         }
12250         if(c.rendered && this.extraCls){
12251             var t = c.getPositionEl ? c.getPositionEl() : c;
12252             t.removeClass(this.extraCls);
12253         }
12254     },
12255
12256     afterRemove: function(c){
12257         if(c.removeRestore){
12258             c.removeMode = 'container';
12259             delete c.removeRestore;
12260         }
12261     },
12262
12263     
12264     onResize: function(){
12265         var ct = this.container,
12266             b;
12267         if(ct.collapsed){
12268             return;
12269         }
12270         if(b = ct.bufferResize && ct.shouldBufferLayout()){
12271             if(!this.resizeTask){
12272                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
12273                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
12274             }
12275             ct.layoutPending = true;
12276             this.resizeTask.delay(this.resizeBuffer);
12277         }else{
12278             this.runLayout();
12279         }
12280     },
12281
12282     runLayout: function(){
12283         var ct = this.container;
12284         this.layout();
12285         ct.onLayout();
12286         delete ct.layoutPending;
12287     },
12288
12289     
12290     setContainer : function(ct){
12291         
12292         if(this.monitorResize && ct != this.container){
12293             var old = this.container;
12294             if(old){
12295                 old.un(old.resizeEvent, this.onResize, this);
12296             }
12297             if(ct){
12298                 ct.on(ct.resizeEvent, this.onResize, this);
12299             }
12300         }
12301         this.container = ct;
12302     },
12303
12304     
12305     parseMargins : function(v){
12306         if (Ext.isNumber(v)) {
12307             v = v.toString();
12308         }
12309         var ms  = v.split(' '),
12310             len = ms.length;
12311             
12312         if (len == 1) {
12313             ms[1] = ms[2] = ms[3] = ms[0];
12314         } else if(len == 2) {
12315             ms[2] = ms[0];
12316             ms[3] = ms[1];
12317         } else if(len == 3) {
12318             ms[3] = ms[1];
12319         }
12320         
12321         return {
12322             top   :parseInt(ms[0], 10) || 0,
12323             right :parseInt(ms[1], 10) || 0,
12324             bottom:parseInt(ms[2], 10) || 0,
12325             left  :parseInt(ms[3], 10) || 0
12326         };
12327     },
12328
12329     
12330     fieldTpl: (function() {
12331         var t = new Ext.Template(
12332             '<div class="x-form-item {itemCls}" tabIndex="-1">',
12333                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
12334                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
12335                 '</div><div class="{clearCls}"></div>',
12336             '</div>'
12337         );
12338         t.disableFormats = true;
12339         return t.compile();
12340     })(),
12341
12342     
12343     destroy : function(){
12344         
12345         if(this.resizeTask && this.resizeTask.cancel){
12346             this.resizeTask.cancel();
12347         }
12348         if(!Ext.isEmpty(this.targetCls)){
12349             var target = this.container.getLayoutTarget();
12350             if(target){
12351                 target.removeClass(this.targetCls);
12352             }
12353         }
12354     }
12355 });
12356 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
12357     type: 'auto',
12358
12359     monitorResize: true,
12360
12361     onLayout : function(ct, target){
12362         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
12363         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
12364         for(i = 0; i < len; i++){
12365             c = cs[i];
12366             if (c.doLayout){
12367                 
12368                 c.doLayout(true);
12369             }
12370         }
12371     }
12372 });
12373
12374 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
12375
12376 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
12377     
12378     monitorResize:true,
12379
12380     type: 'fit',
12381
12382     getLayoutTargetSize : function() {
12383         var target = this.container.getLayoutTarget();
12384         if (!target) {
12385             return {};
12386         }
12387         
12388         return target.getStyleSize();
12389     },
12390
12391     
12392     onLayout : function(ct, target){
12393         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
12394         if(!ct.collapsed){
12395             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
12396         }
12397     },
12398
12399     
12400     setItemSize : function(item, size){
12401         if(item && size.height > 0){ 
12402             item.setSize(size);
12403         }
12404     }
12405 });
12406 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
12407 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
12408     
12409     deferredRender : false,
12410
12411     
12412     layoutOnCardChange : false,
12413
12414     
12415     
12416     renderHidden : true,
12417
12418     type: 'card',
12419
12420     
12421     setActiveItem : function(item){
12422         var ai = this.activeItem,
12423             ct = this.container;
12424         item = ct.getComponent(item);
12425
12426         
12427         if(item && ai != item){
12428
12429             
12430             if(ai){
12431                 ai.hide();
12432                 if (ai.hidden !== true) {
12433                     return false;
12434                 }
12435                 ai.fireEvent('deactivate', ai);
12436             }
12437
12438             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
12439
12440             
12441             this.activeItem = item;
12442
12443             
12444             
12445             delete item.deferLayout;
12446
12447             
12448             item.show();
12449
12450             this.layout();
12451
12452             if(layout){
12453                 item.doLayout();
12454             }
12455             item.fireEvent('activate', item);
12456         }
12457     },
12458
12459     
12460     renderAll : function(ct, target){
12461         if(this.deferredRender){
12462             this.renderItem(this.activeItem, undefined, target);
12463         }else{
12464             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
12465         }
12466     }
12467 });
12468 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
12469
12470 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
12471     
12472
12473     
12474     monitorResize : true,
12475
12476     type : 'anchor',
12477
12478     
12479     defaultAnchor : '100%',
12480
12481     parseAnchorRE : /^(r|right|b|bottom)$/i,
12482
12483     getLayoutTargetSize : function() {
12484         var target = this.container.getLayoutTarget();
12485         if (!target) {
12486             return {};
12487         }
12488         
12489         return target.getStyleSize();
12490     },
12491
12492     
12493     onLayout : function(ct, target){
12494         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
12495         var size = this.getLayoutTargetSize();
12496
12497         var w = size.width, h = size.height;
12498
12499         if(w < 20 && h < 20){
12500             return;
12501         }
12502
12503         
12504         var aw, ah;
12505         if(ct.anchorSize){
12506             if(typeof ct.anchorSize == 'number'){
12507                 aw = ct.anchorSize;
12508             }else{
12509                 aw = ct.anchorSize.width;
12510                 ah = ct.anchorSize.height;
12511             }
12512         }else{
12513             aw = ct.initialConfig.width;
12514             ah = ct.initialConfig.height;
12515         }
12516
12517         var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
12518         for(i = 0; i < len; i++){
12519             c = cs[i];
12520             el = c.getPositionEl();
12521
12522             
12523             if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
12524                 c.anchor = this.defaultAnchor;
12525             }
12526
12527             if(c.anchor){
12528                 a = c.anchorSpec;
12529                 if(!a){ 
12530                     vs = c.anchor.split(' ');
12531                     c.anchorSpec = a = {
12532                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
12533                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
12534                     };
12535                 }
12536                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
12537                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
12538
12539                 if(cw || ch){
12540                     boxes.push({
12541                         comp: c,
12542                         width: cw || undefined,
12543                         height: ch || undefined
12544                     });
12545                 }
12546             }
12547         }
12548         for (i = 0, len = boxes.length; i < len; i++) {
12549             c = boxes[i];
12550             c.comp.setSize(c.width, c.height);
12551         }
12552     },
12553
12554     
12555     parseAnchor : function(a, start, cstart){
12556         if(a && a != 'none'){
12557             var last;
12558             
12559             if(this.parseAnchorRE.test(a)){
12560                 var diff = cstart - start;
12561                 return function(v){
12562                     if(v !== last){
12563                         last = v;
12564                         return v - diff;
12565                     }
12566                 }
12567             
12568             }else if(a.indexOf('%') != -1){
12569                 var ratio = parseFloat(a.replace('%', ''))*.01;
12570                 return function(v){
12571                     if(v !== last){
12572                         last = v;
12573                         return Math.floor(v*ratio);
12574                     }
12575                 }
12576             
12577             }else{
12578                 a = parseInt(a, 10);
12579                 if(!isNaN(a)){
12580                     return function(v){
12581                         if(v !== last){
12582                             last = v;
12583                             return v + a;
12584                         }
12585                     }
12586                 }
12587             }
12588         }
12589         return false;
12590     },
12591
12592     
12593     adjustWidthAnchor : function(value, comp){
12594         return value;
12595     },
12596
12597     
12598     adjustHeightAnchor : function(value, comp){
12599         return value;
12600     }
12601
12602     
12603 });
12604 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
12605
12606 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
12607     
12608     monitorResize:true,
12609
12610     type: 'column',
12611
12612     extraCls: 'x-column',
12613
12614     scrollOffset : 0,
12615
12616     
12617
12618     targetCls: 'x-column-layout-ct',
12619
12620     isValidParent : function(c, target){
12621         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
12622     },
12623
12624     getLayoutTargetSize : function() {
12625         var target = this.container.getLayoutTarget(), ret;
12626         if (target) {
12627             ret = target.getViewSize();
12628
12629             
12630             
12631             
12632             if (Ext.isIE && Ext.isStrict && ret.width == 0){
12633                 ret =  target.getStyleSize();
12634             }
12635
12636             ret.width -= target.getPadding('lr');
12637             ret.height -= target.getPadding('tb');
12638         }
12639         return ret;
12640     },
12641
12642     renderAll : function(ct, target) {
12643         if(!this.innerCt){
12644             
12645             
12646             this.innerCt = target.createChild({cls:'x-column-inner'});
12647             this.innerCt.createChild({cls:'x-clear'});
12648         }
12649         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
12650     },
12651
12652     
12653     onLayout : function(ct, target){
12654         var cs = ct.items.items,
12655             len = cs.length,
12656             c,
12657             i,
12658             m,
12659             margins = [];
12660
12661         this.renderAll(ct, target);
12662
12663         var size = this.getLayoutTargetSize();
12664
12665         if(size.width < 1 && size.height < 1){ 
12666             return;
12667         }
12668
12669         var w = size.width - this.scrollOffset,
12670             h = size.height,
12671             pw = w;
12672
12673         this.innerCt.setWidth(w);
12674
12675         
12676         
12677
12678         for(i = 0; i < len; i++){
12679             c = cs[i];
12680             m = c.getPositionEl().getMargins('lr');
12681             margins[i] = m;
12682             if(!c.columnWidth){
12683                 pw -= (c.getWidth() + m);
12684             }
12685         }
12686
12687         pw = pw < 0 ? 0 : pw;
12688
12689         for(i = 0; i < len; i++){
12690             c = cs[i];
12691             m = margins[i];
12692             if(c.columnWidth){
12693                 c.setSize(Math.floor(c.columnWidth * pw) - m);
12694             }
12695         }
12696
12697         
12698         
12699         if (Ext.isIE) {
12700             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
12701                 var ts = this.getLayoutTargetSize();
12702                 if (ts.width != size.width){
12703                     this.adjustmentPass = true;
12704                     this.onLayout(ct, target);
12705                 }
12706             }
12707         }
12708         delete this.adjustmentPass;
12709     }
12710
12711     
12712 });
12713
12714 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
12715
12716 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
12717     
12718     monitorResize:true,
12719     
12720     rendered : false,
12721
12722     type: 'border',
12723
12724     targetCls: 'x-border-layout-ct',
12725
12726     getLayoutTargetSize : function() {
12727         var target = this.container.getLayoutTarget();
12728         return target ? target.getViewSize() : {};
12729     },
12730
12731     
12732     onLayout : function(ct, target){
12733         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
12734         if(!this.rendered){
12735             collapsed = [];
12736             for(i = 0; i < len; i++) {
12737                 c = items[i];
12738                 pos = c.region;
12739                 if(c.collapsed){
12740                     collapsed.push(c);
12741                 }
12742                 c.collapsed = false;
12743                 if(!c.rendered){
12744                     c.render(target, i);
12745                     c.getPositionEl().addClass('x-border-panel');
12746                 }
12747                 this[pos] = pos != 'center' && c.split ?
12748                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
12749                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
12750                 this[pos].render(target, c);
12751             }
12752             this.rendered = true;
12753         }
12754
12755         var size = this.getLayoutTargetSize();
12756         if(size.width < 20 || size.height < 20){ 
12757             if(collapsed){
12758                 this.restoreCollapsed = collapsed;
12759             }
12760             return;
12761         }else if(this.restoreCollapsed){
12762             collapsed = this.restoreCollapsed;
12763             delete this.restoreCollapsed;
12764         }
12765
12766         var w = size.width, h = size.height,
12767             centerW = w, centerH = h, centerY = 0, centerX = 0,
12768             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
12769             b, m, totalWidth, totalHeight;
12770         if(!c && Ext.layout.BorderLayout.WARN !== false){
12771             throw 'No center region defined in BorderLayout ' + ct.id;
12772         }
12773
12774         if(n && n.isVisible()){
12775             b = n.getSize();
12776             m = n.getMargins();
12777             b.width = w - (m.left+m.right);
12778             b.x = m.left;
12779             b.y = m.top;
12780             centerY = b.height + b.y + m.bottom;
12781             centerH -= centerY;
12782             n.applyLayout(b);
12783         }
12784         if(s && s.isVisible()){
12785             b = s.getSize();
12786             m = s.getMargins();
12787             b.width = w - (m.left+m.right);
12788             b.x = m.left;
12789             totalHeight = (b.height + m.top + m.bottom);
12790             b.y = h - totalHeight + m.top;
12791             centerH -= totalHeight;
12792             s.applyLayout(b);
12793         }
12794         if(west && west.isVisible()){
12795             b = west.getSize();
12796             m = west.getMargins();
12797             b.height = centerH - (m.top+m.bottom);
12798             b.x = m.left;
12799             b.y = centerY + m.top;
12800             totalWidth = (b.width + m.left + m.right);
12801             centerX += totalWidth;
12802             centerW -= totalWidth;
12803             west.applyLayout(b);
12804         }
12805         if(e && e.isVisible()){
12806             b = e.getSize();
12807             m = e.getMargins();
12808             b.height = centerH - (m.top+m.bottom);
12809             totalWidth = (b.width + m.left + m.right);
12810             b.x = w - totalWidth + m.left;
12811             b.y = centerY + m.top;
12812             centerW -= totalWidth;
12813             e.applyLayout(b);
12814         }
12815         if(c){
12816             m = c.getMargins();
12817             var centerBox = {
12818                 x: centerX + m.left,
12819                 y: centerY + m.top,
12820                 width: centerW - (m.left+m.right),
12821                 height: centerH - (m.top+m.bottom)
12822             };
12823             c.applyLayout(centerBox);
12824         }
12825         if(collapsed){
12826             for(i = 0, len = collapsed.length; i < len; i++){
12827                 collapsed[i].collapse(false);
12828             }
12829         }
12830         if(Ext.isIE && Ext.isStrict){ 
12831             target.repaint();
12832         }
12833         
12834         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
12835             var ts = this.getLayoutTargetSize();
12836             if (ts.width != size.width || ts.height != size.height){
12837                 this.adjustmentPass = true;
12838                 this.onLayout(ct, target);
12839             }
12840         }
12841         delete this.adjustmentPass;
12842     },
12843
12844     destroy: function() {
12845         var r = ['north', 'south', 'east', 'west'], i, region;
12846         for (i = 0; i < r.length; i++) {
12847             region = this[r[i]];
12848             if(region){
12849                 if(region.destroy){
12850                     region.destroy();
12851                 }else if (region.split){
12852                     region.split.destroy(true);
12853                 }
12854             }
12855         }
12856         Ext.layout.BorderLayout.superclass.destroy.call(this);
12857     }
12858
12859     
12860 });
12861
12862
12863 Ext.layout.BorderLayout.Region = function(layout, config, pos){
12864     Ext.apply(this, config);
12865     this.layout = layout;
12866     this.position = pos;
12867     this.state = {};
12868     if(typeof this.margins == 'string'){
12869         this.margins = this.layout.parseMargins(this.margins);
12870     }
12871     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
12872     if(this.collapsible){
12873         if(typeof this.cmargins == 'string'){
12874             this.cmargins = this.layout.parseMargins(this.cmargins);
12875         }
12876         if(this.collapseMode == 'mini' && !this.cmargins){
12877             this.cmargins = {left:0,top:0,right:0,bottom:0};
12878         }else{
12879             this.cmargins = Ext.applyIf(this.cmargins || {},
12880                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
12881         }
12882     }
12883 };
12884
12885 Ext.layout.BorderLayout.Region.prototype = {
12886     
12887     
12888     
12889     
12890     
12891     
12892     collapsible : false,
12893     
12894     split:false,
12895     
12896     floatable: true,
12897     
12898     minWidth:50,
12899     
12900     minHeight:50,
12901
12902     
12903     defaultMargins : {left:0,top:0,right:0,bottom:0},
12904     
12905     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
12906     
12907     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
12908     floatingZIndex: 100,
12909
12910     
12911     isCollapsed : false,
12912
12913     
12914     
12915     
12916
12917     
12918     render : function(ct, p){
12919         this.panel = p;
12920         p.el.enableDisplayMode();
12921         this.targetEl = ct;
12922         this.el = p.el;
12923
12924         var gs = p.getState, ps = this.position;
12925         p.getState = function(){
12926             return Ext.apply(gs.call(p) || {}, this.state);
12927         }.createDelegate(this);
12928
12929         if(ps != 'center'){
12930             p.allowQueuedExpand = false;
12931             p.on({
12932                 beforecollapse: this.beforeCollapse,
12933                 collapse: this.onCollapse,
12934                 beforeexpand: this.beforeExpand,
12935                 expand: this.onExpand,
12936                 hide: this.onHide,
12937                 show: this.onShow,
12938                 scope: this
12939             });
12940             if(this.collapsible || this.floatable){
12941                 p.collapseEl = 'el';
12942                 p.slideAnchor = this.getSlideAnchor();
12943             }
12944             if(p.tools && p.tools.toggle){
12945                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
12946                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
12947             }
12948         }
12949     },
12950
12951     
12952     getCollapsedEl : function(){
12953         if(!this.collapsedEl){
12954             if(!this.toolTemplate){
12955                 var tt = new Ext.Template(
12956                      '<div class="x-tool x-tool-{id}">&#160;</div>'
12957                 );
12958                 tt.disableFormats = true;
12959                 tt.compile();
12960                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
12961             }
12962             this.collapsedEl = this.targetEl.createChild({
12963                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
12964                 id: this.panel.id + '-xcollapsed'
12965             });
12966             this.collapsedEl.enableDisplayMode('block');
12967
12968             if(this.collapseMode == 'mini'){
12969                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
12970                 this.miniCollapsedEl = this.collapsedEl.createChild({
12971                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
12972                 });
12973                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
12974                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12975                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
12976             }else {
12977                 if(this.collapsible !== false && !this.hideCollapseTool) {
12978                     var t = this.expandToolEl = this.toolTemplate.append(
12979                             this.collapsedEl.dom,
12980                             {id:'expand-'+this.position}, true);
12981                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
12982                     t.on('click', this.onExpandClick, this, {stopEvent:true});
12983                 }
12984                 if(this.floatable !== false || this.titleCollapse){
12985                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12986                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
12987                 }
12988             }
12989         }
12990         return this.collapsedEl;
12991     },
12992
12993     
12994     onExpandClick : function(e){
12995         if(this.isSlid){
12996             this.panel.expand(false);
12997         }else{
12998             this.panel.expand();
12999         }
13000     },
13001
13002     
13003     onCollapseClick : function(e){
13004         this.panel.collapse();
13005     },
13006
13007     
13008     beforeCollapse : function(p, animate){
13009         this.lastAnim = animate;
13010         if(this.splitEl){
13011             this.splitEl.hide();
13012         }
13013         this.getCollapsedEl().show();
13014         var el = this.panel.getEl();
13015         this.originalZIndex = el.getStyle('z-index');
13016         el.setStyle('z-index', 100);
13017         this.isCollapsed = true;
13018         this.layout.layout();
13019     },
13020
13021     
13022     onCollapse : function(animate){
13023         this.panel.el.setStyle('z-index', 1);
13024         if(this.lastAnim === false || this.panel.animCollapse === false){
13025             this.getCollapsedEl().dom.style.visibility = 'visible';
13026         }else{
13027             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
13028         }
13029         this.state.collapsed = true;
13030         this.panel.saveState();
13031     },
13032
13033     
13034     beforeExpand : function(animate){
13035         if(this.isSlid){
13036             this.afterSlideIn();
13037         }
13038         var c = this.getCollapsedEl();
13039         this.el.show();
13040         if(this.position == 'east' || this.position == 'west'){
13041             this.panel.setSize(undefined, c.getHeight());
13042         }else{
13043             this.panel.setSize(c.getWidth(), undefined);
13044         }
13045         c.hide();
13046         c.dom.style.visibility = 'hidden';
13047         this.panel.el.setStyle('z-index', this.floatingZIndex);
13048     },
13049
13050     
13051     onExpand : function(){
13052         this.isCollapsed = false;
13053         if(this.splitEl){
13054             this.splitEl.show();
13055         }
13056         this.layout.layout();
13057         this.panel.el.setStyle('z-index', this.originalZIndex);
13058         this.state.collapsed = false;
13059         this.panel.saveState();
13060     },
13061
13062     
13063     collapseClick : function(e){
13064         if(this.isSlid){
13065            e.stopPropagation();
13066            this.slideIn();
13067         }else{
13068            e.stopPropagation();
13069            this.slideOut();
13070         }
13071     },
13072
13073     
13074     onHide : function(){
13075         if(this.isCollapsed){
13076             this.getCollapsedEl().hide();
13077         }else if(this.splitEl){
13078             this.splitEl.hide();
13079         }
13080     },
13081
13082     
13083     onShow : function(){
13084         if(this.isCollapsed){
13085             this.getCollapsedEl().show();
13086         }else if(this.splitEl){
13087             this.splitEl.show();
13088         }
13089     },
13090
13091     
13092     isVisible : function(){
13093         return !this.panel.hidden;
13094     },
13095
13096     
13097     getMargins : function(){
13098         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
13099     },
13100
13101     
13102     getSize : function(){
13103         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
13104     },
13105
13106     
13107     setPanel : function(panel){
13108         this.panel = panel;
13109     },
13110
13111     
13112     getMinWidth: function(){
13113         return this.minWidth;
13114     },
13115
13116     
13117     getMinHeight: function(){
13118         return this.minHeight;
13119     },
13120
13121     
13122     applyLayoutCollapsed : function(box){
13123         var ce = this.getCollapsedEl();
13124         ce.setLeftTop(box.x, box.y);
13125         ce.setSize(box.width, box.height);
13126     },
13127
13128     
13129     applyLayout : function(box){
13130         if(this.isCollapsed){
13131             this.applyLayoutCollapsed(box);
13132         }else{
13133             this.panel.setPosition(box.x, box.y);
13134             this.panel.setSize(box.width, box.height);
13135         }
13136     },
13137
13138     
13139     beforeSlide: function(){
13140         this.panel.beforeEffect();
13141     },
13142
13143     
13144     afterSlide : function(){
13145         this.panel.afterEffect();
13146     },
13147
13148     
13149     initAutoHide : function(){
13150         if(this.autoHide !== false){
13151             if(!this.autoHideHd){
13152                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
13153                 this.autoHideHd = {
13154                     "mouseout": function(e){
13155                         if(!e.within(this.el, true)){
13156                             this.autoHideSlideTask.delay(500);
13157                         }
13158                     },
13159                     "mouseover" : function(e){
13160                         this.autoHideSlideTask.cancel();
13161                     },
13162                     scope : this
13163                 };
13164             }
13165             this.el.on(this.autoHideHd);
13166             this.collapsedEl.on(this.autoHideHd);
13167         }
13168     },
13169
13170     
13171     clearAutoHide : function(){
13172         if(this.autoHide !== false){
13173             this.el.un("mouseout", this.autoHideHd.mouseout);
13174             this.el.un("mouseover", this.autoHideHd.mouseover);
13175             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
13176             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
13177         }
13178     },
13179
13180     
13181     clearMonitor : function(){
13182         Ext.getDoc().un("click", this.slideInIf, this);
13183     },
13184
13185     
13186     slideOut : function(){
13187         if(this.isSlid || this.el.hasActiveFx()){
13188             return;
13189         }
13190         this.isSlid = true;
13191         var ts = this.panel.tools, dh, pc;
13192         if(ts && ts.toggle){
13193             ts.toggle.hide();
13194         }
13195         this.el.show();
13196
13197         
13198         pc = this.panel.collapsed;
13199         this.panel.collapsed = false;
13200
13201         if(this.position == 'east' || this.position == 'west'){
13202             
13203             dh = this.panel.deferHeight;
13204             this.panel.deferHeight = false;
13205
13206             this.panel.setSize(undefined, this.collapsedEl.getHeight());
13207
13208             
13209             this.panel.deferHeight = dh;
13210         }else{
13211             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
13212         }
13213
13214         
13215         this.panel.collapsed = pc;
13216
13217         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
13218         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
13219         this.el.setStyle("z-index", this.floatingZIndex+2);
13220         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
13221         if(this.animFloat !== false){
13222             this.beforeSlide();
13223             this.el.slideIn(this.getSlideAnchor(), {
13224                 callback: function(){
13225                     this.afterSlide();
13226                     this.initAutoHide();
13227                     Ext.getDoc().on("click", this.slideInIf, this);
13228                 },
13229                 scope: this,
13230                 block: true
13231             });
13232         }else{
13233             this.initAutoHide();
13234              Ext.getDoc().on("click", this.slideInIf, this);
13235         }
13236     },
13237
13238     
13239     afterSlideIn : function(){
13240         this.clearAutoHide();
13241         this.isSlid = false;
13242         this.clearMonitor();
13243         this.el.setStyle("z-index", "");
13244         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
13245         this.el.dom.style.left = this.restoreLT[0];
13246         this.el.dom.style.top = this.restoreLT[1];
13247
13248         var ts = this.panel.tools;
13249         if(ts && ts.toggle){
13250             ts.toggle.show();
13251         }
13252     },
13253
13254     
13255     slideIn : function(cb){
13256         if(!this.isSlid || this.el.hasActiveFx()){
13257             Ext.callback(cb);
13258             return;
13259         }
13260         this.isSlid = false;
13261         if(this.animFloat !== false){
13262             this.beforeSlide();
13263             this.el.slideOut(this.getSlideAnchor(), {
13264                 callback: function(){
13265                     this.el.hide();
13266                     this.afterSlide();
13267                     this.afterSlideIn();
13268                     Ext.callback(cb);
13269                 },
13270                 scope: this,
13271                 block: true
13272             });
13273         }else{
13274             this.el.hide();
13275             this.afterSlideIn();
13276         }
13277     },
13278
13279     
13280     slideInIf : function(e){
13281         if(!e.within(this.el)){
13282             this.slideIn();
13283         }
13284     },
13285
13286     
13287     anchors : {
13288         "west" : "left",
13289         "east" : "right",
13290         "north" : "top",
13291         "south" : "bottom"
13292     },
13293
13294     
13295     sanchors : {
13296         "west" : "l",
13297         "east" : "r",
13298         "north" : "t",
13299         "south" : "b"
13300     },
13301
13302     
13303     canchors : {
13304         "west" : "tl-tr",
13305         "east" : "tr-tl",
13306         "north" : "tl-bl",
13307         "south" : "bl-tl"
13308     },
13309
13310     
13311     getAnchor : function(){
13312         return this.anchors[this.position];
13313     },
13314
13315     
13316     getCollapseAnchor : function(){
13317         return this.canchors[this.position];
13318     },
13319
13320     
13321     getSlideAnchor : function(){
13322         return this.sanchors[this.position];
13323     },
13324
13325     
13326     getAlignAdj : function(){
13327         var cm = this.cmargins;
13328         switch(this.position){
13329             case "west":
13330                 return [0, 0];
13331             break;
13332             case "east":
13333                 return [0, 0];
13334             break;
13335             case "north":
13336                 return [0, 0];
13337             break;
13338             case "south":
13339                 return [0, 0];
13340             break;
13341         }
13342     },
13343
13344     
13345     getExpandAdj : function(){
13346         var c = this.collapsedEl, cm = this.cmargins;
13347         switch(this.position){
13348             case "west":
13349                 return [-(cm.right+c.getWidth()+cm.left), 0];
13350             break;
13351             case "east":
13352                 return [cm.right+c.getWidth()+cm.left, 0];
13353             break;
13354             case "north":
13355                 return [0, -(cm.top+cm.bottom+c.getHeight())];
13356             break;
13357             case "south":
13358                 return [0, cm.top+cm.bottom+c.getHeight()];
13359             break;
13360         }
13361     },
13362
13363     destroy : function(){
13364         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
13365             this.autoHideSlideTask.cancel();
13366         }
13367         Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
13368     }
13369 };
13370
13371
13372 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
13373     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
13374     
13375     this.applyLayout = this.applyFns[pos];
13376 };
13377
13378 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
13379     
13380     
13381     splitTip : "Drag to resize.",
13382     
13383     collapsibleSplitTip : "Drag to resize. Double click to hide.",
13384     
13385     useSplitTips : false,
13386
13387     
13388     splitSettings : {
13389         north : {
13390             orientation: Ext.SplitBar.VERTICAL,
13391             placement: Ext.SplitBar.TOP,
13392             maxFn : 'getVMaxSize',
13393             minProp: 'minHeight',
13394             maxProp: 'maxHeight'
13395         },
13396         south : {
13397             orientation: Ext.SplitBar.VERTICAL,
13398             placement: Ext.SplitBar.BOTTOM,
13399             maxFn : 'getVMaxSize',
13400             minProp: 'minHeight',
13401             maxProp: 'maxHeight'
13402         },
13403         east : {
13404             orientation: Ext.SplitBar.HORIZONTAL,
13405             placement: Ext.SplitBar.RIGHT,
13406             maxFn : 'getHMaxSize',
13407             minProp: 'minWidth',
13408             maxProp: 'maxWidth'
13409         },
13410         west : {
13411             orientation: Ext.SplitBar.HORIZONTAL,
13412             placement: Ext.SplitBar.LEFT,
13413             maxFn : 'getHMaxSize',
13414             minProp: 'minWidth',
13415             maxProp: 'maxWidth'
13416         }
13417     },
13418
13419     
13420     applyFns : {
13421         west : function(box){
13422             if(this.isCollapsed){
13423                 return this.applyLayoutCollapsed(box);
13424             }
13425             var sd = this.splitEl.dom, s = sd.style;
13426             this.panel.setPosition(box.x, box.y);
13427             var sw = sd.offsetWidth;
13428             s.left = (box.x+box.width-sw)+'px';
13429             s.top = (box.y)+'px';
13430             s.height = Math.max(0, box.height)+'px';
13431             this.panel.setSize(box.width-sw, box.height);
13432         },
13433         east : function(box){
13434             if(this.isCollapsed){
13435                 return this.applyLayoutCollapsed(box);
13436             }
13437             var sd = this.splitEl.dom, s = sd.style;
13438             var sw = sd.offsetWidth;
13439             this.panel.setPosition(box.x+sw, box.y);
13440             s.left = (box.x)+'px';
13441             s.top = (box.y)+'px';
13442             s.height = Math.max(0, box.height)+'px';
13443             this.panel.setSize(box.width-sw, box.height);
13444         },
13445         north : function(box){
13446             if(this.isCollapsed){
13447                 return this.applyLayoutCollapsed(box);
13448             }
13449             var sd = this.splitEl.dom, s = sd.style;
13450             var sh = sd.offsetHeight;
13451             this.panel.setPosition(box.x, box.y);
13452             s.left = (box.x)+'px';
13453             s.top = (box.y+box.height-sh)+'px';
13454             s.width = Math.max(0, box.width)+'px';
13455             this.panel.setSize(box.width, box.height-sh);
13456         },
13457         south : function(box){
13458             if(this.isCollapsed){
13459                 return this.applyLayoutCollapsed(box);
13460             }
13461             var sd = this.splitEl.dom, s = sd.style;
13462             var sh = sd.offsetHeight;
13463             this.panel.setPosition(box.x, box.y+sh);
13464             s.left = (box.x)+'px';
13465             s.top = (box.y)+'px';
13466             s.width = Math.max(0, box.width)+'px';
13467             this.panel.setSize(box.width, box.height-sh);
13468         }
13469     },
13470
13471     
13472     render : function(ct, p){
13473         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
13474
13475         var ps = this.position;
13476
13477         this.splitEl = ct.createChild({
13478             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
13479             id: this.panel.id + '-xsplit'
13480         });
13481
13482         if(this.collapseMode == 'mini'){
13483             this.miniSplitEl = this.splitEl.createChild({
13484                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
13485             });
13486             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
13487             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
13488         }
13489
13490         var s = this.splitSettings[ps];
13491
13492         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
13493         this.split.tickSize = this.tickSize;
13494         this.split.placement = s.placement;
13495         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
13496         this.split.minSize = this.minSize || this[s.minProp];
13497         this.split.on("beforeapply", this.onSplitMove, this);
13498         this.split.useShim = this.useShim === true;
13499         this.maxSize = this.maxSize || this[s.maxProp];
13500
13501         if(p.hidden){
13502             this.splitEl.hide();
13503         }
13504
13505         if(this.useSplitTips){
13506             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
13507         }
13508         if(this.collapsible){
13509             this.splitEl.on("dblclick", this.onCollapseClick,  this);
13510         }
13511     },
13512
13513     
13514     getSize : function(){
13515         if(this.isCollapsed){
13516             return this.collapsedEl.getSize();
13517         }
13518         var s = this.panel.getSize();
13519         if(this.position == 'north' || this.position == 'south'){
13520             s.height += this.splitEl.dom.offsetHeight;
13521         }else{
13522             s.width += this.splitEl.dom.offsetWidth;
13523         }
13524         return s;
13525     },
13526
13527     
13528     getHMaxSize : function(){
13529          var cmax = this.maxSize || 10000;
13530          var center = this.layout.center;
13531          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
13532     },
13533
13534     
13535     getVMaxSize : function(){
13536         var cmax = this.maxSize || 10000;
13537         var center = this.layout.center;
13538         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
13539     },
13540
13541     
13542     onSplitMove : function(split, newSize){
13543         var s = this.panel.getSize();
13544         this.lastSplitSize = newSize;
13545         if(this.position == 'north' || this.position == 'south'){
13546             this.panel.setSize(s.width, newSize);
13547             this.state.height = newSize;
13548         }else{
13549             this.panel.setSize(newSize, s.height);
13550             this.state.width = newSize;
13551         }
13552         this.layout.layout();
13553         this.panel.saveState();
13554         return false;
13555     },
13556
13557     
13558     getSplitBar : function(){
13559         return this.split;
13560     },
13561
13562     
13563     destroy : function() {
13564         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
13565         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
13566     }
13567 });
13568
13569 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
13570
13571 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
13572
13573     
13574     labelSeparator : ':',
13575
13576     
13577
13578     
13579     trackLabels: false,
13580
13581     type: 'form',
13582
13583     onRemove: function(c){
13584         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
13585         if(this.trackLabels){
13586             c.un('show', this.onFieldShow, this);
13587             c.un('hide', this.onFieldHide, this);
13588         }
13589         
13590         var el = c.getPositionEl(),
13591             ct = c.getItemCt && c.getItemCt();
13592         if (c.rendered && ct) {
13593             if (el && el.dom) {
13594                 el.insertAfter(ct);
13595             }
13596             Ext.destroy(ct);
13597             Ext.destroyMembers(c, 'label', 'itemCt');
13598             if (c.customItemCt) {
13599                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
13600             }
13601         }
13602     },
13603
13604     
13605     setContainer : function(ct){
13606         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
13607         if(ct.labelAlign){
13608             ct.addClass('x-form-label-'+ct.labelAlign);
13609         }
13610
13611         if(ct.hideLabels){
13612             Ext.apply(this, {
13613                 labelStyle: 'display:none',
13614                 elementStyle: 'padding-left:0;',
13615                 labelAdjust: 0
13616             });
13617         }else{
13618             this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
13619             ct.labelWidth = ct.labelWidth || 100;
13620             if(Ext.isNumber(ct.labelWidth)){
13621                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
13622                 Ext.apply(this, {
13623                     labelAdjust: ct.labelWidth + pad,
13624                     labelStyle: 'width:' + ct.labelWidth + 'px;',
13625                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
13626                 });
13627             }
13628             if(ct.labelAlign == 'top'){
13629                 Ext.apply(this, {
13630                     labelStyle: 'width:auto;',
13631                     labelAdjust: 0,
13632                     elementStyle: 'padding-left:0;'
13633                 });
13634             }
13635         }
13636     },
13637
13638     
13639     isHide: function(c){
13640         return c.hideLabel || this.container.hideLabels;
13641     },
13642
13643     onFieldShow: function(c){
13644         c.getItemCt().removeClass('x-hide-' + c.hideMode);
13645
13646         
13647         if (c.isComposite) {
13648             c.doLayout();
13649         }
13650     },
13651
13652     onFieldHide: function(c){
13653         c.getItemCt().addClass('x-hide-' + c.hideMode);
13654     },
13655
13656     
13657     getLabelStyle: function(s){
13658         var ls = '', items = [this.labelStyle, s];
13659         for (var i = 0, len = items.length; i < len; ++i){
13660             if (items[i]){
13661                 ls += items[i];
13662                 if (ls.substr(-1, 1) != ';'){
13663                     ls += ';';
13664                 }
13665             }
13666         }
13667         return ls;
13668     },
13669
13670     
13671
13672     
13673     renderItem : function(c, position, target){
13674         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
13675             var args = this.getTemplateArgs(c);
13676             if(Ext.isNumber(position)){
13677                 position = target.dom.childNodes[position] || null;
13678             }
13679             if(position){
13680                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
13681             }else{
13682                 c.itemCt = this.fieldTpl.append(target, args, true);
13683             }
13684             if(!c.getItemCt){
13685                 
13686                 
13687                 Ext.apply(c, {
13688                     getItemCt: function(){
13689                         return c.itemCt;
13690                     },
13691                     customItemCt: true
13692                 });
13693             }
13694             c.label = c.getItemCt().child('label.x-form-item-label');
13695             if(!c.rendered){
13696                 c.render('x-form-el-' + c.id);
13697             }else if(!this.isValidParent(c, target)){
13698                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
13699             }
13700             if(this.trackLabels){
13701                 if(c.hidden){
13702                     this.onFieldHide(c);
13703                 }
13704                 c.on({
13705                     scope: this,
13706                     show: this.onFieldShow,
13707                     hide: this.onFieldHide
13708                 });
13709             }
13710             this.configureItem(c);
13711         }else {
13712             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
13713         }
13714     },
13715
13716     
13717     getTemplateArgs: function(field) {
13718         var noLabelSep = !field.fieldLabel || field.hideLabel;
13719
13720         return {
13721             id            : field.id,
13722             label         : field.fieldLabel,
13723             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
13724             clearCls      : field.clearCls || 'x-form-clear-left',
13725             labelStyle    : this.getLabelStyle(field.labelStyle),
13726             elementStyle  : this.elementStyle || '',
13727             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
13728         };
13729     },
13730
13731     
13732     adjustWidthAnchor: function(value, c){
13733         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
13734             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
13735             return value - this.labelAdjust + (adjust ? -3 : 0);
13736         }
13737         return value;
13738     },
13739
13740     adjustHeightAnchor : function(value, c){
13741         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
13742             return value - c.label.getHeight();
13743         }
13744         return value;
13745     },
13746
13747     
13748     isValidParent : function(c, target){
13749         return target && this.container.getEl().contains(c.getPositionEl());
13750     }
13751
13752     
13753 });
13754
13755 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
13756
13757 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
13758     
13759     fill : true,
13760     
13761     autoWidth : true,
13762     
13763     titleCollapse : true,
13764     
13765     hideCollapseTool : false,
13766     
13767     collapseFirst : false,
13768     
13769     animate : false,
13770     
13771     sequence : false,
13772     
13773     activeOnTop : false,
13774
13775     type: 'accordion',
13776
13777     renderItem : function(c){
13778         if(this.animate === false){
13779             c.animCollapse = false;
13780         }
13781         c.collapsible = true;
13782         if(this.autoWidth){
13783             c.autoWidth = true;
13784         }
13785         if(this.titleCollapse){
13786             c.titleCollapse = true;
13787         }
13788         if(this.hideCollapseTool){
13789             c.hideCollapseTool = true;
13790         }
13791         if(this.collapseFirst !== undefined){
13792             c.collapseFirst = this.collapseFirst;
13793         }
13794         if(!this.activeItem && !c.collapsed){
13795             this.setActiveItem(c, true);
13796         }else if(this.activeItem && this.activeItem != c){
13797             c.collapsed = true;
13798         }
13799         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
13800         c.header.addClass('x-accordion-hd');
13801         c.on('beforeexpand', this.beforeExpand, this);
13802     },
13803
13804     onRemove: function(c){
13805         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
13806         if(c.rendered){
13807             c.header.removeClass('x-accordion-hd');
13808         }
13809         c.un('beforeexpand', this.beforeExpand, this);
13810     },
13811
13812     
13813     beforeExpand : function(p, anim){
13814         var ai = this.activeItem;
13815         if(ai){
13816             if(this.sequence){
13817                 delete this.activeItem;
13818                 if (!ai.collapsed){
13819                     ai.collapse({callback:function(){
13820                         p.expand(anim || true);
13821                     }, scope: this});
13822                     return false;
13823                 }
13824             }else{
13825                 ai.collapse(this.animate);
13826             }
13827         }
13828         this.setActive(p);
13829         if(this.activeOnTop){
13830             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
13831         }
13832         
13833         this.layout();
13834     },
13835
13836     
13837     setItemSize : function(item, size){
13838         if(this.fill && item){
13839             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
13840             
13841             for (i = 0; i < len; i++) {
13842                 if((p = ct[i]) != item && !p.hidden){
13843                     hh += p.header.getHeight();
13844                 }
13845             };
13846             
13847             size.height -= hh;
13848             
13849             
13850             item.setSize(size);
13851         }
13852     },
13853
13854     
13855     setActiveItem : function(item){
13856         this.setActive(item, true);
13857     },
13858
13859     
13860     setActive : function(item, expand){
13861         var ai = this.activeItem;
13862         item = this.container.getComponent(item);
13863         if(ai != item){
13864             if(item.rendered && item.collapsed && expand){
13865                 item.expand();
13866             }else{
13867                 if(ai){
13868                    ai.fireEvent('deactivate', ai);
13869                 }
13870                 this.activeItem = item;
13871                 item.fireEvent('activate', item);
13872             }
13873         }
13874     }
13875 });
13876 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
13877
13878
13879 Ext.layout.Accordion = Ext.layout.AccordionLayout;
13880 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
13881     
13882
13883     
13884     monitorResize:false,
13885
13886     type: 'table',
13887
13888     targetCls: 'x-table-layout-ct',
13889
13890     
13891     tableAttrs:null,
13892
13893     
13894     setContainer : function(ct){
13895         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
13896
13897         this.currentRow = 0;
13898         this.currentColumn = 0;
13899         this.cells = [];
13900     },
13901     
13902     
13903     onLayout : function(ct, target){
13904         var cs = ct.items.items, len = cs.length, c, i;
13905
13906         if(!this.table){
13907             target.addClass('x-table-layout-ct');
13908
13909             this.table = target.createChild(
13910                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
13911         }
13912         this.renderAll(ct, target);
13913     },
13914
13915     
13916     getRow : function(index){
13917         var row = this.table.tBodies[0].childNodes[index];
13918         if(!row){
13919             row = document.createElement('tr');
13920             this.table.tBodies[0].appendChild(row);
13921         }
13922         return row;
13923     },
13924
13925     
13926     getNextCell : function(c){
13927         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
13928         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
13929         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
13930             if(!this.cells[rowIndex]){
13931                 this.cells[rowIndex] = [];
13932             }
13933             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
13934                 this.cells[rowIndex][colIndex] = true;
13935             }
13936         }
13937         var td = document.createElement('td');
13938         if(c.cellId){
13939             td.id = c.cellId;
13940         }
13941         var cls = 'x-table-layout-cell';
13942         if(c.cellCls){
13943             cls += ' ' + c.cellCls;
13944         }
13945         td.className = cls;
13946         if(c.colspan){
13947             td.colSpan = c.colspan;
13948         }
13949         if(c.rowspan){
13950             td.rowSpan = c.rowspan;
13951         }
13952         this.getRow(curRow).appendChild(td);
13953         return td;
13954     },
13955
13956     
13957     getNextNonSpan: function(colIndex, rowIndex){
13958         var cols = this.columns;
13959         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
13960             if(cols && colIndex >= cols){
13961                 rowIndex++;
13962                 colIndex = 0;
13963             }else{
13964                 colIndex++;
13965             }
13966         }
13967         return [colIndex, rowIndex];
13968     },
13969
13970     
13971     renderItem : function(c, position, target){
13972         
13973         if(!this.table){
13974             this.table = target.createChild(
13975                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
13976         }
13977         if(c && !c.rendered){
13978             c.render(this.getNextCell(c));
13979             this.configureItem(c, position);
13980         }else if(c && !this.isValidParent(c, target)){
13981             var container = this.getNextCell(c);
13982             container.insertBefore(c.getPositionEl().dom, null);
13983             c.container = Ext.get(container);
13984             this.configureItem(c, position);
13985         }
13986     },
13987
13988     
13989     isValidParent : function(c, target){
13990         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
13991     },
13992     
13993     destroy: function(){
13994         delete this.table;
13995         Ext.layout.TableLayout.superclass.destroy.call(this);
13996     }
13997
13998     
13999 });
14000
14001 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
14002 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
14003
14004     extraCls: 'x-abs-layout-item',
14005
14006     type: 'absolute',
14007
14008     onLayout : function(ct, target){
14009         target.position();
14010         this.paddingLeft = target.getPadding('l');
14011         this.paddingTop = target.getPadding('t');
14012         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
14013     },
14014
14015     
14016     adjustWidthAnchor : function(value, comp){
14017         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
14018     },
14019
14020     
14021     adjustHeightAnchor : function(value, comp){
14022         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
14023     }
14024     
14025 });
14026 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
14027
14028 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
14029     
14030     defaultMargins : {left:0,top:0,right:0,bottom:0},
14031     
14032     padding : '0',
14033     
14034     pack : 'start',
14035
14036     
14037     monitorResize : true,
14038     type: 'box',
14039     scrollOffset : 0,
14040     extraCls : 'x-box-item',
14041     targetCls : 'x-box-layout-ct',
14042     innerCls : 'x-box-inner',
14043
14044     constructor : function(config){
14045         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
14046
14047         if (Ext.isString(this.defaultMargins)) {
14048             this.defaultMargins = this.parseMargins(this.defaultMargins);
14049         }
14050     },
14051
14052     
14053     onLayout: function(container, target) {
14054         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
14055
14056         var items = this.getVisibleItems(container),
14057             tSize = this.getLayoutTargetSize();
14058
14059         
14060         this.layoutTargetLastSize = tSize;
14061
14062         
14063         this.childBoxCache = this.calculateChildBoxes(items, tSize);
14064
14065         this.updateInnerCtSize(tSize, this.childBoxCache);
14066         this.updateChildBoxes(this.childBoxCache.boxes);
14067
14068         
14069         this.handleTargetOverflow(tSize, container, target);
14070     },
14071
14072     
14073     updateChildBoxes: function(boxes) {
14074         for (var i = 0, length = boxes.length; i < length; i++) {
14075             var box  = boxes[i],
14076                 comp = box.component;
14077
14078             if (box.dirtySize) {
14079                 comp.setSize(box.width, box.height);
14080             }
14081             
14082             if (isNaN(box.left) || isNaN(box.top)) {
14083                 continue;
14084             }
14085             comp.setPosition(box.left, box.top);
14086         }
14087     },
14088
14089     
14090     updateInnerCtSize: Ext.emptyFn,
14091
14092     
14093     handleTargetOverflow: function(previousTargetSize, container, target) {
14094         var overflow = target.getStyle('overflow');
14095
14096         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
14097             var newTargetSize = this.getLayoutTargetSize();
14098             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
14099                 this.adjustmentPass = true;
14100                 this.onLayout(container, target);
14101             }
14102         }
14103
14104         delete this.adjustmentPass;
14105     },
14106
14107     
14108     isValidParent : function(c, target){
14109         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
14110     },
14111
14112     
14113     getVisibleItems: function(ct) {
14114         var ct  = ct || this.container,
14115             t   = ct.getLayoutTarget(),
14116             cti = ct.items.items,
14117             len = cti.length,
14118
14119             i, c, items = [];
14120
14121         for (i = 0; i < len; i++) {
14122             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
14123                 items.push(c);
14124             }
14125         }
14126
14127         return items;
14128     },
14129
14130     
14131     renderAll : function(ct, target){
14132         if(!this.innerCt){
14133             
14134             
14135             this.innerCt = target.createChild({cls:this.innerCls});
14136             this.padding = this.parseMargins(this.padding);
14137         }
14138         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
14139     },
14140
14141     getLayoutTargetSize : function(){
14142         var target = this.container.getLayoutTarget(), ret;
14143         if (target) {
14144             ret = target.getViewSize();
14145
14146             
14147             
14148             
14149             if (Ext.isIE && Ext.isStrict && ret.width == 0){
14150                 ret =  target.getStyleSize();
14151             }
14152
14153             ret.width -= target.getPadding('lr');
14154             ret.height -= target.getPadding('tb');
14155         }
14156         return ret;
14157     },
14158
14159     
14160     renderItem : function(c){
14161         if(Ext.isString(c.margins)){
14162             c.margins = this.parseMargins(c.margins);
14163         }else if(!c.margins){
14164             c.margins = this.defaultMargins;
14165         }
14166         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
14167     }
14168 });
14169
14170
14171 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
14172     
14173     align : 'left', 
14174     type: 'vbox',
14175
14176     
14177
14178     
14179
14180     
14181     updateInnerCtSize: function(tSize, calcs) {
14182         var innerCtHeight = tSize.height,
14183             innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
14184
14185         if (this.align == 'stretch') {
14186             innerCtWidth = tSize.width;
14187         } else if (this.align == 'center') {
14188             innerCtWidth = Math.max(tSize.width, innerCtWidth);
14189         }
14190
14191         
14192         
14193         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
14194     },
14195
14196     
14197     calculateChildBoxes: function(visibleItems, targetSize) {
14198         var visibleCount = visibleItems.length,
14199
14200             padding      = this.padding,
14201             topOffset    = padding.top,
14202             leftOffset   = padding.left,
14203             paddingVert  = topOffset  + padding.bottom,
14204             paddingHoriz = leftOffset + padding.right,
14205
14206             width        = targetSize.width - this.scrollOffset,
14207             height       = targetSize.height,
14208             availWidth   = Math.max(0, width - paddingHoriz),
14209
14210             isStart      = this.pack == 'start',
14211             isCenter     = this.pack == 'center',
14212             isEnd        = this.pack == 'end',
14213
14214             nonFlexHeight= 0,
14215             maxWidth     = 0,
14216             totalFlex    = 0,
14217
14218             
14219             boxes        = [],
14220
14221             
14222             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
14223
14224             
14225             for (i = 0; i < visibleCount; i++) {
14226                 child = visibleItems[i];
14227                 childHeight = child.height;
14228                 childWidth  = child.width;
14229                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
14230
14231
14232                 
14233                 if (!Ext.isNumber(childHeight)) {
14234
14235                     
14236                     if (child.flex && !childHeight) {
14237                         totalFlex += child.flex;
14238
14239                     
14240                     } else {
14241                         
14242                         
14243                         if (!childHeight && canLayout) {
14244                             child.doLayout();
14245                         }
14246
14247                         childSize = child.getSize();
14248                         childWidth = childSize.width;
14249                         childHeight = childSize.height;
14250                     }
14251                 }
14252
14253                 childMargins = child.margins;
14254
14255                 nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
14256
14257                 
14258                 if (!Ext.isNumber(childWidth)) {
14259                     if (canLayout) {
14260                         child.doLayout();
14261                     }
14262                     childWidth = child.getWidth();
14263                 }
14264
14265                 maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
14266
14267                 
14268                 boxes.push({
14269                     component: child,
14270                     height   : childHeight || undefined,
14271                     width    : childWidth || undefined
14272                 });
14273             }
14274
14275             
14276             var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
14277
14278             if (isCenter) {
14279                 topOffset += availableHeight / 2;
14280             } else if (isEnd) {
14281                 topOffset += availableHeight;
14282             }
14283
14284             
14285             var remainingHeight = availableHeight,
14286                 remainingFlex   = totalFlex;
14287
14288             
14289             for (i = 0; i < visibleCount; i++) {
14290                 child = visibleItems[i];
14291                 calcs = boxes[i];
14292
14293                 childMargins = child.margins;
14294                 horizMargins = childMargins.left + childMargins.right;
14295
14296                 topOffset   += childMargins.top;
14297
14298                 if (isStart && child.flex && !child.height) {
14299                     flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
14300                     remainingHeight -= flexedHeight;
14301                     remainingFlex   -= child.flex;
14302
14303                     calcs.height = flexedHeight;
14304                     calcs.dirtySize = true;
14305                 }
14306
14307                 calcs.left = leftOffset + childMargins.left;
14308                 calcs.top  = topOffset;
14309
14310                 switch (this.align) {
14311                     case 'stretch':
14312                         stretchWidth = availWidth - horizMargins;
14313                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
14314                         calcs.dirtySize = true;
14315                         break;
14316                     case 'stretchmax':
14317                         stretchWidth = maxWidth - horizMargins;
14318                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
14319                         calcs.dirtySize = true;
14320                         break;
14321                     case 'center':
14322                         var diff = availWidth - calcs.width - horizMargins;
14323                         if (diff > 0) {
14324                             calcs.left = leftOffset + horizMargins + (diff / 2);
14325                         }
14326                 }
14327
14328                 topOffset += calcs.height + childMargins.bottom;
14329             }
14330
14331         return {
14332             boxes: boxes,
14333             meta : {
14334                 maxWidth: maxWidth
14335             }
14336         };
14337     }
14338 });
14339
14340 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
14341
14342
14343 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
14344     
14345     align: 'top', 
14346
14347     type : 'hbox',
14348
14349     
14350     updateInnerCtSize: function(tSize, calcs) {
14351         var innerCtWidth  = tSize.width,
14352             innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
14353
14354         if (this.align == 'stretch') {
14355             innerCtHeight = tSize.height;
14356         } else if (this.align == 'middle') {
14357             innerCtHeight = Math.max(tSize.height, innerCtHeight);
14358         }
14359
14360         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
14361     },
14362
14363     
14364     
14365
14366     
14367     calculateChildBoxes: function(visibleItems, targetSize) {
14368         var visibleCount = visibleItems.length,
14369
14370             padding      = this.padding,
14371             topOffset    = padding.top,
14372             leftOffset   = padding.left,
14373             paddingVert  = topOffset  + padding.bottom,
14374             paddingHoriz = leftOffset + padding.right,
14375
14376             width        = targetSize.width - this.scrollOffset,
14377             height       = targetSize.height,
14378             availHeight  = Math.max(0, height - paddingVert),
14379
14380             isStart      = this.pack == 'start',
14381             isCenter     = this.pack == 'center',
14382             isEnd        = this.pack == 'end',
14383             
14384
14385             nonFlexWidth = 0,
14386             maxHeight    = 0,
14387             totalFlex    = 0,
14388
14389             
14390             boxes        = [],
14391
14392             
14393             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
14394
14395             
14396             for (i = 0; i < visibleCount; i++) {
14397                 child       = visibleItems[i];
14398                 childHeight = child.height;
14399                 childWidth  = child.width;
14400                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
14401
14402                 
14403                 if (!Ext.isNumber(childWidth)) {
14404
14405                     
14406                     if (child.flex && !childWidth) {
14407                         totalFlex += child.flex;
14408
14409                     
14410                     } else {
14411                         
14412                         
14413                         if (!childWidth && canLayout) {
14414                             child.doLayout();
14415                         }
14416
14417                         childSize   = child.getSize();
14418                         childWidth  = childSize.width;
14419                         childHeight = childSize.height;
14420                     }
14421                 }
14422
14423                 childMargins = child.margins;
14424
14425                 nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
14426
14427                 
14428                 if (!Ext.isNumber(childHeight)) {
14429                     if (canLayout) {
14430                         child.doLayout();
14431                     }
14432                     childHeight = child.getHeight();
14433                 }
14434
14435                 maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
14436
14437                 
14438                 boxes.push({
14439                     component: child,
14440                     height   : childHeight || undefined,
14441                     width    : childWidth || undefined
14442                 });
14443             }
14444
14445             
14446             var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
14447
14448             if (isCenter) {
14449                 leftOffset += availableWidth / 2;
14450             } else if (isEnd) {
14451                 leftOffset += availableWidth;
14452             }
14453
14454             
14455             var remainingWidth = availableWidth,
14456                 remainingFlex  = totalFlex;
14457
14458             
14459             for (i = 0; i < visibleCount; i++) {
14460                 child = visibleItems[i];
14461                 calcs = boxes[i];
14462
14463                 childMargins = child.margins;
14464                 vertMargins  = childMargins.top + childMargins.bottom;
14465
14466                 leftOffset  += childMargins.left;
14467
14468                 if (isStart && child.flex && !child.width) {
14469                     flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
14470                     remainingWidth -= flexedWidth;
14471                     remainingFlex  -= child.flex;
14472
14473                     calcs.width = flexedWidth;
14474                     calcs.dirtySize = true;
14475                 }
14476
14477                 calcs.left = leftOffset;
14478                 calcs.top  = topOffset + childMargins.top;
14479
14480                 switch (this.align) {
14481                     case 'stretch':
14482                         stretchHeight = availHeight - vertMargins;
14483                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
14484                         calcs.dirtySize = true;
14485                         break;
14486                     case 'stretchmax':
14487                         stretchHeight = maxHeight - vertMargins;
14488                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
14489                         calcs.dirtySize = true;
14490                         break;
14491                     case 'middle':
14492                         var diff = availHeight - calcs.height - vertMargins;
14493                         if (diff > 0) {
14494                             calcs.top = topOffset + vertMargins + (diff / 2);
14495                         }
14496                 }
14497                 leftOffset += calcs.width + childMargins.right;
14498             }
14499
14500         return {
14501             boxes: boxes,
14502             meta : {
14503                 maxHeight: maxHeight
14504             }
14505         };
14506     }
14507 });
14508
14509 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
14510
14511 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
14512     monitorResize : true,
14513
14514     type: 'toolbar',
14515
14516     
14517     triggerWidth: 18,
14518
14519     
14520     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
14521
14522     
14523     lastOverflow: false,
14524
14525     
14526     tableHTML: [
14527         '<table cellspacing="0" class="x-toolbar-ct">',
14528             '<tbody>',
14529                 '<tr>',
14530                     '<td class="x-toolbar-left" align="{0}">',
14531                         '<table cellspacing="0">',
14532                             '<tbody>',
14533                                 '<tr class="x-toolbar-left-row"></tr>',
14534                             '</tbody>',
14535                         '</table>',
14536                     '</td>',
14537                     '<td class="x-toolbar-right" align="right">',
14538                         '<table cellspacing="0" class="x-toolbar-right-ct">',
14539                             '<tbody>',
14540                                 '<tr>',
14541                                     '<td>',
14542                                         '<table cellspacing="0">',
14543                                             '<tbody>',
14544                                                 '<tr class="x-toolbar-right-row"></tr>',
14545                                             '</tbody>',
14546                                         '</table>',
14547                                     '</td>',
14548                                     '<td>',
14549                                         '<table cellspacing="0">',
14550                                             '<tbody>',
14551                                                 '<tr class="x-toolbar-extras-row"></tr>',
14552                                             '</tbody>',
14553                                         '</table>',
14554                                     '</td>',
14555                                 '</tr>',
14556                             '</tbody>',
14557                         '</table>',
14558                     '</td>',
14559                 '</tr>',
14560             '</tbody>',
14561         '</table>'
14562     ].join(""),
14563
14564     
14565     onLayout : function(ct, target) {
14566         
14567         if (!this.leftTr) {
14568             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
14569
14570             target.addClass('x-toolbar-layout-ct');
14571             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
14572
14573             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
14574             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
14575             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
14576
14577             if (this.hiddenItem == undefined) {
14578                 
14579                 this.hiddenItems = [];
14580             }
14581         }
14582
14583         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
14584             items    = ct.items.items,
14585             position = 0;
14586
14587         
14588         for (var i = 0, len = items.length, c; i < len; i++, position++) {
14589             c = items[i];
14590
14591             if (c.isFill) {
14592                 side   = this.rightTr;
14593                 position = -1;
14594             } else if (!c.rendered) {
14595                 c.render(this.insertCell(c, side, position));
14596             } else {
14597                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
14598                     var td = this.insertCell(c, side, position);
14599                     td.appendChild(c.getPositionEl().dom);
14600                     c.container = Ext.get(td);
14601                 }
14602             }
14603         }
14604
14605         
14606         this.cleanup(this.leftTr);
14607         this.cleanup(this.rightTr);
14608         this.cleanup(this.extrasTr);
14609         this.fitToSize(target);
14610     },
14611
14612     
14613     cleanup : function(el) {
14614         var cn = el.childNodes, i, c;
14615
14616         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
14617             if (!c.firstChild) {
14618                 el.removeChild(c);
14619             }
14620         }
14621     },
14622
14623     
14624     insertCell : function(c, target, position) {
14625         var td = document.createElement('td');
14626         td.className = 'x-toolbar-cell';
14627
14628         target.insertBefore(td, target.childNodes[position] || null);
14629
14630         return td;
14631     },
14632
14633     
14634     hideItem : function(item) {
14635         this.hiddenItems.push(item);
14636
14637         item.xtbHidden = true;
14638         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
14639         item.hide();
14640     },
14641
14642     
14643     unhideItem : function(item) {
14644         item.show();
14645         item.xtbHidden = false;
14646         this.hiddenItems.remove(item);
14647     },
14648
14649     
14650     getItemWidth : function(c) {
14651         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
14652     },
14653
14654     
14655     fitToSize : function(target) {
14656         if (this.container.enableOverflow === false) {
14657             return;
14658         }
14659
14660         var width       = target.dom.clientWidth,
14661             tableWidth  = target.dom.firstChild.offsetWidth,
14662             clipWidth   = width - this.triggerWidth,
14663             lastWidth   = this.lastWidth || 0,
14664
14665             hiddenItems = this.hiddenItems,
14666             hasHiddens  = hiddenItems.length != 0,
14667             isLarger    = width >= lastWidth;
14668
14669         this.lastWidth  = width;
14670
14671         if (tableWidth > width || (hasHiddens && isLarger)) {
14672             var items     = this.container.items.items,
14673                 len       = items.length,
14674                 loopWidth = 0,
14675                 item;
14676
14677             for (var i = 0; i < len; i++) {
14678                 item = items[i];
14679
14680                 if (!item.isFill) {
14681                     loopWidth += this.getItemWidth(item);
14682                     if (loopWidth > clipWidth) {
14683                         if (!(item.hidden || item.xtbHidden)) {
14684                             this.hideItem(item);
14685                         }
14686                     } else if (item.xtbHidden) {
14687                         this.unhideItem(item);
14688                     }
14689                 }
14690             }
14691         }
14692
14693         
14694         hasHiddens = hiddenItems.length != 0;
14695
14696         if (hasHiddens) {
14697             this.initMore();
14698
14699             if (!this.lastOverflow) {
14700                 this.container.fireEvent('overflowchange', this.container, true);
14701                 this.lastOverflow = true;
14702             }
14703         } else if (this.more) {
14704             this.clearMenu();
14705             this.more.destroy();
14706             delete this.more;
14707
14708             if (this.lastOverflow) {
14709                 this.container.fireEvent('overflowchange', this.container, false);
14710                 this.lastOverflow = false;
14711             }
14712         }
14713     },
14714
14715     
14716     createMenuConfig : function(component, hideOnClick){
14717         var config = Ext.apply({}, component.initialConfig),
14718             group  = component.toggleGroup;
14719
14720         Ext.copyTo(config, component, [
14721             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
14722         ]);
14723
14724         Ext.apply(config, {
14725             text       : component.overflowText || component.text,
14726             hideOnClick: hideOnClick
14727         });
14728
14729         if (group || component.enableToggle) {
14730             Ext.apply(config, {
14731                 group  : group,
14732                 checked: component.pressed,
14733                 listeners: {
14734                     checkchange: function(item, checked){
14735                         component.toggle(checked);
14736                     }
14737                 }
14738             });
14739         }
14740
14741         delete config.ownerCt;
14742         delete config.xtype;
14743         delete config.id;
14744
14745         return config;
14746     },
14747
14748     
14749     addComponentToMenu : function(menu, component) {
14750         if (component instanceof Ext.Toolbar.Separator) {
14751             menu.add('-');
14752
14753         } else if (Ext.isFunction(component.isXType)) {
14754             if (component.isXType('splitbutton')) {
14755                 menu.add(this.createMenuConfig(component, true));
14756
14757             } else if (component.isXType('button')) {
14758                 menu.add(this.createMenuConfig(component, !component.menu));
14759
14760             } else if (component.isXType('buttongroup')) {
14761                 component.items.each(function(item){
14762                      this.addComponentToMenu(menu, item);
14763                 }, this);
14764             }
14765         }
14766     },
14767
14768     
14769     clearMenu : function(){
14770         var menu = this.moreMenu;
14771         if (menu && menu.items) {
14772             menu.items.each(function(item){
14773                 delete item.menu;
14774             });
14775         }
14776     },
14777
14778     
14779     beforeMoreShow : function(menu) {
14780         var items = this.container.items.items,
14781             len   = items.length,
14782             item,
14783             prev;
14784
14785         var needsSep = function(group, item){
14786             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
14787         };
14788
14789         this.clearMenu();
14790         menu.removeAll();
14791         for (var i = 0; i < len; i++) {
14792             item = items[i];
14793             if (item.xtbHidden) {
14794                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
14795                     menu.add('-');
14796                 }
14797                 this.addComponentToMenu(menu, item);
14798                 prev = item;
14799             }
14800         }
14801
14802         
14803         if (menu.items.length < 1) {
14804             menu.add(this.noItemsMenuText);
14805         }
14806     },
14807
14808     
14809     initMore : function(){
14810         if (!this.more) {
14811             
14812             this.moreMenu = new Ext.menu.Menu({
14813                 ownerCt : this.container,
14814                 listeners: {
14815                     beforeshow: this.beforeMoreShow,
14816                     scope: this
14817                 }
14818             });
14819
14820             
14821             this.more = new Ext.Button({
14822                 iconCls: 'x-toolbar-more-icon',
14823                 cls    : 'x-toolbar-more',
14824                 menu   : this.moreMenu,
14825                 ownerCt: this.container
14826             });
14827
14828             var td = this.insertCell(this.more, this.extrasTr, 100);
14829             this.more.render(td);
14830         }
14831     },
14832
14833     destroy : function(){
14834         Ext.destroy(this.more, this.moreMenu);
14835         delete this.leftTr;
14836         delete this.rightTr;
14837         delete this.extrasTr;
14838         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
14839     }
14840 });
14841
14842 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
14843
14844  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
14845     monitorResize : true,
14846
14847     type: 'menu',
14848
14849     setContainer : function(ct){
14850         this.monitorResize = !ct.floating;
14851         
14852         
14853         ct.on('autosize', this.doAutoSize, this);
14854         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
14855     },
14856
14857     renderItem : function(c, position, target){
14858         if (!this.itemTpl) {
14859             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
14860                 '<li id="{itemId}" class="{itemCls}">',
14861                     '<tpl if="needsIcon">',
14862                         '<img src="{icon}" class="{iconCls}"/>',
14863                     '</tpl>',
14864                 '</li>'
14865             );
14866         }
14867
14868         if(c && !c.rendered){
14869             if(Ext.isNumber(position)){
14870                 position = target.dom.childNodes[position];
14871             }
14872             var a = this.getItemArgs(c);
14873
14874
14875             c.render(c.positionEl = position ?
14876                 this.itemTpl.insertBefore(position, a, true) :
14877                 this.itemTpl.append(target, a, true));
14878
14879
14880             c.positionEl.menuItemId = c.getItemId();
14881
14882
14883
14884             if (!a.isMenuItem && a.needsIcon) {
14885                 c.positionEl.addClass('x-menu-list-item-indent');
14886             }
14887             this.configureItem(c, position);
14888         }else if(c && !this.isValidParent(c, target)){
14889             if(Ext.isNumber(position)){
14890                 position = target.dom.childNodes[position];
14891             }
14892             target.dom.insertBefore(c.getActionEl().dom, position || null);
14893         }
14894     },
14895
14896     getItemArgs : function(c) {
14897         var isMenuItem = c instanceof Ext.menu.Item;
14898         return {
14899             isMenuItem: isMenuItem,
14900             needsIcon: !isMenuItem && (c.icon || c.iconCls),
14901             icon: c.icon || Ext.BLANK_IMAGE_URL,
14902             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
14903             itemId: 'x-menu-el-' + c.id,
14904             itemCls: 'x-menu-list-item '
14905         };
14906     },
14907
14908     
14909     isValidParent : function(c, target) {
14910         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
14911     },
14912
14913     onLayout : function(ct, target){
14914         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
14915         this.doAutoSize();
14916     },
14917
14918     doAutoSize : function(){
14919         var ct = this.container, w = ct.width;
14920         if(ct.floating){
14921             if(w){
14922                 ct.setWidth(w);
14923             }else if(Ext.isIE){
14924                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
14925                 var el = ct.getEl(), t = el.dom.offsetWidth; 
14926                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
14927             }
14928         }
14929     }
14930 });
14931 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
14932
14933 Ext.Viewport = Ext.extend(Ext.Container, {
14934     
14935     
14936     
14937     
14938     
14939     
14940     
14941     
14942     
14943     
14944     
14945     
14946
14947     initComponent : function() {
14948         Ext.Viewport.superclass.initComponent.call(this);
14949         document.getElementsByTagName('html')[0].className += ' x-viewport';
14950         this.el = Ext.getBody();
14951         this.el.setHeight = Ext.emptyFn;
14952         this.el.setWidth = Ext.emptyFn;
14953         this.el.setSize = Ext.emptyFn;
14954         this.el.dom.scroll = 'no';
14955         this.allowDomMove = false;
14956         this.autoWidth = true;
14957         this.autoHeight = true;
14958         Ext.EventManager.onWindowResize(this.fireResize, this);
14959         this.renderTo = this.el;
14960     },
14961
14962     fireResize : function(w, h){
14963         this.fireEvent('resize', this, w, h, w, h);
14964     }
14965 });
14966 Ext.reg('viewport', Ext.Viewport);
14967
14968 Ext.Panel = Ext.extend(Ext.Container, {
14969     
14970     
14971     
14972     
14973     
14974     
14975     
14976     
14977     
14978     
14979     
14980     
14981     
14982     
14983     
14984     
14985     
14986     
14987     
14988     
14989     
14990     
14991     
14992     
14993     
14994     
14995     
14996     
14997     
14998     
14999     
15000     
15001
15002     
15003     
15004     
15005     
15006     
15007     
15008     
15009     
15010
15011
15012     
15013     baseCls : 'x-panel',
15014     
15015     collapsedCls : 'x-panel-collapsed',
15016     
15017     maskDisabled : true,
15018     
15019     animCollapse : Ext.enableFx,
15020     
15021     headerAsText : true,
15022     
15023     buttonAlign : 'right',
15024     
15025     collapsed : false,
15026     
15027     collapseFirst : true,
15028     
15029     minButtonWidth : 75,
15030     
15031     
15032     elements : 'body',
15033     
15034     preventBodyReset : false,
15035
15036     
15037     padding: undefined,
15038
15039     
15040     resizeEvent: 'bodyresize',
15041
15042     
15043     
15044     
15045     toolTarget : 'header',
15046     collapseEl : 'bwrap',
15047     slideAnchor : 't',
15048     disabledClass : '',
15049
15050     
15051     deferHeight : true,
15052     
15053     expandDefaults: {
15054         duration : 0.25
15055     },
15056     
15057     collapseDefaults : {
15058         duration : 0.25
15059     },
15060
15061     
15062     initComponent : function(){
15063         Ext.Panel.superclass.initComponent.call(this);
15064
15065         this.addEvents(
15066             
15067             'bodyresize',
15068             
15069             'titlechange',
15070             
15071             'iconchange',
15072             
15073             'collapse',
15074             
15075             'expand',
15076             
15077             'beforecollapse',
15078             
15079             'beforeexpand',
15080             
15081             'beforeclose',
15082             
15083             'close',
15084             
15085             'activate',
15086             
15087             'deactivate'
15088         );
15089
15090         if(this.unstyled){
15091             this.baseCls = 'x-plain';
15092         }
15093
15094
15095         this.toolbars = [];
15096         
15097         if(this.tbar){
15098             this.elements += ',tbar';
15099             this.topToolbar = this.createToolbar(this.tbar);
15100             this.tbar = null;
15101
15102         }
15103         if(this.bbar){
15104             this.elements += ',bbar';
15105             this.bottomToolbar = this.createToolbar(this.bbar);
15106             this.bbar = null;
15107         }
15108
15109         if(this.header === true){
15110             this.elements += ',header';
15111             this.header = null;
15112         }else if(this.headerCfg || (this.title && this.header !== false)){
15113             this.elements += ',header';
15114         }
15115
15116         if(this.footerCfg || this.footer === true){
15117             this.elements += ',footer';
15118             this.footer = null;
15119         }
15120
15121         if(this.buttons){
15122             this.fbar = this.buttons;
15123             this.buttons = null;
15124         }
15125         if(this.fbar){
15126             this.createFbar(this.fbar);
15127         }
15128         if(this.autoLoad){
15129             this.on('render', this.doAutoLoad, this, {delay:10});
15130         }
15131     },
15132
15133     
15134     createFbar : function(fbar){
15135         var min = this.minButtonWidth;
15136         this.elements += ',footer';
15137         this.fbar = this.createToolbar(fbar, {
15138             buttonAlign: this.buttonAlign,
15139             toolbarCls: 'x-panel-fbar',
15140             enableOverflow: false,
15141             defaults: function(c){
15142                 return {
15143                     minWidth: c.minWidth || min
15144                 };
15145             }
15146         });
15147         
15148         
15149         
15150         this.fbar.items.each(function(c){
15151             c.minWidth = c.minWidth || this.minButtonWidth;
15152         }, this);
15153         this.buttons = this.fbar.items.items;
15154     },
15155
15156     
15157     createToolbar: function(tb, options){
15158         var result;
15159         
15160         if(Ext.isArray(tb)){
15161             tb = {
15162                 items: tb
15163             };
15164         }
15165         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
15166         this.toolbars.push(result);
15167         return result;
15168     },
15169
15170     
15171     createElement : function(name, pnode){
15172         if(this[name]){
15173             pnode.appendChild(this[name].dom);
15174             return;
15175         }
15176
15177         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
15178             if(this[name+'Cfg']){
15179                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
15180             }else{
15181                 var el = document.createElement('div');
15182                 el.className = this[name+'Cls'];
15183                 this[name] = Ext.get(pnode.appendChild(el));
15184             }
15185             if(this[name+'CssClass']){
15186                 this[name].addClass(this[name+'CssClass']);
15187             }
15188             if(this[name+'Style']){
15189                 this[name].applyStyles(this[name+'Style']);
15190             }
15191         }
15192     },
15193
15194     
15195     onRender : function(ct, position){
15196         Ext.Panel.superclass.onRender.call(this, ct, position);
15197         this.createClasses();
15198
15199         var el = this.el,
15200             d = el.dom,
15201             bw,
15202             ts;
15203
15204
15205         if(this.collapsible && !this.hideCollapseTool){
15206             this.tools = this.tools ? this.tools.slice(0) : [];
15207             this.tools[this.collapseFirst?'unshift':'push']({
15208                 id: 'toggle',
15209                 handler : this.toggleCollapse,
15210                 scope: this
15211             });
15212         }
15213
15214         if(this.tools){
15215             ts = this.tools;
15216             this.elements += (this.header !== false) ? ',header' : '';
15217         }
15218         this.tools = {};
15219
15220         el.addClass(this.baseCls);
15221         if(d.firstChild){ 
15222             this.header = el.down('.'+this.headerCls);
15223             this.bwrap = el.down('.'+this.bwrapCls);
15224             var cp = this.bwrap ? this.bwrap : el;
15225             this.tbar = cp.down('.'+this.tbarCls);
15226             this.body = cp.down('.'+this.bodyCls);
15227             this.bbar = cp.down('.'+this.bbarCls);
15228             this.footer = cp.down('.'+this.footerCls);
15229             this.fromMarkup = true;
15230         }
15231         if (this.preventBodyReset === true) {
15232             el.addClass('x-panel-reset');
15233         }
15234         if(this.cls){
15235             el.addClass(this.cls);
15236         }
15237
15238         if(this.buttons){
15239             this.elements += ',footer';
15240         }
15241
15242         
15243
15244         
15245         if(this.frame){
15246             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
15247
15248             this.createElement('header', d.firstChild.firstChild.firstChild);
15249             this.createElement('bwrap', d);
15250
15251             
15252             bw = this.bwrap.dom;
15253             var ml = d.childNodes[1], bl = d.childNodes[2];
15254             bw.appendChild(ml);
15255             bw.appendChild(bl);
15256
15257             var mc = bw.firstChild.firstChild.firstChild;
15258             this.createElement('tbar', mc);
15259             this.createElement('body', mc);
15260             this.createElement('bbar', mc);
15261             this.createElement('footer', bw.lastChild.firstChild.firstChild);
15262
15263             if(!this.footer){
15264                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
15265             }
15266             
15267             this.ft = Ext.get(this.bwrap.dom.lastChild);
15268             this.mc = Ext.get(mc);
15269         }else{
15270             this.createElement('header', d);
15271             this.createElement('bwrap', d);
15272
15273             
15274             bw = this.bwrap.dom;
15275             this.createElement('tbar', bw);
15276             this.createElement('body', bw);
15277             this.createElement('bbar', bw);
15278             this.createElement('footer', bw);
15279
15280             if(!this.header){
15281                 this.body.addClass(this.bodyCls + '-noheader');
15282                 if(this.tbar){
15283                     this.tbar.addClass(this.tbarCls + '-noheader');
15284                 }
15285             }
15286         }
15287
15288         if(Ext.isDefined(this.padding)){
15289             this.body.setStyle('padding', this.body.addUnits(this.padding));
15290         }
15291
15292         if(this.border === false){
15293             this.el.addClass(this.baseCls + '-noborder');
15294             this.body.addClass(this.bodyCls + '-noborder');
15295             if(this.header){
15296                 this.header.addClass(this.headerCls + '-noborder');
15297             }
15298             if(this.footer){
15299                 this.footer.addClass(this.footerCls + '-noborder');
15300             }
15301             if(this.tbar){
15302                 this.tbar.addClass(this.tbarCls + '-noborder');
15303             }
15304             if(this.bbar){
15305                 this.bbar.addClass(this.bbarCls + '-noborder');
15306             }
15307         }
15308
15309         if(this.bodyBorder === false){
15310            this.body.addClass(this.bodyCls + '-noborder');
15311         }
15312
15313         this.bwrap.enableDisplayMode('block');
15314
15315         if(this.header){
15316             this.header.unselectable();
15317
15318             
15319             if(this.headerAsText){
15320                 this.header.dom.innerHTML =
15321                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
15322
15323                 if(this.iconCls){
15324                     this.setIconClass(this.iconCls);
15325                 }
15326             }
15327         }
15328
15329         if(this.floating){
15330             this.makeFloating(this.floating);
15331         }
15332
15333         if(this.collapsible && this.titleCollapse && this.header){
15334             this.mon(this.header, 'click', this.toggleCollapse, this);
15335             this.header.setStyle('cursor', 'pointer');
15336         }
15337         if(ts){
15338             this.addTool.apply(this, ts);
15339         }
15340
15341         
15342         if(this.fbar){
15343             this.footer.addClass('x-panel-btns');
15344             this.fbar.ownerCt = this;
15345             this.fbar.render(this.footer);
15346             this.footer.createChild({cls:'x-clear'});
15347         }
15348         if(this.tbar && this.topToolbar){
15349             this.topToolbar.ownerCt = this;
15350             this.topToolbar.render(this.tbar);
15351         }
15352         if(this.bbar && this.bottomToolbar){
15353             this.bottomToolbar.ownerCt = this;
15354             this.bottomToolbar.render(this.bbar);
15355         }
15356     },
15357
15358     
15359     setIconClass : function(cls){
15360         var old = this.iconCls;
15361         this.iconCls = cls;
15362         if(this.rendered && this.header){
15363             if(this.frame){
15364                 this.header.addClass('x-panel-icon');
15365                 this.header.replaceClass(old, this.iconCls);
15366             }else{
15367                 var hd = this.header,
15368                     img = hd.child('img.x-panel-inline-icon');
15369                 if(img){
15370                     Ext.fly(img).replaceClass(old, this.iconCls);
15371                 }else{
15372                     var hdspan = hd.child('span.' + this.headerTextCls);
15373                     if (hdspan) {
15374                         Ext.DomHelper.insertBefore(hdspan.dom, {
15375                             tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
15376                         });
15377                     }
15378                  }
15379             }
15380         }
15381         this.fireEvent('iconchange', this, cls, old);
15382     },
15383
15384     
15385     makeFloating : function(cfg){
15386         this.floating = true;
15387         this.el = new Ext.Layer(Ext.apply({}, cfg, {
15388             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
15389             shadowOffset: this.shadowOffset,
15390             constrain:false,
15391             shim: this.shim === false ? false : undefined
15392         }), this.el);
15393     },
15394
15395     
15396     getTopToolbar : function(){
15397         return this.topToolbar;
15398     },
15399
15400     
15401     getBottomToolbar : function(){
15402         return this.bottomToolbar;
15403     },
15404
15405     
15406     getFooterToolbar : function() {
15407         return this.fbar;
15408     },
15409
15410     
15411     addButton : function(config, handler, scope){
15412         if(!this.fbar){
15413             this.createFbar([]);
15414         }
15415         if(handler){
15416             if(Ext.isString(config)){
15417                 config = {text: config};
15418             }
15419             config = Ext.apply({
15420                 handler: handler,
15421                 scope: scope
15422             }, config);
15423         }
15424         return this.fbar.add(config);
15425     },
15426
15427     
15428     addTool : function(){
15429         if(!this.rendered){
15430             if(!this.tools){
15431                 this.tools = [];
15432             }
15433             Ext.each(arguments, function(arg){
15434                 this.tools.push(arg);
15435             }, this);
15436             return;
15437         }
15438          
15439         if(!this[this.toolTarget]){
15440             return;
15441         }
15442         if(!this.toolTemplate){
15443             
15444             var tt = new Ext.Template(
15445                  '<div class="x-tool x-tool-{id}">&#160;</div>'
15446             );
15447             tt.disableFormats = true;
15448             tt.compile();
15449             Ext.Panel.prototype.toolTemplate = tt;
15450         }
15451         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
15452             var tc = a[i];
15453             if(!this.tools[tc.id]){
15454                 var overCls = 'x-tool-'+tc.id+'-over';
15455                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
15456                 this.tools[tc.id] = t;
15457                 t.enableDisplayMode('block');
15458                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
15459                 if(tc.on){
15460                     this.mon(t, tc.on);
15461                 }
15462                 if(tc.hidden){
15463                     t.hide();
15464                 }
15465                 if(tc.qtip){
15466                     if(Ext.isObject(tc.qtip)){
15467                         Ext.QuickTips.register(Ext.apply({
15468                               target: t.id
15469                         }, tc.qtip));
15470                     } else {
15471                         t.dom.qtip = tc.qtip;
15472                     }
15473                 }
15474                 t.addClassOnOver(overCls);
15475             }
15476         }
15477     },
15478
15479     onLayout : function(shallow, force){
15480         Ext.Panel.superclass.onLayout.apply(this, arguments);
15481         if(this.hasLayout && this.toolbars.length > 0){
15482             Ext.each(this.toolbars, function(tb){
15483                 tb.doLayout(undefined, force);
15484             });
15485             this.syncHeight();
15486         }
15487     },
15488
15489     syncHeight : function(){
15490         var h = this.toolbarHeight,
15491                 bd = this.body,
15492                 lsh = this.lastSize.height,
15493                 sz;
15494
15495         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
15496             return;
15497         }
15498
15499
15500         if(h != this.getToolbarHeight()){
15501             h = Math.max(0, lsh - this.getFrameHeight());
15502             bd.setHeight(h);
15503             sz = bd.getSize();
15504             this.toolbarHeight = this.getToolbarHeight();
15505             this.onBodyResize(sz.width, sz.height);
15506         }
15507     },
15508
15509     
15510     onShow : function(){
15511         if(this.floating){
15512             return this.el.show();
15513         }
15514         Ext.Panel.superclass.onShow.call(this);
15515     },
15516
15517     
15518     onHide : function(){
15519         if(this.floating){
15520             return this.el.hide();
15521         }
15522         Ext.Panel.superclass.onHide.call(this);
15523     },
15524
15525     
15526     createToolHandler : function(t, tc, overCls, panel){
15527         return function(e){
15528             t.removeClass(overCls);
15529             if(tc.stopEvent !== false){
15530                 e.stopEvent();
15531             }
15532             if(tc.handler){
15533                 tc.handler.call(tc.scope || t, e, t, panel, tc);
15534             }
15535         };
15536     },
15537
15538     
15539     afterRender : function(){
15540         if(this.floating && !this.hidden){
15541             this.el.show();
15542         }
15543         if(this.title){
15544             this.setTitle(this.title);
15545         }
15546         Ext.Panel.superclass.afterRender.call(this); 
15547         if (this.collapsed) {
15548             this.collapsed = false;
15549             this.collapse(false);
15550         }
15551         this.initEvents();
15552     },
15553
15554     
15555     getKeyMap : function(){
15556         if(!this.keyMap){
15557             this.keyMap = new Ext.KeyMap(this.el, this.keys);
15558         }
15559         return this.keyMap;
15560     },
15561
15562     
15563     initEvents : function(){
15564         if(this.keys){
15565             this.getKeyMap();
15566         }
15567         if(this.draggable){
15568             this.initDraggable();
15569         }
15570         if(this.toolbars.length > 0){
15571             Ext.each(this.toolbars, function(tb){
15572                 tb.doLayout();
15573                 tb.on({
15574                     scope: this,
15575                     afterlayout: this.syncHeight,
15576                     remove: this.syncHeight
15577                 });
15578             }, this);
15579             this.syncHeight();
15580         }
15581
15582     },
15583
15584     
15585     initDraggable : function(){
15586         
15587         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
15588     },
15589
15590     
15591     beforeEffect : function(anim){
15592         if(this.floating){
15593             this.el.beforeAction();
15594         }
15595         if(anim !== false){
15596             this.el.addClass('x-panel-animated');
15597         }
15598     },
15599
15600     
15601     afterEffect : function(anim){
15602         this.syncShadow();
15603         this.el.removeClass('x-panel-animated');
15604     },
15605
15606     
15607     createEffect : function(a, cb, scope){
15608         var o = {
15609             scope:scope,
15610             block:true
15611         };
15612         if(a === true){
15613             o.callback = cb;
15614             return o;
15615         }else if(!a.callback){
15616             o.callback = cb;
15617         }else { 
15618             o.callback = function(){
15619                 cb.call(scope);
15620                 Ext.callback(a.callback, a.scope);
15621             };
15622         }
15623         return Ext.applyIf(o, a);
15624     },
15625
15626     
15627     collapse : function(animate){
15628         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
15629             return;
15630         }
15631         var doAnim = animate === true || (animate !== false && this.animCollapse);
15632         this.beforeEffect(doAnim);
15633         this.onCollapse(doAnim, animate);
15634         return this;
15635     },
15636
15637     
15638     onCollapse : function(doAnim, animArg){
15639         if(doAnim){
15640             this[this.collapseEl].slideOut(this.slideAnchor,
15641                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
15642                         this.collapseDefaults));
15643         }else{
15644             this[this.collapseEl].hide(this.hideMode);
15645             this.afterCollapse(false);
15646         }
15647     },
15648
15649     
15650     afterCollapse : function(anim){
15651         this.collapsed = true;
15652         this.el.addClass(this.collapsedCls);
15653         if(anim !== false){
15654             this[this.collapseEl].hide(this.hideMode);
15655         }
15656         this.afterEffect(anim);
15657
15658         
15659         this.cascade(function(c) {
15660             if (c.lastSize) {
15661                 c.lastSize = { width: undefined, height: undefined };
15662             }
15663         });
15664         this.fireEvent('collapse', this);
15665     },
15666
15667     
15668     expand : function(animate){
15669         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
15670             return;
15671         }
15672         var doAnim = animate === true || (animate !== false && this.animCollapse);
15673         this.el.removeClass(this.collapsedCls);
15674         this.beforeEffect(doAnim);
15675         this.onExpand(doAnim, animate);
15676         return this;
15677     },
15678
15679     
15680     onExpand : function(doAnim, animArg){
15681         if(doAnim){
15682             this[this.collapseEl].slideIn(this.slideAnchor,
15683                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
15684                         this.expandDefaults));
15685         }else{
15686             this[this.collapseEl].show(this.hideMode);
15687             this.afterExpand(false);
15688         }
15689     },
15690
15691     
15692     afterExpand : function(anim){
15693         this.collapsed = false;
15694         if(anim !== false){
15695             this[this.collapseEl].show(this.hideMode);
15696         }
15697         this.afterEffect(anim);
15698         if (this.deferLayout) {
15699             delete this.deferLayout;
15700             this.doLayout(true);
15701         }
15702         this.fireEvent('expand', this);
15703     },
15704
15705     
15706     toggleCollapse : function(animate){
15707         this[this.collapsed ? 'expand' : 'collapse'](animate);
15708         return this;
15709     },
15710
15711     
15712     onDisable : function(){
15713         if(this.rendered && this.maskDisabled){
15714             this.el.mask();
15715         }
15716         Ext.Panel.superclass.onDisable.call(this);
15717     },
15718
15719     
15720     onEnable : function(){
15721         if(this.rendered && this.maskDisabled){
15722             this.el.unmask();
15723         }
15724         Ext.Panel.superclass.onEnable.call(this);
15725     },
15726
15727     
15728     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15729         var w = adjWidth,
15730             h = adjHeight;
15731
15732         if(Ext.isDefined(w) || Ext.isDefined(h)){
15733             if(!this.collapsed){
15734                 
15735                 
15736                 
15737
15738                 if(Ext.isNumber(w)){
15739                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
15740                 } else if (w == 'auto') {
15741                     w = this.body.setWidth('auto').dom.offsetWidth;
15742                 } else {
15743                     w = this.body.dom.offsetWidth;
15744                 }
15745
15746                 if(this.tbar){
15747                     this.tbar.setWidth(w);
15748                     if(this.topToolbar){
15749                         this.topToolbar.setSize(w);
15750                     }
15751                 }
15752                 if(this.bbar){
15753                     this.bbar.setWidth(w);
15754                     if(this.bottomToolbar){
15755                         this.bottomToolbar.setSize(w);
15756                         
15757                         if (Ext.isIE) {
15758                             this.bbar.setStyle('position', 'static');
15759                             this.bbar.setStyle('position', '');
15760                         }
15761                     }
15762                 }
15763                 if(this.footer){
15764                     this.footer.setWidth(w);
15765                     if(this.fbar){
15766                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
15767                     }
15768                 }
15769
15770                 
15771                 if(Ext.isNumber(h)){
15772                     h = Math.max(0, h - this.getFrameHeight());
15773                     
15774                     this.body.setHeight(h);
15775                 }else if(h == 'auto'){
15776                     this.body.setHeight(h);
15777                 }
15778
15779                 if(this.disabled && this.el._mask){
15780                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
15781                 }
15782             }else{
15783                 
15784                 this.queuedBodySize = {width: w, height: h};
15785                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
15786                     this.queuedExpand = true;
15787                     this.on('expand', function(){
15788                         delete this.queuedExpand;
15789                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
15790                     }, this, {single:true});
15791                 }
15792             }
15793             this.onBodyResize(w, h);
15794         }
15795         this.syncShadow();
15796         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
15797
15798     },
15799
15800     
15801     onBodyResize: function(w, h){
15802         this.fireEvent('bodyresize', this, w, h);
15803     },
15804
15805     
15806     getToolbarHeight: function(){
15807         var h = 0;
15808         if(this.rendered){
15809             Ext.each(this.toolbars, function(tb){
15810                 h += tb.getHeight();
15811             }, this);
15812         }
15813         return h;
15814     },
15815
15816     
15817     adjustBodyHeight : function(h){
15818         return h;
15819     },
15820
15821     
15822     adjustBodyWidth : function(w){
15823         return w;
15824     },
15825
15826     
15827     onPosition : function(){
15828         this.syncShadow();
15829     },
15830
15831     
15832     getFrameWidth : function(){
15833         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
15834
15835         if(this.frame){
15836             var l = this.bwrap.dom.firstChild;
15837             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
15838             w += this.mc.getFrameWidth('lr');
15839         }
15840         return w;
15841     },
15842
15843     
15844     getFrameHeight : function() {
15845         var h = Math.max(0, this.getHeight() - this.body.getHeight());
15846
15847         if (isNaN(h)) {
15848             h = 0;
15849         }
15850         return h;
15851
15852         
15853     },
15854
15855     
15856     getInnerWidth : function(){
15857         return this.getSize().width - this.getFrameWidth();
15858     },
15859
15860     
15861     getInnerHeight : function(){
15862         return this.body.getHeight();
15863         
15864     },
15865
15866     
15867     syncShadow : function(){
15868         if(this.floating){
15869             this.el.sync(true);
15870         }
15871     },
15872
15873     
15874     getLayoutTarget : function(){
15875         return this.body;
15876     },
15877
15878     
15879     getContentTarget : function(){
15880         return this.body;
15881     },
15882
15883     
15884     setTitle : function(title, iconCls){
15885         this.title = title;
15886         if(this.header && this.headerAsText){
15887             this.header.child('span').update(title);
15888         }
15889         if(iconCls){
15890             this.setIconClass(iconCls);
15891         }
15892         this.fireEvent('titlechange', this, title);
15893         return this;
15894     },
15895
15896     
15897     getUpdater : function(){
15898         return this.body.getUpdater();
15899     },
15900
15901      
15902     load : function(){
15903         var um = this.body.getUpdater();
15904         um.update.apply(um, arguments);
15905         return this;
15906     },
15907
15908     
15909     beforeDestroy : function(){
15910         Ext.Panel.superclass.beforeDestroy.call(this);
15911         if(this.header){
15912             this.header.removeAllListeners();
15913         }
15914         if(this.tools){
15915             for(var k in this.tools){
15916                 Ext.destroy(this.tools[k]);
15917             }
15918         }
15919         if(this.toolbars.length > 0){
15920             Ext.each(this.toolbars, function(tb){
15921                 tb.un('afterlayout', this.syncHeight, this);
15922                 tb.un('remove', this.syncHeight, this);
15923             }, this);
15924         }
15925         if(Ext.isArray(this.buttons)){
15926             while(this.buttons.length) {
15927                 Ext.destroy(this.buttons[0]);
15928             }
15929         }
15930         if(this.rendered){
15931             Ext.destroy(
15932                 this.ft,
15933                 this.header,
15934                 this.footer,
15935                 this.tbar,
15936                 this.bbar,
15937                 this.body,
15938                 this.mc,
15939                 this.bwrap,
15940                 this.dd
15941             );
15942             if (this.fbar) {
15943                 Ext.destroy(
15944                     this.fbar,
15945                     this.fbar.el
15946                 );
15947             }
15948         }
15949         Ext.destroy(this.toolbars);
15950     },
15951
15952     
15953     createClasses : function(){
15954         this.headerCls = this.baseCls + '-header';
15955         this.headerTextCls = this.baseCls + '-header-text';
15956         this.bwrapCls = this.baseCls + '-bwrap';
15957         this.tbarCls = this.baseCls + '-tbar';
15958         this.bodyCls = this.baseCls + '-body';
15959         this.bbarCls = this.baseCls + '-bbar';
15960         this.footerCls = this.baseCls + '-footer';
15961     },
15962
15963     
15964     createGhost : function(cls, useShim, appendTo){
15965         var el = document.createElement('div');
15966         el.className = 'x-panel-ghost ' + (cls ? cls : '');
15967         if(this.header){
15968             el.appendChild(this.el.dom.firstChild.cloneNode(true));
15969         }
15970         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
15971         el.style.width = this.el.dom.offsetWidth + 'px';;
15972         if(!appendTo){
15973             this.container.dom.appendChild(el);
15974         }else{
15975             Ext.getDom(appendTo).appendChild(el);
15976         }
15977         if(useShim !== false && this.el.useShim !== false){
15978             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
15979             layer.show();
15980             return layer;
15981         }else{
15982             return new Ext.Element(el);
15983         }
15984     },
15985
15986     
15987     doAutoLoad : function(){
15988         var u = this.body.getUpdater();
15989         if(this.renderer){
15990             u.setRenderer(this.renderer);
15991         }
15992         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
15993     },
15994
15995     
15996     getTool : function(id) {
15997         return this.tools[id];
15998     }
15999
16000
16001 });
16002 Ext.reg('panel', Ext.Panel);
16003
16004 Ext.Editor = function(field, config){
16005     if(field.field){
16006         this.field = Ext.create(field.field, 'textfield');
16007         config = Ext.apply({}, field); 
16008         delete config.field;
16009     }else{
16010         this.field = field;
16011     }
16012     Ext.Editor.superclass.constructor.call(this, config);
16013 };
16014
16015 Ext.extend(Ext.Editor, Ext.Component, {
16016     
16017     
16018     allowBlur: true,
16019     
16020     
16021     
16022     
16023     
16024     value : "",
16025     
16026     alignment: "c-c?",
16027     
16028     offsets: [0, 0],
16029     
16030     shadow : "frame",
16031     
16032     constrain : false,
16033     
16034     swallowKeys : true,
16035     
16036     completeOnEnter : true,
16037     
16038     cancelOnEsc : true,
16039     
16040     updateEl : false,
16041
16042     initComponent : function(){
16043         Ext.Editor.superclass.initComponent.call(this);
16044         this.addEvents(
16045             
16046             "beforestartedit",
16047             
16048             "startedit",
16049             
16050             "beforecomplete",
16051             
16052             "complete",
16053             
16054             "canceledit",
16055             
16056             "specialkey"
16057         );
16058     },
16059
16060     
16061     onRender : function(ct, position){
16062         this.el = new Ext.Layer({
16063             shadow: this.shadow,
16064             cls: "x-editor",
16065             parentEl : ct,
16066             shim : this.shim,
16067             shadowOffset: this.shadowOffset || 4,
16068             id: this.id,
16069             constrain: this.constrain
16070         });
16071         if(this.zIndex){
16072             this.el.setZIndex(this.zIndex);
16073         }
16074         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
16075         if(this.field.msgTarget != 'title'){
16076             this.field.msgTarget = 'qtip';
16077         }
16078         this.field.inEditor = true;
16079         this.mon(this.field, {
16080             scope: this,
16081             blur: this.onBlur,
16082             specialkey: this.onSpecialKey
16083         });
16084         if(this.field.grow){
16085             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
16086         }
16087         this.field.render(this.el).show();
16088         this.field.getEl().dom.name = '';
16089         if(this.swallowKeys){
16090             this.field.el.swallowEvent([
16091                 'keypress', 
16092                 'keydown'   
16093             ]);
16094         }
16095     },
16096
16097     
16098     onSpecialKey : function(field, e){
16099         var key = e.getKey(),
16100             complete = this.completeOnEnter && key == e.ENTER,
16101             cancel = this.cancelOnEsc && key == e.ESC;
16102         if(complete || cancel){
16103             e.stopEvent();
16104             if(complete){
16105                 this.completeEdit();
16106             }else{
16107                 this.cancelEdit();
16108             }
16109             if(field.triggerBlur){
16110                 field.triggerBlur();
16111             }
16112         }
16113         this.fireEvent('specialkey', field, e);
16114     },
16115
16116     
16117     startEdit : function(el, value){
16118         if(this.editing){
16119             this.completeEdit();
16120         }
16121         this.boundEl = Ext.get(el);
16122         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
16123         if(!this.rendered){
16124             this.render(this.parentEl || document.body);
16125         }
16126         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
16127             this.startValue = v;
16128             this.field.reset();
16129             this.field.setValue(v);
16130             this.realign(true);
16131             this.editing = true;
16132             this.show();
16133         }
16134     },
16135
16136     
16137     doAutoSize : function(){
16138         if(this.autoSize){
16139             var sz = this.boundEl.getSize(),
16140                 fs = this.field.getSize();
16141
16142             switch(this.autoSize){
16143                 case "width":
16144                     this.setSize(sz.width, fs.height);
16145                     break;
16146                 case "height":
16147                     this.setSize(fs.width, sz.height);
16148                     break;
16149                 case "none":
16150                     this.setSize(fs.width, fs.height);
16151                     break;
16152                 default:
16153                     this.setSize(sz.width, sz.height);
16154             }
16155         }
16156     },
16157
16158     
16159     setSize : function(w, h){
16160         delete this.field.lastSize;
16161         this.field.setSize(w, h);
16162         if(this.el){
16163             
16164             if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
16165                 
16166                 this.el.setSize(w, h);
16167             }
16168             this.el.sync();
16169         }
16170     },
16171
16172     
16173     realign : function(autoSize){
16174         if(autoSize === true){
16175             this.doAutoSize();
16176         }
16177         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
16178     },
16179
16180     
16181     completeEdit : function(remainVisible){
16182         if(!this.editing){
16183             return;
16184         }
16185         
16186         if (this.field.assertValue) {
16187             this.field.assertValue();
16188         }
16189         var v = this.getValue();
16190         if(!this.field.isValid()){
16191             if(this.revertInvalid !== false){
16192                 this.cancelEdit(remainVisible);
16193             }
16194             return;
16195         }
16196         if(String(v) === String(this.startValue) && this.ignoreNoChange){
16197             this.hideEdit(remainVisible);
16198             return;
16199         }
16200         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
16201             v = this.getValue();
16202             if(this.updateEl && this.boundEl){
16203                 this.boundEl.update(v);
16204             }
16205             this.hideEdit(remainVisible);
16206             this.fireEvent("complete", this, v, this.startValue);
16207         }
16208     },
16209
16210     
16211     onShow : function(){
16212         this.el.show();
16213         if(this.hideEl !== false){
16214             this.boundEl.hide();
16215         }
16216         this.field.show().focus(false, true);
16217         this.fireEvent("startedit", this.boundEl, this.startValue);
16218     },
16219
16220     
16221     cancelEdit : function(remainVisible){
16222         if(this.editing){
16223             var v = this.getValue();
16224             this.setValue(this.startValue);
16225             this.hideEdit(remainVisible);
16226             this.fireEvent("canceledit", this, v, this.startValue);
16227         }
16228     },
16229
16230     
16231     hideEdit: function(remainVisible){
16232         if(remainVisible !== true){
16233             this.editing = false;
16234             this.hide();
16235         }
16236     },
16237
16238     
16239     onBlur : function(){
16240         
16241         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
16242             this.completeEdit();
16243         }
16244     },
16245
16246     
16247     onHide : function(){
16248         if(this.editing){
16249             this.completeEdit();
16250             return;
16251         }
16252         this.field.blur();
16253         if(this.field.collapse){
16254             this.field.collapse();
16255         }
16256         this.el.hide();
16257         if(this.hideEl !== false){
16258             this.boundEl.show();
16259         }
16260     },
16261
16262     
16263     setValue : function(v){
16264         this.field.setValue(v);
16265     },
16266
16267     
16268     getValue : function(){
16269         return this.field.getValue();
16270     },
16271
16272     beforeDestroy : function(){
16273         Ext.destroyMembers(this, 'field');
16274
16275         delete this.parentEl;
16276         delete this.boundEl;
16277     }
16278 });
16279 Ext.reg('editor', Ext.Editor);
16280
16281 Ext.ColorPalette = Ext.extend(Ext.Component, {
16282         
16283     
16284     itemCls : 'x-color-palette',
16285     
16286     value : null,
16287     
16288     clickEvent :'click',
16289     
16290     ctype : 'Ext.ColorPalette',
16291
16292     
16293     allowReselect : false,
16294
16295     
16296     colors : [
16297         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
16298         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
16299         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
16300         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
16301         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
16302     ],
16303
16304     
16305     
16306     
16307     
16308     initComponent : function(){
16309         Ext.ColorPalette.superclass.initComponent.call(this);
16310         this.addEvents(
16311             
16312             'select'
16313         );
16314
16315         if(this.handler){
16316             this.on('select', this.handler, this.scope, true);
16317         }    
16318     },
16319
16320     
16321     onRender : function(container, position){
16322         this.autoEl = {
16323             tag: 'div',
16324             cls: this.itemCls
16325         };
16326         Ext.ColorPalette.superclass.onRender.call(this, container, position);
16327         var t = this.tpl || new Ext.XTemplate(
16328             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
16329         );
16330         t.overwrite(this.el, this.colors);
16331         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
16332         if(this.clickEvent != 'click'){
16333                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
16334         }
16335     },
16336
16337     
16338     afterRender : function(){
16339         Ext.ColorPalette.superclass.afterRender.call(this);
16340         if(this.value){
16341             var s = this.value;
16342             this.value = null;
16343             this.select(s, true);
16344         }
16345     },
16346
16347     
16348     handleClick : function(e, t){
16349         e.preventDefault();
16350         if(!this.disabled){
16351             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
16352             this.select(c.toUpperCase());
16353         }
16354     },
16355
16356     
16357     select : function(color, suppressEvent){
16358         color = color.replace('#', '');
16359         if(color != this.value || this.allowReselect){
16360             var el = this.el;
16361             if(this.value){
16362                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
16363             }
16364             el.child('a.color-'+color).addClass('x-color-palette-sel');
16365             this.value = color;
16366             if(suppressEvent !== true){
16367                 this.fireEvent('select', this, color);
16368             }
16369         }
16370     }
16371
16372     
16373 });
16374 Ext.reg('colorpalette', Ext.ColorPalette);
16375 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
16376     
16377     todayText : 'Today',
16378     
16379     okText : '&#160;OK&#160;',
16380     
16381     cancelText : 'Cancel',
16382     
16383     
16384     
16385     todayTip : '{0} (Spacebar)',
16386     
16387     minText : 'This date is before the minimum date',
16388     
16389     maxText : 'This date is after the maximum date',
16390     
16391     format : 'm/d/y',
16392     
16393     disabledDaysText : 'Disabled',
16394     
16395     disabledDatesText : 'Disabled',
16396     
16397     monthNames : Date.monthNames,
16398     
16399     dayNames : Date.dayNames,
16400     
16401     nextText : 'Next Month (Control+Right)',
16402     
16403     prevText : 'Previous Month (Control+Left)',
16404     
16405     monthYearText : 'Choose a month (Control+Up/Down to move years)',
16406     
16407     startDay : 0,
16408     
16409     showToday : true,
16410     
16411     
16412     
16413     
16414     
16415
16416     
16417     
16418     focusOnSelect: true,
16419
16420     
16421     
16422     initHour: 12, 
16423
16424     
16425     initComponent : function(){
16426         Ext.DatePicker.superclass.initComponent.call(this);
16427
16428         this.value = this.value ?
16429                  this.value.clearTime(true) : new Date().clearTime();
16430
16431         this.addEvents(
16432             
16433             'select'
16434         );
16435
16436         if(this.handler){
16437             this.on('select', this.handler,  this.scope || this);
16438         }
16439
16440         this.initDisabledDays();
16441     },
16442
16443     
16444     initDisabledDays : function(){
16445         if(!this.disabledDatesRE && this.disabledDates){
16446             var dd = this.disabledDates,
16447                 len = dd.length - 1,
16448                 re = '(?:';
16449
16450             Ext.each(dd, function(d, i){
16451                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
16452                 if(i != len){
16453                     re += '|';
16454                 }
16455             }, this);
16456             this.disabledDatesRE = new RegExp(re + ')');
16457         }
16458     },
16459
16460     
16461     setDisabledDates : function(dd){
16462         if(Ext.isArray(dd)){
16463             this.disabledDates = dd;
16464             this.disabledDatesRE = null;
16465         }else{
16466             this.disabledDatesRE = dd;
16467         }
16468         this.initDisabledDays();
16469         this.update(this.value, true);
16470     },
16471
16472     
16473     setDisabledDays : function(dd){
16474         this.disabledDays = dd;
16475         this.update(this.value, true);
16476     },
16477
16478     
16479     setMinDate : function(dt){
16480         this.minDate = dt;
16481         this.update(this.value, true);
16482     },
16483
16484     
16485     setMaxDate : function(dt){
16486         this.maxDate = dt;
16487         this.update(this.value, true);
16488     },
16489
16490     
16491     setValue : function(value){
16492         this.value = value.clearTime(true);
16493         this.update(this.value);
16494     },
16495
16496     
16497     getValue : function(){
16498         return this.value;
16499     },
16500
16501     
16502     focus : function(){
16503         this.update(this.activeDate);
16504     },
16505
16506     
16507     onEnable: function(initial){
16508         Ext.DatePicker.superclass.onEnable.call(this);
16509         this.doDisabled(false);
16510         this.update(initial ? this.value : this.activeDate);
16511         if(Ext.isIE){
16512             this.el.repaint();
16513         }
16514
16515     },
16516
16517     
16518     onDisable : function(){
16519         Ext.DatePicker.superclass.onDisable.call(this);
16520         this.doDisabled(true);
16521         if(Ext.isIE && !Ext.isIE8){
16522             
16523              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
16524                  Ext.fly(el).repaint();
16525              });
16526         }
16527     },
16528
16529     
16530     doDisabled : function(disabled){
16531         this.keyNav.setDisabled(disabled);
16532         this.prevRepeater.setDisabled(disabled);
16533         this.nextRepeater.setDisabled(disabled);
16534         if(this.showToday){
16535             this.todayKeyListener.setDisabled(disabled);
16536             this.todayBtn.setDisabled(disabled);
16537         }
16538     },
16539
16540     
16541     onRender : function(container, position){
16542         var m = [
16543              '<table cellspacing="0">',
16544                 '<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>',
16545                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
16546                 dn = this.dayNames,
16547                 i;
16548         for(i = 0; i < 7; i++){
16549             var d = this.startDay+i;
16550             if(d > 6){
16551                 d = d-7;
16552             }
16553             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
16554         }
16555         m[m.length] = '</tr></thead><tbody><tr>';
16556         for(i = 0; i < 42; i++) {
16557             if(i % 7 === 0 && i !== 0){
16558                 m[m.length] = '</tr><tr>';
16559             }
16560             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
16561         }
16562         m.push('</tr></tbody></table></td></tr>',
16563                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
16564                 '</table><div class="x-date-mp"></div>');
16565
16566         var el = document.createElement('div');
16567         el.className = 'x-date-picker';
16568         el.innerHTML = m.join('');
16569
16570         container.dom.insertBefore(el, position);
16571
16572         this.el = Ext.get(el);
16573         this.eventEl = Ext.get(el.firstChild);
16574
16575         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
16576             handler: this.showPrevMonth,
16577             scope: this,
16578             preventDefault:true,
16579             stopDefault:true
16580         });
16581
16582         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
16583             handler: this.showNextMonth,
16584             scope: this,
16585             preventDefault:true,
16586             stopDefault:true
16587         });
16588
16589         this.monthPicker = this.el.down('div.x-date-mp');
16590         this.monthPicker.enableDisplayMode('block');
16591
16592         this.keyNav = new Ext.KeyNav(this.eventEl, {
16593             'left' : function(e){
16594                 if(e.ctrlKey){
16595                     this.showPrevMonth();
16596                 }else{
16597                     this.update(this.activeDate.add('d', -1));
16598                 }
16599             },
16600
16601             'right' : function(e){
16602                 if(e.ctrlKey){
16603                     this.showNextMonth();
16604                 }else{
16605                     this.update(this.activeDate.add('d', 1));
16606                 }
16607             },
16608
16609             'up' : function(e){
16610                 if(e.ctrlKey){
16611                     this.showNextYear();
16612                 }else{
16613                     this.update(this.activeDate.add('d', -7));
16614                 }
16615             },
16616
16617             'down' : function(e){
16618                 if(e.ctrlKey){
16619                     this.showPrevYear();
16620                 }else{
16621                     this.update(this.activeDate.add('d', 7));
16622                 }
16623             },
16624
16625             'pageUp' : function(e){
16626                 this.showNextMonth();
16627             },
16628
16629             'pageDown' : function(e){
16630                 this.showPrevMonth();
16631             },
16632
16633             'enter' : function(e){
16634                 e.stopPropagation();
16635                 return true;
16636             },
16637
16638             scope : this
16639         });
16640
16641         this.el.unselectable();
16642
16643         this.cells = this.el.select('table.x-date-inner tbody td');
16644         this.textNodes = this.el.query('table.x-date-inner tbody span');
16645
16646         this.mbtn = new Ext.Button({
16647             text: '&#160;',
16648             tooltip: this.monthYearText,
16649             renderTo: this.el.child('td.x-date-middle', true)
16650         });
16651         this.mbtn.el.child('em').addClass('x-btn-arrow');
16652
16653         if(this.showToday){
16654             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
16655             var today = (new Date()).dateFormat(this.format);
16656             this.todayBtn = new Ext.Button({
16657                 renderTo: this.el.child('td.x-date-bottom', true),
16658                 text: String.format(this.todayText, today),
16659                 tooltip: String.format(this.todayTip, today),
16660                 handler: this.selectToday,
16661                 scope: this
16662             });
16663         }
16664         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
16665         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
16666         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
16667         this.onEnable(true);
16668     },
16669
16670     
16671     createMonthPicker : function(){
16672         if(!this.monthPicker.dom.firstChild){
16673             var buf = ['<table border="0" cellspacing="0">'];
16674             for(var i = 0; i < 6; i++){
16675                 buf.push(
16676                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
16677                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
16678                     i === 0 ?
16679                     '<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>' :
16680                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
16681                 );
16682             }
16683             buf.push(
16684                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
16685                     this.okText,
16686                     '</button><button type="button" class="x-date-mp-cancel">',
16687                     this.cancelText,
16688                     '</button></td></tr>',
16689                 '</table>'
16690             );
16691             this.monthPicker.update(buf.join(''));
16692
16693             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
16694             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
16695
16696             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
16697             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
16698
16699             this.mpMonths.each(function(m, a, i){
16700                 i += 1;
16701                 if((i%2) === 0){
16702                     m.dom.xmonth = 5 + Math.round(i * 0.5);
16703                 }else{
16704                     m.dom.xmonth = Math.round((i-1) * 0.5);
16705                 }
16706             });
16707         }
16708     },
16709
16710     
16711     showMonthPicker : function(){
16712         if(!this.disabled){
16713             this.createMonthPicker();
16714             var size = this.el.getSize();
16715             this.monthPicker.setSize(size);
16716             this.monthPicker.child('table').setSize(size);
16717
16718             this.mpSelMonth = (this.activeDate || this.value).getMonth();
16719             this.updateMPMonth(this.mpSelMonth);
16720             this.mpSelYear = (this.activeDate || this.value).getFullYear();
16721             this.updateMPYear(this.mpSelYear);
16722
16723             this.monthPicker.slideIn('t', {duration:0.2});
16724         }
16725     },
16726
16727     
16728     updateMPYear : function(y){
16729         this.mpyear = y;
16730         var ys = this.mpYears.elements;
16731         for(var i = 1; i <= 10; i++){
16732             var td = ys[i-1], y2;
16733             if((i%2) === 0){
16734                 y2 = y + Math.round(i * 0.5);
16735                 td.firstChild.innerHTML = y2;
16736                 td.xyear = y2;
16737             }else{
16738                 y2 = y - (5-Math.round(i * 0.5));
16739                 td.firstChild.innerHTML = y2;
16740                 td.xyear = y2;
16741             }
16742             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
16743         }
16744     },
16745
16746     
16747     updateMPMonth : function(sm){
16748         this.mpMonths.each(function(m, a, i){
16749             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
16750         });
16751     },
16752
16753     
16754     selectMPMonth : function(m){
16755
16756     },
16757
16758     
16759     onMonthClick : function(e, t){
16760         e.stopEvent();
16761         var el = new Ext.Element(t), pn;
16762         if(el.is('button.x-date-mp-cancel')){
16763             this.hideMonthPicker();
16764         }
16765         else if(el.is('button.x-date-mp-ok')){
16766             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
16767             if(d.getMonth() != this.mpSelMonth){
16768                 
16769                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
16770             }
16771             this.update(d);
16772             this.hideMonthPicker();
16773         }
16774         else if((pn = el.up('td.x-date-mp-month', 2))){
16775             this.mpMonths.removeClass('x-date-mp-sel');
16776             pn.addClass('x-date-mp-sel');
16777             this.mpSelMonth = pn.dom.xmonth;
16778         }
16779         else if((pn = el.up('td.x-date-mp-year', 2))){
16780             this.mpYears.removeClass('x-date-mp-sel');
16781             pn.addClass('x-date-mp-sel');
16782             this.mpSelYear = pn.dom.xyear;
16783         }
16784         else if(el.is('a.x-date-mp-prev')){
16785             this.updateMPYear(this.mpyear-10);
16786         }
16787         else if(el.is('a.x-date-mp-next')){
16788             this.updateMPYear(this.mpyear+10);
16789         }
16790     },
16791
16792     
16793     onMonthDblClick : function(e, t){
16794         e.stopEvent();
16795         var el = new Ext.Element(t), pn;
16796         if((pn = el.up('td.x-date-mp-month', 2))){
16797             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
16798             this.hideMonthPicker();
16799         }
16800         else if((pn = el.up('td.x-date-mp-year', 2))){
16801             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
16802             this.hideMonthPicker();
16803         }
16804     },
16805
16806     
16807     hideMonthPicker : function(disableAnim){
16808         if(this.monthPicker){
16809             if(disableAnim === true){
16810                 this.monthPicker.hide();
16811             }else{
16812                 this.monthPicker.slideOut('t', {duration:0.2});
16813             }
16814         }
16815     },
16816
16817     
16818     showPrevMonth : function(e){
16819         this.update(this.activeDate.add('mo', -1));
16820     },
16821
16822     
16823     showNextMonth : function(e){
16824         this.update(this.activeDate.add('mo', 1));
16825     },
16826
16827     
16828     showPrevYear : function(){
16829         this.update(this.activeDate.add('y', -1));
16830     },
16831
16832     
16833     showNextYear : function(){
16834         this.update(this.activeDate.add('y', 1));
16835     },
16836
16837     
16838     handleMouseWheel : function(e){
16839         e.stopEvent();
16840         if(!this.disabled){
16841             var delta = e.getWheelDelta();
16842             if(delta > 0){
16843                 this.showPrevMonth();
16844             } else if(delta < 0){
16845                 this.showNextMonth();
16846             }
16847         }
16848     },
16849
16850     
16851     handleDateClick : function(e, t){
16852         e.stopEvent();
16853         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
16854             this.cancelFocus = this.focusOnSelect === false;
16855             this.setValue(new Date(t.dateValue));
16856             delete this.cancelFocus;
16857             this.fireEvent('select', this, this.value);
16858         }
16859     },
16860
16861     
16862     selectToday : function(){
16863         if(this.todayBtn && !this.todayBtn.disabled){
16864             this.setValue(new Date().clearTime());
16865             this.fireEvent('select', this, this.value);
16866         }
16867     },
16868
16869     
16870     update : function(date, forceRefresh){
16871         if(this.rendered){
16872             var vd = this.activeDate, vis = this.isVisible();
16873             this.activeDate = date;
16874             if(!forceRefresh && vd && this.el){
16875                 var t = date.getTime();
16876                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
16877                     this.cells.removeClass('x-date-selected');
16878                     this.cells.each(function(c){
16879                        if(c.dom.firstChild.dateValue == t){
16880                            c.addClass('x-date-selected');
16881                            if(vis && !this.cancelFocus){
16882                                Ext.fly(c.dom.firstChild).focus(50);
16883                            }
16884                            return false;
16885                        }
16886                     }, this);
16887                     return;
16888                 }
16889             }
16890             var days = date.getDaysInMonth(),
16891                 firstOfMonth = date.getFirstDateOfMonth(),
16892                 startingPos = firstOfMonth.getDay()-this.startDay;
16893
16894             if(startingPos < 0){
16895                 startingPos += 7;
16896             }
16897             days += startingPos;
16898
16899             var pm = date.add('mo', -1),
16900                 prevStart = pm.getDaysInMonth()-startingPos,
16901                 cells = this.cells.elements,
16902                 textEls = this.textNodes,
16903                 
16904                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
16905                 today = new Date().clearTime().getTime(),
16906                 sel = date.clearTime(true).getTime(),
16907                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
16908                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
16909                 ddMatch = this.disabledDatesRE,
16910                 ddText = this.disabledDatesText,
16911                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
16912                 ddaysText = this.disabledDaysText,
16913                 format = this.format;
16914
16915             if(this.showToday){
16916                 var td = new Date().clearTime(),
16917                     disable = (td < min || td > max ||
16918                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
16919                     (ddays && ddays.indexOf(td.getDay()) != -1));
16920
16921                 if(!this.disabled){
16922                     this.todayBtn.setDisabled(disable);
16923                     this.todayKeyListener[disable ? 'disable' : 'enable']();
16924                 }
16925             }
16926
16927             var setCellClass = function(cal, cell){
16928                 cell.title = '';
16929                 var t = d.clearTime(true).getTime();
16930                 cell.firstChild.dateValue = t;
16931                 if(t == today){
16932                     cell.className += ' x-date-today';
16933                     cell.title = cal.todayText;
16934                 }
16935                 if(t == sel){
16936                     cell.className += ' x-date-selected';
16937                     if(vis){
16938                         Ext.fly(cell.firstChild).focus(50);
16939                     }
16940                 }
16941                 
16942                 if(t < min) {
16943                     cell.className = ' x-date-disabled';
16944                     cell.title = cal.minText;
16945                     return;
16946                 }
16947                 if(t > max) {
16948                     cell.className = ' x-date-disabled';
16949                     cell.title = cal.maxText;
16950                     return;
16951                 }
16952                 if(ddays){
16953                     if(ddays.indexOf(d.getDay()) != -1){
16954                         cell.title = ddaysText;
16955                         cell.className = ' x-date-disabled';
16956                     }
16957                 }
16958                 if(ddMatch && format){
16959                     var fvalue = d.dateFormat(format);
16960                     if(ddMatch.test(fvalue)){
16961                         cell.title = ddText.replace('%0', fvalue);
16962                         cell.className = ' x-date-disabled';
16963                     }
16964                 }
16965             };
16966
16967             var i = 0;
16968             for(; i < startingPos; i++) {
16969                 textEls[i].innerHTML = (++prevStart);
16970                 d.setDate(d.getDate()+1);
16971                 cells[i].className = 'x-date-prevday';
16972                 setCellClass(this, cells[i]);
16973             }
16974             for(; i < days; i++){
16975                 var intDay = i - startingPos + 1;
16976                 textEls[i].innerHTML = (intDay);
16977                 d.setDate(d.getDate()+1);
16978                 cells[i].className = 'x-date-active';
16979                 setCellClass(this, cells[i]);
16980             }
16981             var extraDays = 0;
16982             for(; i < 42; i++) {
16983                  textEls[i].innerHTML = (++extraDays);
16984                  d.setDate(d.getDate()+1);
16985                  cells[i].className = 'x-date-nextday';
16986                  setCellClass(this, cells[i]);
16987             }
16988
16989             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
16990
16991             if(!this.internalRender){
16992                 var main = this.el.dom.firstChild,
16993                     w = main.offsetWidth;
16994                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
16995                 Ext.fly(main).setWidth(w);
16996                 this.internalRender = true;
16997                 
16998                 
16999                 
17000                 if(Ext.isOpera && !this.secondPass){
17001                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
17002                     this.secondPass = true;
17003                     this.update.defer(10, this, [date]);
17004                 }
17005             }
17006         }
17007     },
17008
17009     
17010     beforeDestroy : function() {
17011         if(this.rendered){
17012             Ext.destroy(
17013                 this.keyNav,
17014                 this.monthPicker,
17015                 this.eventEl,
17016                 this.mbtn,
17017                 this.nextRepeater,
17018                 this.prevRepeater,
17019                 this.cells.el,
17020                 this.todayBtn
17021             );
17022             delete this.textNodes;
17023             delete this.cells.elements;
17024         }
17025     }
17026
17027     
17028 });
17029
17030 Ext.reg('datepicker', Ext.DatePicker);
17031
17032 Ext.LoadMask = function(el, config){
17033     this.el = Ext.get(el);
17034     Ext.apply(this, config);
17035     if(this.store){
17036         this.store.on({
17037             scope: this,
17038             beforeload: this.onBeforeLoad,
17039             load: this.onLoad,
17040             exception: this.onLoad
17041         });
17042         this.removeMask = Ext.value(this.removeMask, false);
17043     }else{
17044         var um = this.el.getUpdater();
17045         um.showLoadIndicator = false; 
17046         um.on({
17047             scope: this,
17048             beforeupdate: this.onBeforeLoad,
17049             update: this.onLoad,
17050             failure: this.onLoad
17051         });
17052         this.removeMask = Ext.value(this.removeMask, true);
17053     }
17054 };
17055
17056 Ext.LoadMask.prototype = {
17057     
17058     
17059     
17060     msg : 'Loading...',
17061     
17062     msgCls : 'x-mask-loading',
17063
17064     
17065     disabled: false,
17066
17067     
17068     disable : function(){
17069        this.disabled = true;
17070     },
17071
17072     
17073     enable : function(){
17074         this.disabled = false;
17075     },
17076
17077     
17078     onLoad : function(){
17079         this.el.unmask(this.removeMask);
17080     },
17081
17082     
17083     onBeforeLoad : function(){
17084         if(!this.disabled){
17085             this.el.mask(this.msg, this.msgCls);
17086         }
17087     },
17088
17089     
17090     show: function(){
17091         this.onBeforeLoad();
17092     },
17093
17094     
17095     hide: function(){
17096         this.onLoad();
17097     },
17098
17099     
17100     destroy : function(){
17101         if(this.store){
17102             this.store.un('beforeload', this.onBeforeLoad, this);
17103             this.store.un('load', this.onLoad, this);
17104             this.store.un('exception', this.onLoad, this);
17105         }else{
17106             var um = this.el.getUpdater();
17107             um.un('beforeupdate', this.onBeforeLoad, this);
17108             um.un('update', this.onLoad, this);
17109             um.un('failure', this.onLoad, this);
17110         }
17111     }
17112 };Ext.ns('Ext.slider');
17113
17114
17115 Ext.slider.Thumb = Ext.extend(Object, {
17116
17117     
17118     constructor: function(config) {
17119         
17120         Ext.apply(this, config || {}, {
17121             cls: 'x-slider-thumb',
17122
17123             
17124             constrain: false
17125         });
17126
17127         Ext.slider.Thumb.superclass.constructor.call(this, config);
17128
17129         if (this.slider.vertical) {
17130             Ext.apply(this, Ext.slider.Thumb.Vertical);
17131         }
17132     },
17133
17134     
17135     render: function() {
17136         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
17137
17138         this.initEvents();
17139     },
17140
17141     
17142     enable: function() {
17143         this.disabled = false;
17144         this.el.removeClass(this.slider.disabledClass);
17145     },
17146
17147     
17148     disable: function() {
17149         this.disabled = true;
17150         this.el.addClass(this.slider.disabledClass);
17151     },
17152
17153     
17154     initEvents: function() {
17155         var el = this.el;
17156
17157         el.addClassOnOver('x-slider-thumb-over');
17158
17159         this.tracker = new Ext.dd.DragTracker({
17160             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
17161             onStart      : this.onDragStart.createDelegate(this),
17162             onDrag       : this.onDrag.createDelegate(this),
17163             onEnd        : this.onDragEnd.createDelegate(this),
17164             tolerance    : 3,
17165             autoStart    : 300
17166         });
17167
17168         this.tracker.initEl(el);
17169     },
17170
17171     
17172     onBeforeDragStart : function(e) {
17173         if (this.disabled) {
17174             return false;
17175         } else {
17176             this.slider.promoteThumb(this);
17177             return true;
17178         }
17179     },
17180
17181     
17182     onDragStart: function(e){
17183         this.el.addClass('x-slider-thumb-drag');
17184         this.dragging = true;
17185         this.dragStartValue = this.value;
17186
17187         this.slider.fireEvent('dragstart', this.slider, e, this);
17188     },
17189
17190     
17191     onDrag: function(e) {
17192         var slider   = this.slider,
17193             index    = this.index,
17194             newValue = this.getNewValue();
17195
17196         if (this.constrain) {
17197             var above = slider.thumbs[index + 1],
17198                 below = slider.thumbs[index - 1];
17199
17200             if (below != undefined && newValue <= below.value) newValue = below.value;
17201             if (above != undefined && newValue >= above.value) newValue = above.value;
17202         }
17203
17204         slider.setValue(index, newValue, false);
17205         slider.fireEvent('drag', slider, e, this);
17206     },
17207
17208     getNewValue: function() {
17209         var slider   = this.slider,
17210             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
17211
17212         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
17213     },
17214
17215     
17216     onDragEnd: function(e) {
17217         var slider = this.slider,
17218             value  = this.value;
17219
17220         this.el.removeClass('x-slider-thumb-drag');
17221
17222         this.dragging = false;
17223         slider.fireEvent('dragend', slider, e);
17224
17225         if (this.dragStartValue != value) {
17226             slider.fireEvent('changecomplete', slider, value, this);
17227         }
17228     },
17229     
17230     
17231     destroy: function(){
17232         Ext.destroyMembers(this, 'tracker', 'el');
17233     }
17234 });
17235
17236
17237 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
17238     
17239     
17240     vertical: false,
17241     
17242     minValue: 0,
17243     
17244     maxValue: 100,
17245     
17246     decimalPrecision: 0,
17247     
17248     keyIncrement: 1,
17249     
17250     increment: 0,
17251
17252     
17253     clickRange: [5,15],
17254
17255     
17256     clickToChange : true,
17257     
17258     animate: true,
17259
17260     
17261     dragging: false,
17262
17263     
17264     constrainThumbs: true,
17265
17266     
17267     topThumbZIndex: 10000,
17268
17269     
17270     initComponent : function(){
17271         if(!Ext.isDefined(this.value)){
17272             this.value = this.minValue;
17273         }
17274
17275         
17276         this.thumbs = [];
17277
17278         Ext.slider.MultiSlider.superclass.initComponent.call(this);
17279
17280         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
17281         this.addEvents(
17282             
17283             'beforechange',
17284
17285             
17286             'change',
17287
17288             
17289             'changecomplete',
17290
17291             
17292             'dragstart',
17293
17294             
17295             'drag',
17296
17297             
17298             'dragend'
17299         );
17300
17301         
17302         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
17303
17304         var values = this.values;
17305
17306         for (var i=0; i < values.length; i++) {
17307             this.addThumb(values[i]);
17308         }
17309
17310         if(this.vertical){
17311             Ext.apply(this, Ext.slider.Vertical);
17312         }
17313     },
17314
17315     
17316     addThumb: function(value) {
17317         var thumb = new Ext.slider.Thumb({
17318             value    : value,
17319             slider   : this,
17320             index    : this.thumbs.length,
17321             constrain: this.constrainThumbs
17322         });
17323         this.thumbs.push(thumb);
17324
17325         
17326         if (this.rendered) thumb.render();
17327     },
17328
17329     
17330     promoteThumb: function(topThumb) {
17331         var thumbs = this.thumbs,
17332             zIndex, thumb;
17333
17334         for (var i = 0, j = thumbs.length; i < j; i++) {
17335             thumb = thumbs[i];
17336
17337             if (thumb == topThumb) {
17338                 zIndex = this.topThumbZIndex;
17339             } else {
17340                 zIndex = '';
17341             }
17342
17343             thumb.el.setStyle('zIndex', zIndex);
17344         }
17345     },
17346
17347     
17348     onRender : function() {
17349         this.autoEl = {
17350             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
17351             cn : {
17352                 cls: 'x-slider-end',
17353                 cn : {
17354                     cls:'x-slider-inner',
17355                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
17356                 }
17357             }
17358         };
17359
17360         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
17361
17362         this.endEl   = this.el.first();
17363         this.innerEl = this.endEl.first();
17364         this.focusEl = this.innerEl.child('.x-slider-focus');
17365
17366         
17367         for (var i=0; i < this.thumbs.length; i++) {
17368             this.thumbs[i].render();
17369         }
17370
17371         
17372         var thumb      = this.innerEl.child('.x-slider-thumb');
17373         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
17374
17375         this.initEvents();
17376     },
17377
17378     
17379     initEvents : function(){
17380         this.mon(this.el, {
17381             scope    : this,
17382             mousedown: this.onMouseDown,
17383             keydown  : this.onKeyDown
17384         });
17385
17386         this.focusEl.swallowEvent("click", true);
17387     },
17388
17389     
17390     onMouseDown : function(e){
17391         if(this.disabled){
17392             return;
17393         }
17394
17395         
17396         var thumbClicked = false;
17397         for (var i=0; i < this.thumbs.length; i++) {
17398             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
17399         }
17400
17401         if (this.clickToChange && !thumbClicked) {
17402             var local = this.innerEl.translatePoints(e.getXY());
17403             this.onClickChange(local);
17404         }
17405         this.focus();
17406     },
17407
17408     
17409     onClickChange : function(local) {
17410         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
17411             
17412             var thumb = this.getNearest(local, 'left'),
17413                 index = thumb.index;
17414
17415             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
17416         }
17417     },
17418
17419     
17420     getNearest: function(local, prop) {
17421         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
17422             clickValue = this.reverseValue(localValue),
17423             nearestDistance = (this.maxValue - this.minValue) + 5, 
17424             index = 0,
17425             nearest = null;
17426
17427         for (var i=0; i < this.thumbs.length; i++) {
17428             var thumb = this.thumbs[i],
17429                 value = thumb.value,
17430                 dist  = Math.abs(value - clickValue);
17431
17432             if (Math.abs(dist <= nearestDistance)) {
17433                 nearest = thumb;
17434                 index = i;
17435                 nearestDistance = dist;
17436             }
17437         }
17438         return nearest;
17439     },
17440
17441     
17442     onKeyDown : function(e){
17443         
17444         if(this.disabled || this.thumbs.length !== 1){
17445             e.preventDefault();
17446             return;
17447         }
17448         var k = e.getKey(),
17449             val;
17450         switch(k){
17451             case e.UP:
17452             case e.RIGHT:
17453                 e.stopEvent();
17454                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
17455                 this.setValue(0, val, undefined, true);
17456             break;
17457             case e.DOWN:
17458             case e.LEFT:
17459                 e.stopEvent();
17460                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
17461                 this.setValue(0, val, undefined, true);
17462             break;
17463             default:
17464                 e.preventDefault();
17465         }
17466     },
17467
17468     
17469     doSnap : function(value){
17470         if (!(this.increment && value)) {
17471             return value;
17472         }
17473         var newValue = value,
17474             inc = this.increment,
17475             m = value % inc;
17476         if (m != 0) {
17477             newValue -= m;
17478             if (m * 2 >= inc) {
17479                 newValue += inc;
17480             } else if (m * 2 < -inc) {
17481                 newValue -= inc;
17482             }
17483         }
17484         return newValue.constrain(this.minValue,  this.maxValue);
17485     },
17486
17487     
17488     afterRender : function(){
17489         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
17490
17491         for (var i=0; i < this.thumbs.length; i++) {
17492             var thumb = this.thumbs[i];
17493
17494             if (thumb.value !== undefined) {
17495                 var v = this.normalizeValue(thumb.value);
17496
17497                 if (v !== thumb.value) {
17498                     
17499                     this.setValue(i, v, false);
17500                 } else {
17501                     this.moveThumb(i, this.translateValue(v), false);
17502                 }
17503             }
17504         };
17505     },
17506
17507     
17508     getRatio : function(){
17509         var w = this.innerEl.getWidth(),
17510             v = this.maxValue - this.minValue;
17511         return v == 0 ? w : (w/v);
17512     },
17513
17514     
17515     normalizeValue : function(v){
17516         v = this.doSnap(v);
17517         v = Ext.util.Format.round(v, this.decimalPrecision);
17518         v = v.constrain(this.minValue, this.maxValue);
17519         return v;
17520     },
17521
17522     
17523     setMinValue : function(val){
17524         this.minValue = val;
17525         var i = 0,
17526             thumbs = this.thumbs,
17527             len = thumbs.length,
17528             t;
17529             
17530         for(; i < len; ++i){
17531             t = thumbs[i];
17532             t.value = t.value < val ? val : t.value;
17533         }
17534         this.syncThumb();
17535     },
17536
17537     
17538     setMaxValue : function(val){
17539         this.maxValue = val;
17540         var i = 0,
17541             thumbs = this.thumbs,
17542             len = thumbs.length,
17543             t;
17544             
17545         for(; i < len; ++i){
17546             t = thumbs[i];
17547             t.value = t.value > val ? val : t.value;
17548         }
17549         this.syncThumb();
17550     },
17551
17552     
17553     setValue : function(index, v, animate, changeComplete) {
17554         var thumb = this.thumbs[index],
17555             el    = thumb.el;
17556
17557         v = this.normalizeValue(v);
17558
17559         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
17560             thumb.value = v;
17561             if(this.rendered){
17562                 this.moveThumb(index, this.translateValue(v), animate !== false);
17563                 this.fireEvent('change', this, v, thumb);
17564                 if(changeComplete){
17565                     this.fireEvent('changecomplete', this, v, thumb);
17566                 }
17567             }
17568         }
17569     },
17570
17571     
17572     translateValue : function(v) {
17573         var ratio = this.getRatio();
17574         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
17575     },
17576
17577     
17578     reverseValue : function(pos){
17579         var ratio = this.getRatio();
17580         return (pos + (this.minValue * ratio)) / ratio;
17581     },
17582
17583     
17584     moveThumb: function(index, v, animate){
17585         var thumb = this.thumbs[index].el;
17586
17587         if(!animate || this.animate === false){
17588             thumb.setLeft(v);
17589         }else{
17590             thumb.shift({left: v, stopFx: true, duration:.35});
17591         }
17592     },
17593
17594     
17595     focus : function(){
17596         this.focusEl.focus(10);
17597     },
17598
17599     
17600     onResize : function(w, h){
17601         var thumbs = this.thumbs,
17602             len = thumbs.length,
17603             i = 0;
17604             
17605         
17606         for(; i < len; ++i){
17607             thumbs[i].el.stopFx();    
17608         }
17609         
17610         if(Ext.isNumber(w)){
17611             this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
17612         }
17613         this.syncThumb();
17614         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
17615     },
17616
17617     
17618     onDisable: function(){
17619         Ext.slider.MultiSlider.superclass.onDisable.call(this);
17620
17621         for (var i=0; i < this.thumbs.length; i++) {
17622             var thumb = this.thumbs[i],
17623                 el    = thumb.el;
17624
17625             thumb.disable();
17626
17627             if(Ext.isIE){
17628                 
17629                 
17630                 var xy = el.getXY();
17631                 el.hide();
17632
17633                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
17634
17635                 if (!this.thumbHolder) {
17636                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
17637                 }
17638
17639                 this.thumbHolder.show().setXY(xy);
17640             }
17641         }
17642     },
17643
17644     
17645     onEnable: function(){
17646         Ext.slider.MultiSlider.superclass.onEnable.call(this);
17647
17648         for (var i=0; i < this.thumbs.length; i++) {
17649             var thumb = this.thumbs[i],
17650                 el    = thumb.el;
17651
17652             thumb.enable();
17653
17654             if (Ext.isIE) {
17655                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
17656
17657                 if (this.thumbHolder) this.thumbHolder.hide();
17658
17659                 el.show();
17660                 this.syncThumb();
17661             }
17662         }
17663     },
17664
17665     
17666     syncThumb : function() {
17667         if (this.rendered) {
17668             for (var i=0; i < this.thumbs.length; i++) {
17669                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
17670             }
17671         }
17672     },
17673
17674     
17675     getValue : function(index) {
17676         return this.thumbs[index].value;
17677     },
17678
17679     
17680     getValues: function() {
17681         var values = [];
17682
17683         for (var i=0; i < this.thumbs.length; i++) {
17684             values.push(this.thumbs[i].value);
17685         }
17686
17687         return values;
17688     },
17689
17690     
17691     beforeDestroy : function(){
17692         var thumbs = this.thumbs;
17693         for(var i = 0, len = thumbs.length; i < len; ++i){
17694             thumbs[i].destroy();
17695             thumbs[i] = null;
17696         }
17697         Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
17698         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
17699     }
17700 });
17701
17702 Ext.reg('multislider', Ext.slider.MultiSlider);
17703
17704
17705 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
17706     constructor: function(config) {
17707       config = config || {};
17708
17709       Ext.applyIf(config, {
17710           values: [config.value || 0]
17711       });
17712
17713       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
17714     },
17715
17716     
17717     getValue: function() {
17718         
17719         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
17720     },
17721
17722     
17723     setValue: function(value, animate) {
17724         var args = Ext.toArray(arguments),
17725             len  = args.length;
17726
17727         
17728         
17729         
17730         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
17731             args.unshift(0);
17732         }
17733
17734         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
17735     },
17736
17737     
17738     syncThumb : function() {
17739         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
17740     },
17741     
17742     
17743     getNearest : function(){
17744         
17745         return this.thumbs[0];    
17746     }
17747 });
17748
17749
17750 Ext.Slider = Ext.slider.SingleSlider;
17751
17752 Ext.reg('slider', Ext.slider.SingleSlider);
17753
17754
17755 Ext.slider.Vertical = {
17756     onResize : function(w, h){
17757         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
17758         this.syncThumb();
17759     },
17760
17761     getRatio : function(){
17762         var h = this.innerEl.getHeight(),
17763             v = this.maxValue - this.minValue;
17764         return h/v;
17765     },
17766
17767     moveThumb: function(index, v, animate) {
17768         var thumb = this.thumbs[index],
17769             el    = thumb.el;
17770
17771         if (!animate || this.animate === false) {
17772             el.setBottom(v);
17773         } else {
17774             el.shift({bottom: v, stopFx: true, duration:.35});
17775         }
17776     },
17777
17778     onClickChange : function(local) {
17779         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
17780             var thumb = this.getNearest(local, 'top'),
17781                 index = thumb.index,
17782                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
17783
17784             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
17785         }
17786     }
17787 };
17788
17789
17790 Ext.slider.Thumb.Vertical = {
17791     getNewValue: function() {
17792         var slider   = this.slider,
17793             innerEl  = slider.innerEl,
17794             pos      = innerEl.translatePoints(this.tracker.getXY()),
17795             bottom   = innerEl.getHeight() - pos.top;
17796
17797         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
17798     }
17799 };
17800
17801 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
17802    
17803     baseCls : 'x-progress',
17804     
17805     
17806     animate : false,
17807
17808     
17809     waitTimer : null,
17810
17811     
17812     initComponent : function(){
17813         Ext.ProgressBar.superclass.initComponent.call(this);
17814         this.addEvents(
17815             
17816             "update"
17817         );
17818     },
17819
17820     
17821     onRender : function(ct, position){
17822         var tpl = new Ext.Template(
17823             '<div class="{cls}-wrap">',
17824                 '<div class="{cls}-inner">',
17825                     '<div class="{cls}-bar">',
17826                         '<div class="{cls}-text">',
17827                             '<div>&#160;</div>',
17828                         '</div>',
17829                     '</div>',
17830                     '<div class="{cls}-text {cls}-text-back">',
17831                         '<div>&#160;</div>',
17832                     '</div>',
17833                 '</div>',
17834             '</div>'
17835         );
17836
17837         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
17838             : tpl.append(ct, {cls: this.baseCls}, true);
17839                 
17840         if(this.id){
17841             this.el.dom.id = this.id;
17842         }
17843         var inner = this.el.dom.firstChild;
17844         this.progressBar = Ext.get(inner.firstChild);
17845
17846         if(this.textEl){
17847             
17848             this.textEl = Ext.get(this.textEl);
17849             delete this.textTopEl;
17850         }else{
17851             
17852             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
17853             var textBackEl = Ext.get(inner.childNodes[1]);
17854             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
17855             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
17856             this.textEl.setWidth(inner.offsetWidth);
17857         }
17858         this.progressBar.setHeight(inner.offsetHeight);
17859     },
17860     
17861     
17862     afterRender : function(){
17863         Ext.ProgressBar.superclass.afterRender.call(this);
17864         if(this.value){
17865             this.updateProgress(this.value, this.text);
17866         }else{
17867             this.updateText(this.text);
17868         }
17869     },
17870
17871     
17872     updateProgress : function(value, text, animate){
17873         this.value = value || 0;
17874         if(text){
17875             this.updateText(text);
17876         }
17877         if(this.rendered && !this.isDestroyed){
17878             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
17879             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
17880             if(this.textTopEl){
17881                 
17882                 this.textTopEl.removeClass('x-hidden').setWidth(w);
17883             }
17884         }
17885         this.fireEvent('update', this, value, text);
17886         return this;
17887     },
17888
17889     
17890     wait : function(o){
17891         if(!this.waitTimer){
17892             var scope = this;
17893             o = o || {};
17894             this.updateText(o.text);
17895             this.waitTimer = Ext.TaskMgr.start({
17896                 run: function(i){
17897                     var inc = o.increment || 10;
17898                     i -= 1;
17899                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
17900                 },
17901                 interval: o.interval || 1000,
17902                 duration: o.duration,
17903                 onStop: function(){
17904                     if(o.fn){
17905                         o.fn.apply(o.scope || this);
17906                     }
17907                     this.reset();
17908                 },
17909                 scope: scope
17910             });
17911         }
17912         return this;
17913     },
17914
17915     
17916     isWaiting : function(){
17917         return this.waitTimer !== null;
17918     },
17919
17920     
17921     updateText : function(text){
17922         this.text = text || '&#160;';
17923         if(this.rendered){
17924             this.textEl.update(this.text);
17925         }
17926         return this;
17927     },
17928     
17929     
17930     syncProgressBar : function(){
17931         if(this.value){
17932             this.updateProgress(this.value, this.text);
17933         }
17934         return this;
17935     },
17936
17937     
17938     setSize : function(w, h){
17939         Ext.ProgressBar.superclass.setSize.call(this, w, h);
17940         if(this.textTopEl){
17941             var inner = this.el.dom.firstChild;
17942             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
17943         }
17944         this.syncProgressBar();
17945         return this;
17946     },
17947
17948     
17949     reset : function(hide){
17950         this.updateProgress(0);
17951         if(this.textTopEl){
17952             this.textTopEl.addClass('x-hidden');
17953         }
17954         this.clearTimer();
17955         if(hide === true){
17956             this.hide();
17957         }
17958         return this;
17959     },
17960     
17961     
17962     clearTimer : function(){
17963         if(this.waitTimer){
17964             this.waitTimer.onStop = null; 
17965             Ext.TaskMgr.stop(this.waitTimer);
17966             this.waitTimer = null;
17967         }
17968     },
17969     
17970     onDestroy: function(){
17971         this.clearTimer();
17972         if(this.rendered){
17973             if(this.textEl.isComposite){
17974                 this.textEl.clear();
17975             }
17976             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
17977         }
17978         Ext.ProgressBar.superclass.onDestroy.call(this);
17979     }
17980 });
17981 Ext.reg('progress', Ext.ProgressBar);
17982
17983 (function() {
17984
17985 var Event=Ext.EventManager;
17986 var Dom=Ext.lib.Dom;
17987
17988
17989 Ext.dd.DragDrop = function(id, sGroup, config) {
17990     if(id) {
17991         this.init(id, sGroup, config);
17992     }
17993 };
17994
17995 Ext.dd.DragDrop.prototype = {
17996
17997     
17998
17999     
18000     id: null,
18001
18002     
18003     config: null,
18004
18005     
18006     dragElId: null,
18007
18008     
18009     handleElId: null,
18010
18011     
18012     invalidHandleTypes: null,
18013
18014     
18015     invalidHandleIds: null,
18016
18017     
18018     invalidHandleClasses: null,
18019
18020     
18021     startPageX: 0,
18022
18023     
18024     startPageY: 0,
18025
18026     
18027     groups: null,
18028
18029     
18030     locked: false,
18031
18032     
18033     lock: function() {
18034         this.locked = true;
18035     },
18036
18037     
18038     moveOnly: false,
18039
18040     
18041     unlock: function() {
18042         this.locked = false;
18043     },
18044
18045     
18046     isTarget: true,
18047
18048     
18049     padding: null,
18050
18051     
18052     _domRef: null,
18053
18054     
18055     __ygDragDrop: true,
18056
18057     
18058     constrainX: false,
18059
18060     
18061     constrainY: false,
18062
18063     
18064     minX: 0,
18065
18066     
18067     maxX: 0,
18068
18069     
18070     minY: 0,
18071
18072     
18073     maxY: 0,
18074
18075     
18076     maintainOffset: false,
18077
18078     
18079     xTicks: null,
18080
18081     
18082     yTicks: null,
18083
18084     
18085     primaryButtonOnly: true,
18086
18087     
18088     available: false,
18089
18090     
18091     hasOuterHandles: false,
18092
18093     
18094     b4StartDrag: function(x, y) { },
18095
18096     
18097     startDrag: function(x, y) {  },
18098
18099     
18100     b4Drag: function(e) { },
18101
18102     
18103     onDrag: function(e) {  },
18104
18105     
18106     onDragEnter: function(e, id) {  },
18107
18108     
18109     b4DragOver: function(e) { },
18110
18111     
18112     onDragOver: function(e, id) {  },
18113
18114     
18115     b4DragOut: function(e) { },
18116
18117     
18118     onDragOut: function(e, id) {  },
18119
18120     
18121     b4DragDrop: function(e) { },
18122
18123     
18124     onDragDrop: function(e, id) {  },
18125
18126     
18127     onInvalidDrop: function(e) {  },
18128
18129     
18130     b4EndDrag: function(e) { },
18131
18132     
18133     endDrag: function(e) {  },
18134
18135     
18136     b4MouseDown: function(e) {  },
18137
18138     
18139     onMouseDown: function(e) {  },
18140
18141     
18142     onMouseUp: function(e) {  },
18143
18144     
18145     onAvailable: function () {
18146     },
18147
18148     
18149     defaultPadding : {left:0, right:0, top:0, bottom:0},
18150
18151     
18152     constrainTo : function(constrainTo, pad, inContent){
18153         if(Ext.isNumber(pad)){
18154             pad = {left: pad, right:pad, top:pad, bottom:pad};
18155         }
18156         pad = pad || this.defaultPadding;
18157         var b = Ext.get(this.getEl()).getBox(),
18158             ce = Ext.get(constrainTo),
18159             s = ce.getScroll(),
18160             c, 
18161             cd = ce.dom;
18162         if(cd == document.body){
18163             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
18164         }else{
18165             var xy = ce.getXY();
18166             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
18167         }
18168
18169
18170         var topSpace = b.y - c.y,
18171             leftSpace = b.x - c.x;
18172
18173         this.resetConstraints();
18174         this.setXConstraint(leftSpace - (pad.left||0), 
18175                 c.width - leftSpace - b.width - (pad.right||0), 
18176                                 this.xTickSize
18177         );
18178         this.setYConstraint(topSpace - (pad.top||0), 
18179                 c.height - topSpace - b.height - (pad.bottom||0), 
18180                                 this.yTickSize
18181         );
18182     },
18183
18184     
18185     getEl: function() {
18186         if (!this._domRef) {
18187             this._domRef = Ext.getDom(this.id);
18188         }
18189
18190         return this._domRef;
18191     },
18192
18193     
18194     getDragEl: function() {
18195         return Ext.getDom(this.dragElId);
18196     },
18197
18198     
18199     init: function(id, sGroup, config) {
18200         this.initTarget(id, sGroup, config);
18201         Event.on(this.id, "mousedown", this.handleMouseDown, this);
18202         
18203     },
18204
18205     
18206     initTarget: function(id, sGroup, config) {
18207
18208         
18209         this.config = config || {};
18210
18211         
18212         this.DDM = Ext.dd.DDM;
18213         
18214         this.groups = {};
18215
18216         
18217         
18218         if (typeof id !== "string") {
18219             id = Ext.id(id);
18220         }
18221
18222         
18223         this.id = id;
18224
18225         
18226         this.addToGroup((sGroup) ? sGroup : "default");
18227
18228         
18229         
18230         this.handleElId = id;
18231
18232         
18233         this.setDragElId(id);
18234
18235         
18236         this.invalidHandleTypes = { A: "A" };
18237         this.invalidHandleIds = {};
18238         this.invalidHandleClasses = [];
18239
18240         this.applyConfig();
18241
18242         this.handleOnAvailable();
18243     },
18244
18245     
18246     applyConfig: function() {
18247
18248         
18249         
18250         this.padding           = this.config.padding || [0, 0, 0, 0];
18251         this.isTarget          = (this.config.isTarget !== false);
18252         this.maintainOffset    = (this.config.maintainOffset);
18253         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18254
18255     },
18256
18257     
18258     handleOnAvailable: function() {
18259         this.available = true;
18260         this.resetConstraints();
18261         this.onAvailable();
18262     },
18263
18264      
18265     setPadding: function(iTop, iRight, iBot, iLeft) {
18266         
18267         if (!iRight && 0 !== iRight) {
18268             this.padding = [iTop, iTop, iTop, iTop];
18269         } else if (!iBot && 0 !== iBot) {
18270             this.padding = [iTop, iRight, iTop, iRight];
18271         } else {
18272             this.padding = [iTop, iRight, iBot, iLeft];
18273         }
18274     },
18275
18276     
18277     setInitPosition: function(diffX, diffY) {
18278         var el = this.getEl();
18279
18280         if (!this.DDM.verifyEl(el)) {
18281             return;
18282         }
18283
18284         var dx = diffX || 0;
18285         var dy = diffY || 0;
18286
18287         var p = Dom.getXY( el );
18288
18289         this.initPageX = p[0] - dx;
18290         this.initPageY = p[1] - dy;
18291
18292         this.lastPageX = p[0];
18293         this.lastPageY = p[1];
18294
18295         this.setStartPosition(p);
18296     },
18297
18298     
18299     setStartPosition: function(pos) {
18300         var p = pos || Dom.getXY( this.getEl() );
18301         this.deltaSetXY = null;
18302
18303         this.startPageX = p[0];
18304         this.startPageY = p[1];
18305     },
18306
18307     
18308     addToGroup: function(sGroup) {
18309         this.groups[sGroup] = true;
18310         this.DDM.regDragDrop(this, sGroup);
18311     },
18312
18313     
18314     removeFromGroup: function(sGroup) {
18315         if (this.groups[sGroup]) {
18316             delete this.groups[sGroup];
18317         }
18318
18319         this.DDM.removeDDFromGroup(this, sGroup);
18320     },
18321
18322     
18323     setDragElId: function(id) {
18324         this.dragElId = id;
18325     },
18326
18327     
18328     setHandleElId: function(id) {
18329         if (typeof id !== "string") {
18330             id = Ext.id(id);
18331         }
18332         this.handleElId = id;
18333         this.DDM.regHandle(this.id, id);
18334     },
18335
18336     
18337     setOuterHandleElId: function(id) {
18338         if (typeof id !== "string") {
18339             id = Ext.id(id);
18340         }
18341         Event.on(id, "mousedown",
18342                 this.handleMouseDown, this);
18343         this.setHandleElId(id);
18344
18345         this.hasOuterHandles = true;
18346     },
18347
18348     
18349     unreg: function() {
18350         Event.un(this.id, "mousedown",
18351                 this.handleMouseDown);
18352         this._domRef = null;
18353         this.DDM._remove(this);
18354     },
18355
18356     destroy : function(){
18357         this.unreg();
18358     },
18359
18360     
18361     isLocked: function() {
18362         return (this.DDM.isLocked() || this.locked);
18363     },
18364
18365     
18366     handleMouseDown: function(e, oDD){
18367         if (this.primaryButtonOnly && e.button != 0) {
18368             return;
18369         }
18370
18371         if (this.isLocked()) {
18372             return;
18373         }
18374
18375         this.DDM.refreshCache(this.groups);
18376
18377         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
18378         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
18379         } else {
18380             if (this.clickValidator(e)) {
18381
18382                 
18383                 this.setStartPosition();
18384
18385                 this.b4MouseDown(e);
18386                 this.onMouseDown(e);
18387
18388                 this.DDM.handleMouseDown(e, this);
18389
18390                 this.DDM.stopEvent(e);
18391             } else {
18392
18393
18394             }
18395         }
18396     },
18397
18398     clickValidator: function(e) {
18399         var target = e.getTarget();
18400         return ( this.isValidHandleChild(target) &&
18401                     (this.id == this.handleElId ||
18402                         this.DDM.handleWasClicked(target, this.id)) );
18403     },
18404
18405     
18406     addInvalidHandleType: function(tagName) {
18407         var type = tagName.toUpperCase();
18408         this.invalidHandleTypes[type] = type;
18409     },
18410
18411     
18412     addInvalidHandleId: function(id) {
18413         if (typeof id !== "string") {
18414             id = Ext.id(id);
18415         }
18416         this.invalidHandleIds[id] = id;
18417     },
18418
18419     
18420     addInvalidHandleClass: function(cssClass) {
18421         this.invalidHandleClasses.push(cssClass);
18422     },
18423
18424     
18425     removeInvalidHandleType: function(tagName) {
18426         var type = tagName.toUpperCase();
18427         
18428         delete this.invalidHandleTypes[type];
18429     },
18430
18431     
18432     removeInvalidHandleId: function(id) {
18433         if (typeof id !== "string") {
18434             id = Ext.id(id);
18435         }
18436         delete this.invalidHandleIds[id];
18437     },
18438
18439     
18440     removeInvalidHandleClass: function(cssClass) {
18441         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18442             if (this.invalidHandleClasses[i] == cssClass) {
18443                 delete this.invalidHandleClasses[i];
18444             }
18445         }
18446     },
18447
18448     
18449     isValidHandleChild: function(node) {
18450
18451         var valid = true;
18452         
18453         var nodeName;
18454         try {
18455             nodeName = node.nodeName.toUpperCase();
18456         } catch(e) {
18457             nodeName = node.nodeName;
18458         }
18459         valid = valid && !this.invalidHandleTypes[nodeName];
18460         valid = valid && !this.invalidHandleIds[node.id];
18461
18462         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18463             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
18464         }
18465
18466
18467         return valid;
18468
18469     },
18470
18471     
18472     setXTicks: function(iStartX, iTickSize) {
18473         this.xTicks = [];
18474         this.xTickSize = iTickSize;
18475
18476         var tickMap = {};
18477
18478         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18479             if (!tickMap[i]) {
18480                 this.xTicks[this.xTicks.length] = i;
18481                 tickMap[i] = true;
18482             }
18483         }
18484
18485         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18486             if (!tickMap[i]) {
18487                 this.xTicks[this.xTicks.length] = i;
18488                 tickMap[i] = true;
18489             }
18490         }
18491
18492         this.xTicks.sort(this.DDM.numericSort) ;
18493     },
18494
18495     
18496     setYTicks: function(iStartY, iTickSize) {
18497         this.yTicks = [];
18498         this.yTickSize = iTickSize;
18499
18500         var tickMap = {};
18501
18502         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18503             if (!tickMap[i]) {
18504                 this.yTicks[this.yTicks.length] = i;
18505                 tickMap[i] = true;
18506             }
18507         }
18508
18509         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18510             if (!tickMap[i]) {
18511                 this.yTicks[this.yTicks.length] = i;
18512                 tickMap[i] = true;
18513             }
18514         }
18515
18516         this.yTicks.sort(this.DDM.numericSort) ;
18517     },
18518
18519     
18520     setXConstraint: function(iLeft, iRight, iTickSize) {
18521         this.leftConstraint = iLeft;
18522         this.rightConstraint = iRight;
18523
18524         this.minX = this.initPageX - iLeft;
18525         this.maxX = this.initPageX + iRight;
18526         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
18527
18528         this.constrainX = true;
18529     },
18530
18531     
18532     clearConstraints: function() {
18533         this.constrainX = false;
18534         this.constrainY = false;
18535         this.clearTicks();
18536     },
18537
18538     
18539     clearTicks: function() {
18540         this.xTicks = null;
18541         this.yTicks = null;
18542         this.xTickSize = 0;
18543         this.yTickSize = 0;
18544     },
18545
18546     
18547     setYConstraint: function(iUp, iDown, iTickSize) {
18548         this.topConstraint = iUp;
18549         this.bottomConstraint = iDown;
18550
18551         this.minY = this.initPageY - iUp;
18552         this.maxY = this.initPageY + iDown;
18553         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
18554
18555         this.constrainY = true;
18556
18557     },
18558
18559     
18560     resetConstraints: function() {
18561         
18562         if (this.initPageX || this.initPageX === 0) {
18563             
18564             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
18565             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
18566
18567             this.setInitPosition(dx, dy);
18568
18569         
18570         } else {
18571             this.setInitPosition();
18572         }
18573
18574         if (this.constrainX) {
18575             this.setXConstraint( this.leftConstraint,
18576                                  this.rightConstraint,
18577                                  this.xTickSize        );
18578         }
18579
18580         if (this.constrainY) {
18581             this.setYConstraint( this.topConstraint,
18582                                  this.bottomConstraint,
18583                                  this.yTickSize         );
18584         }
18585     },
18586
18587     
18588     getTick: function(val, tickArray) {
18589         if (!tickArray) {
18590             
18591             
18592             return val;
18593         } else if (tickArray[0] >= val) {
18594             
18595             
18596             return tickArray[0];
18597         } else {
18598             for (var i=0, len=tickArray.length; i<len; ++i) {
18599                 var next = i + 1;
18600                 if (tickArray[next] && tickArray[next] >= val) {
18601                     var diff1 = val - tickArray[i];
18602                     var diff2 = tickArray[next] - val;
18603                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
18604                 }
18605             }
18606
18607             
18608             
18609             return tickArray[tickArray.length - 1];
18610         }
18611     },
18612
18613     
18614     toString: function() {
18615         return ("DragDrop " + this.id);
18616     }
18617
18618 };
18619
18620 })();
18621
18622
18623
18624
18625 if (!Ext.dd.DragDropMgr) {
18626
18627
18628 Ext.dd.DragDropMgr = function() {
18629
18630     var Event = Ext.EventManager;
18631
18632     return {
18633
18634         
18635         ids: {},
18636
18637         
18638         handleIds: {},
18639
18640         
18641         dragCurrent: null,
18642
18643         
18644         dragOvers: {},
18645
18646         
18647         deltaX: 0,
18648
18649         
18650         deltaY: 0,
18651
18652         
18653         preventDefault: true,
18654
18655         
18656         stopPropagation: true,
18657
18658         
18659         initialized: false,
18660
18661         
18662         locked: false,
18663
18664         
18665         init: function() {
18666             this.initialized = true;
18667         },
18668
18669         
18670         POINT: 0,
18671
18672         
18673         INTERSECT: 1,
18674
18675         
18676         mode: 0,
18677
18678         
18679         _execOnAll: function(sMethod, args) {
18680             for (var i in this.ids) {
18681                 for (var j in this.ids[i]) {
18682                     var oDD = this.ids[i][j];
18683                     if (! this.isTypeOfDD(oDD)) {
18684                         continue;
18685                     }
18686                     oDD[sMethod].apply(oDD, args);
18687                 }
18688             }
18689         },
18690
18691         
18692         _onLoad: function() {
18693
18694             this.init();
18695
18696
18697             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
18698             Event.on(document, "mousemove", this.handleMouseMove, this, true);
18699             Event.on(window,   "unload",    this._onUnload, this, true);
18700             Event.on(window,   "resize",    this._onResize, this, true);
18701             
18702
18703         },
18704
18705         
18706         _onResize: function(e) {
18707             this._execOnAll("resetConstraints", []);
18708         },
18709
18710         
18711         lock: function() { this.locked = true; },
18712
18713         
18714         unlock: function() { this.locked = false; },
18715
18716         
18717         isLocked: function() { return this.locked; },
18718
18719         
18720         locationCache: {},
18721
18722         
18723         useCache: true,
18724
18725         
18726         clickPixelThresh: 3,
18727
18728         
18729         clickTimeThresh: 350,
18730
18731         
18732         dragThreshMet: false,
18733
18734         
18735         clickTimeout: null,
18736
18737         
18738         startX: 0,
18739
18740         
18741         startY: 0,
18742
18743         
18744         regDragDrop: function(oDD, sGroup) {
18745             if (!this.initialized) { this.init(); }
18746
18747             if (!this.ids[sGroup]) {
18748                 this.ids[sGroup] = {};
18749             }
18750             this.ids[sGroup][oDD.id] = oDD;
18751         },
18752
18753         
18754         removeDDFromGroup: function(oDD, sGroup) {
18755             if (!this.ids[sGroup]) {
18756                 this.ids[sGroup] = {};
18757             }
18758
18759             var obj = this.ids[sGroup];
18760             if (obj && obj[oDD.id]) {
18761                 delete obj[oDD.id];
18762             }
18763         },
18764
18765         
18766         _remove: function(oDD) {
18767             for (var g in oDD.groups) {
18768                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
18769                     delete this.ids[g][oDD.id];
18770                 }
18771             }
18772             delete this.handleIds[oDD.id];
18773         },
18774
18775         
18776         regHandle: function(sDDId, sHandleId) {
18777             if (!this.handleIds[sDDId]) {
18778                 this.handleIds[sDDId] = {};
18779             }
18780             this.handleIds[sDDId][sHandleId] = sHandleId;
18781         },
18782
18783         
18784         isDragDrop: function(id) {
18785             return ( this.getDDById(id) ) ? true : false;
18786         },
18787
18788         
18789         getRelated: function(p_oDD, bTargetsOnly) {
18790             var oDDs = [];
18791             for (var i in p_oDD.groups) {
18792                 for (var j in this.ids[i]) {
18793                     var dd = this.ids[i][j];
18794                     if (! this.isTypeOfDD(dd)) {
18795                         continue;
18796                     }
18797                     if (!bTargetsOnly || dd.isTarget) {
18798                         oDDs[oDDs.length] = dd;
18799                     }
18800                 }
18801             }
18802
18803             return oDDs;
18804         },
18805
18806         
18807         isLegalTarget: function (oDD, oTargetDD) {
18808             var targets = this.getRelated(oDD, true);
18809             for (var i=0, len=targets.length;i<len;++i) {
18810                 if (targets[i].id == oTargetDD.id) {
18811                     return true;
18812                 }
18813             }
18814
18815             return false;
18816         },
18817
18818         
18819         isTypeOfDD: function (oDD) {
18820             return (oDD && oDD.__ygDragDrop);
18821         },
18822
18823         
18824         isHandle: function(sDDId, sHandleId) {
18825             return ( this.handleIds[sDDId] &&
18826                             this.handleIds[sDDId][sHandleId] );
18827         },
18828
18829         
18830         getDDById: function(id) {
18831             for (var i in this.ids) {
18832                 if (this.ids[i][id]) {
18833                     return this.ids[i][id];
18834                 }
18835             }
18836             return null;
18837         },
18838
18839         
18840         handleMouseDown: function(e, oDD) {
18841             if(Ext.QuickTips){
18842                 Ext.QuickTips.disable();
18843             }
18844             if(this.dragCurrent){
18845                 
18846                 
18847                 this.handleMouseUp(e);
18848             }
18849             
18850             this.currentTarget = e.getTarget();
18851             this.dragCurrent = oDD;
18852
18853             var el = oDD.getEl();
18854
18855             
18856             this.startX = e.getPageX();
18857             this.startY = e.getPageY();
18858
18859             this.deltaX = this.startX - el.offsetLeft;
18860             this.deltaY = this.startY - el.offsetTop;
18861
18862             this.dragThreshMet = false;
18863
18864             this.clickTimeout = setTimeout(
18865                     function() {
18866                         var DDM = Ext.dd.DDM;
18867                         DDM.startDrag(DDM.startX, DDM.startY);
18868                     },
18869                     this.clickTimeThresh );
18870         },
18871
18872         
18873         startDrag: function(x, y) {
18874             clearTimeout(this.clickTimeout);
18875             if (this.dragCurrent) {
18876                 this.dragCurrent.b4StartDrag(x, y);
18877                 this.dragCurrent.startDrag(x, y);
18878             }
18879             this.dragThreshMet = true;
18880         },
18881
18882         
18883         handleMouseUp: function(e) {
18884
18885             if(Ext.QuickTips){
18886                 Ext.QuickTips.enable();
18887             }
18888             if (! this.dragCurrent) {
18889                 return;
18890             }
18891
18892             clearTimeout(this.clickTimeout);
18893
18894             if (this.dragThreshMet) {
18895                 this.fireEvents(e, true);
18896             } else {
18897             }
18898
18899             this.stopDrag(e);
18900
18901             this.stopEvent(e);
18902         },
18903
18904         
18905         stopEvent: function(e){
18906             if(this.stopPropagation) {
18907                 e.stopPropagation();
18908             }
18909
18910             if (this.preventDefault) {
18911                 e.preventDefault();
18912             }
18913         },
18914
18915         
18916         stopDrag: function(e) {
18917             
18918             if (this.dragCurrent) {
18919                 if (this.dragThreshMet) {
18920                     this.dragCurrent.b4EndDrag(e);
18921                     this.dragCurrent.endDrag(e);
18922                 }
18923
18924                 this.dragCurrent.onMouseUp(e);
18925             }
18926
18927             this.dragCurrent = null;
18928             this.dragOvers = {};
18929         },
18930
18931         
18932         handleMouseMove: function(e) {
18933             if (! this.dragCurrent) {
18934                 return true;
18935             }
18936             
18937
18938             
18939             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
18940                 this.stopEvent(e);
18941                 return this.handleMouseUp(e);
18942             }
18943
18944             if (!this.dragThreshMet) {
18945                 var diffX = Math.abs(this.startX - e.getPageX());
18946                 var diffY = Math.abs(this.startY - e.getPageY());
18947                 if (diffX > this.clickPixelThresh ||
18948                             diffY > this.clickPixelThresh) {
18949                     this.startDrag(this.startX, this.startY);
18950                 }
18951             }
18952
18953             if (this.dragThreshMet) {
18954                 this.dragCurrent.b4Drag(e);
18955                 this.dragCurrent.onDrag(e);
18956                 if(!this.dragCurrent.moveOnly){
18957                     this.fireEvents(e, false);
18958                 }
18959             }
18960
18961             this.stopEvent(e);
18962
18963             return true;
18964         },
18965
18966         
18967         fireEvents: function(e, isDrop) {
18968             var dc = this.dragCurrent;
18969
18970             
18971             
18972             if (!dc || dc.isLocked()) {
18973                 return;
18974             }
18975
18976             var pt = e.getPoint();
18977
18978             
18979             var oldOvers = [];
18980
18981             var outEvts   = [];
18982             var overEvts  = [];
18983             var dropEvts  = [];
18984             var enterEvts = [];
18985
18986             
18987             
18988             for (var i in this.dragOvers) {
18989
18990                 var ddo = this.dragOvers[i];
18991
18992                 if (! this.isTypeOfDD(ddo)) {
18993                     continue;
18994                 }
18995
18996                 if (! this.isOverTarget(pt, ddo, this.mode)) {
18997                     outEvts.push( ddo );
18998                 }
18999
19000                 oldOvers[i] = true;
19001                 delete this.dragOvers[i];
19002             }
19003
19004             for (var sGroup in dc.groups) {
19005
19006                 if ("string" != typeof sGroup) {
19007                     continue;
19008                 }
19009
19010                 for (i in this.ids[sGroup]) {
19011                     var oDD = this.ids[sGroup][i];
19012                     if (! this.isTypeOfDD(oDD)) {
19013                         continue;
19014                     }
19015
19016                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
19017                         if (this.isOverTarget(pt, oDD, this.mode)) {
19018                             
19019                             if (isDrop) {
19020                                 dropEvts.push( oDD );
19021                             
19022                             } else {
19023
19024                                 
19025                                 if (!oldOvers[oDD.id]) {
19026                                     enterEvts.push( oDD );
19027                                 
19028                                 } else {
19029                                     overEvts.push( oDD );
19030                                 }
19031
19032                                 this.dragOvers[oDD.id] = oDD;
19033                             }
19034                         }
19035                     }
19036                 }
19037             }
19038
19039             if (this.mode) {
19040                 if (outEvts.length) {
19041                     dc.b4DragOut(e, outEvts);
19042                     dc.onDragOut(e, outEvts);
19043                 }
19044
19045                 if (enterEvts.length) {
19046                     dc.onDragEnter(e, enterEvts);
19047                 }
19048
19049                 if (overEvts.length) {
19050                     dc.b4DragOver(e, overEvts);
19051                     dc.onDragOver(e, overEvts);
19052                 }
19053
19054                 if (dropEvts.length) {
19055                     dc.b4DragDrop(e, dropEvts);
19056                     dc.onDragDrop(e, dropEvts);
19057                 }
19058
19059             } else {
19060                 
19061                 var len = 0;
19062                 for (i=0, len=outEvts.length; i<len; ++i) {
19063                     dc.b4DragOut(e, outEvts[i].id);
19064                     dc.onDragOut(e, outEvts[i].id);
19065                 }
19066
19067                 
19068                 for (i=0,len=enterEvts.length; i<len; ++i) {
19069                     
19070                     dc.onDragEnter(e, enterEvts[i].id);
19071                 }
19072
19073                 
19074                 for (i=0,len=overEvts.length; i<len; ++i) {
19075                     dc.b4DragOver(e, overEvts[i].id);
19076                     dc.onDragOver(e, overEvts[i].id);
19077                 }
19078
19079                 
19080                 for (i=0, len=dropEvts.length; i<len; ++i) {
19081                     dc.b4DragDrop(e, dropEvts[i].id);
19082                     dc.onDragDrop(e, dropEvts[i].id);
19083                 }
19084
19085             }
19086
19087             
19088             if (isDrop && !dropEvts.length) {
19089                 dc.onInvalidDrop(e);
19090             }
19091
19092         },
19093
19094         
19095         getBestMatch: function(dds) {
19096             var winner = null;
19097             
19098             
19099                
19100             
19101             
19102
19103             var len = dds.length;
19104
19105             if (len == 1) {
19106                 winner = dds[0];
19107             } else {
19108                 
19109                 for (var i=0; i<len; ++i) {
19110                     var dd = dds[i];
19111                     
19112                     
19113                     
19114                     if (dd.cursorIsOver) {
19115                         winner = dd;
19116                         break;
19117                     
19118                     } else {
19119                         if (!winner ||
19120                             winner.overlap.getArea() < dd.overlap.getArea()) {
19121                             winner = dd;
19122                         }
19123                     }
19124                 }
19125             }
19126
19127             return winner;
19128         },
19129
19130         
19131         refreshCache: function(groups) {
19132             for (var sGroup in groups) {
19133                 if ("string" != typeof sGroup) {
19134                     continue;
19135                 }
19136                 for (var i in this.ids[sGroup]) {
19137                     var oDD = this.ids[sGroup][i];
19138
19139                     if (this.isTypeOfDD(oDD)) {
19140                     
19141                         var loc = this.getLocation(oDD);
19142                         if (loc) {
19143                             this.locationCache[oDD.id] = loc;
19144                         } else {
19145                             delete this.locationCache[oDD.id];
19146                             
19147                             
19148                             
19149                         }
19150                     }
19151                 }
19152             }
19153         },
19154
19155         
19156         verifyEl: function(el) {
19157             if (el) {
19158                 var parent;
19159                 if(Ext.isIE){
19160                     try{
19161                         parent = el.offsetParent;
19162                     }catch(e){}
19163                 }else{
19164                     parent = el.offsetParent;
19165                 }
19166                 if (parent) {
19167                     return true;
19168                 }
19169             }
19170
19171             return false;
19172         },
19173
19174         
19175         getLocation: function(oDD) {
19176             if (! this.isTypeOfDD(oDD)) {
19177                 return null;
19178             }
19179
19180             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
19181
19182             try {
19183                 pos= Ext.lib.Dom.getXY(el);
19184             } catch (e) { }
19185
19186             if (!pos) {
19187                 return null;
19188             }
19189
19190             x1 = pos[0];
19191             x2 = x1 + el.offsetWidth;
19192             y1 = pos[1];
19193             y2 = y1 + el.offsetHeight;
19194
19195             t = y1 - oDD.padding[0];
19196             r = x2 + oDD.padding[1];
19197             b = y2 + oDD.padding[2];
19198             l = x1 - oDD.padding[3];
19199
19200             return new Ext.lib.Region( t, r, b, l );
19201         },
19202
19203         
19204         isOverTarget: function(pt, oTarget, intersect) {
19205             
19206             var loc = this.locationCache[oTarget.id];
19207             if (!loc || !this.useCache) {
19208                 loc = this.getLocation(oTarget);
19209                 this.locationCache[oTarget.id] = loc;
19210
19211             }
19212
19213             if (!loc) {
19214                 return false;
19215             }
19216
19217             oTarget.cursorIsOver = loc.contains( pt );
19218
19219             
19220             
19221             
19222             
19223             
19224             var dc = this.dragCurrent;
19225             if (!dc || !dc.getTargetCoord ||
19226                     (!intersect && !dc.constrainX && !dc.constrainY)) {
19227                 return oTarget.cursorIsOver;
19228             }
19229
19230             oTarget.overlap = null;
19231
19232             
19233             
19234             
19235             
19236             var pos = dc.getTargetCoord(pt.x, pt.y);
19237
19238             var el = dc.getDragEl();
19239             var curRegion = new Ext.lib.Region( pos.y,
19240                                                    pos.x + el.offsetWidth,
19241                                                    pos.y + el.offsetHeight,
19242                                                    pos.x );
19243
19244             var overlap = curRegion.intersect(loc);
19245
19246             if (overlap) {
19247                 oTarget.overlap = overlap;
19248                 return (intersect) ? true : oTarget.cursorIsOver;
19249             } else {
19250                 return false;
19251             }
19252         },
19253
19254         
19255         _onUnload: function(e, me) {
19256             Ext.dd.DragDropMgr.unregAll();
19257         },
19258
19259         
19260         unregAll: function() {
19261
19262             if (this.dragCurrent) {
19263                 this.stopDrag();
19264                 this.dragCurrent = null;
19265             }
19266
19267             this._execOnAll("unreg", []);
19268
19269             for (var i in this.elementCache) {
19270                 delete this.elementCache[i];
19271             }
19272
19273             this.elementCache = {};
19274             this.ids = {};
19275         },
19276
19277         
19278         elementCache: {},
19279
19280         
19281         getElWrapper: function(id) {
19282             var oWrapper = this.elementCache[id];
19283             if (!oWrapper || !oWrapper.el) {
19284                 oWrapper = this.elementCache[id] =
19285                     new this.ElementWrapper(Ext.getDom(id));
19286             }
19287             return oWrapper;
19288         },
19289
19290         
19291         getElement: function(id) {
19292             return Ext.getDom(id);
19293         },
19294
19295         
19296         getCss: function(id) {
19297             var el = Ext.getDom(id);
19298             return (el) ? el.style : null;
19299         },
19300
19301         
19302         ElementWrapper: function(el) {
19303                 
19304                 this.el = el || null;
19305                 
19306                 this.id = this.el && el.id;
19307                 
19308                 this.css = this.el && el.style;
19309             },
19310
19311         
19312         getPosX: function(el) {
19313             return Ext.lib.Dom.getX(el);
19314         },
19315
19316         
19317         getPosY: function(el) {
19318             return Ext.lib.Dom.getY(el);
19319         },
19320
19321         
19322         swapNode: function(n1, n2) {
19323             if (n1.swapNode) {
19324                 n1.swapNode(n2);
19325             } else {
19326                 var p = n2.parentNode;
19327                 var s = n2.nextSibling;
19328
19329                 if (s == n1) {
19330                     p.insertBefore(n1, n2);
19331                 } else if (n2 == n1.nextSibling) {
19332                     p.insertBefore(n2, n1);
19333                 } else {
19334                     n1.parentNode.replaceChild(n2, n1);
19335                     p.insertBefore(n1, s);
19336                 }
19337             }
19338         },
19339
19340         
19341         getScroll: function () {
19342             var t, l, dde=document.documentElement, db=document.body;
19343             if (dde && (dde.scrollTop || dde.scrollLeft)) {
19344                 t = dde.scrollTop;
19345                 l = dde.scrollLeft;
19346             } else if (db) {
19347                 t = db.scrollTop;
19348                 l = db.scrollLeft;
19349             } else {
19350
19351             }
19352             return { top: t, left: l };
19353         },
19354
19355         
19356         getStyle: function(el, styleProp) {
19357             return Ext.fly(el).getStyle(styleProp);
19358         },
19359
19360         
19361         getScrollTop: function () {
19362             return this.getScroll().top;
19363         },
19364
19365         
19366         getScrollLeft: function () {
19367             return this.getScroll().left;
19368         },
19369
19370         
19371         moveToEl: function (moveEl, targetEl) {
19372             var aCoord = Ext.lib.Dom.getXY(targetEl);
19373             Ext.lib.Dom.setXY(moveEl, aCoord);
19374         },
19375
19376         
19377         numericSort: function(a, b) {
19378             return (a - b);
19379         },
19380
19381         
19382         _timeoutCount: 0,
19383
19384         
19385         _addListeners: function() {
19386             var DDM = Ext.dd.DDM;
19387             if ( Ext.lib.Event && document ) {
19388                 DDM._onLoad();
19389             } else {
19390                 if (DDM._timeoutCount > 2000) {
19391                 } else {
19392                     setTimeout(DDM._addListeners, 10);
19393                     if (document && document.body) {
19394                         DDM._timeoutCount += 1;
19395                     }
19396                 }
19397             }
19398         },
19399
19400         
19401         handleWasClicked: function(node, id) {
19402             if (this.isHandle(id, node.id)) {
19403                 return true;
19404             } else {
19405                 
19406                 var p = node.parentNode;
19407
19408                 while (p) {
19409                     if (this.isHandle(id, p.id)) {
19410                         return true;
19411                     } else {
19412                         p = p.parentNode;
19413                     }
19414                 }
19415             }
19416
19417             return false;
19418         }
19419
19420     };
19421
19422 }();
19423
19424
19425 Ext.dd.DDM = Ext.dd.DragDropMgr;
19426 Ext.dd.DDM._addListeners();
19427
19428 }
19429
19430
19431 Ext.dd.DD = function(id, sGroup, config) {
19432     if (id) {
19433         this.init(id, sGroup, config);
19434     }
19435 };
19436
19437 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
19438
19439     
19440     scroll: true,
19441
19442     
19443     autoOffset: function(iPageX, iPageY) {
19444         var x = iPageX - this.startPageX;
19445         var y = iPageY - this.startPageY;
19446         this.setDelta(x, y);
19447     },
19448
19449     
19450     setDelta: function(iDeltaX, iDeltaY) {
19451         this.deltaX = iDeltaX;
19452         this.deltaY = iDeltaY;
19453     },
19454
19455     
19456     setDragElPos: function(iPageX, iPageY) {
19457         
19458         
19459
19460         var el = this.getDragEl();
19461         this.alignElWithMouse(el, iPageX, iPageY);
19462     },
19463
19464     
19465     alignElWithMouse: function(el, iPageX, iPageY) {
19466         var oCoord = this.getTargetCoord(iPageX, iPageY);
19467         var fly = el.dom ? el : Ext.fly(el, '_dd');
19468         if (!this.deltaSetXY) {
19469             var aCoord = [oCoord.x, oCoord.y];
19470             fly.setXY(aCoord);
19471             var newLeft = fly.getLeft(true);
19472             var newTop  = fly.getTop(true);
19473             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
19474         } else {
19475             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
19476         }
19477
19478         this.cachePosition(oCoord.x, oCoord.y);
19479         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
19480         return oCoord;
19481     },
19482
19483     
19484     cachePosition: function(iPageX, iPageY) {
19485         if (iPageX) {
19486             this.lastPageX = iPageX;
19487             this.lastPageY = iPageY;
19488         } else {
19489             var aCoord = Ext.lib.Dom.getXY(this.getEl());
19490             this.lastPageX = aCoord[0];
19491             this.lastPageY = aCoord[1];
19492         }
19493     },
19494
19495     
19496     autoScroll: function(x, y, h, w) {
19497
19498         if (this.scroll) {
19499             
19500             var clientH = Ext.lib.Dom.getViewHeight();
19501
19502             
19503             var clientW = Ext.lib.Dom.getViewWidth();
19504
19505             
19506             var st = this.DDM.getScrollTop();
19507
19508             
19509             var sl = this.DDM.getScrollLeft();
19510
19511             
19512             var bot = h + y;
19513
19514             
19515             var right = w + x;
19516
19517             
19518             
19519             
19520             var toBot = (clientH + st - y - this.deltaY);
19521
19522             
19523             var toRight = (clientW + sl - x - this.deltaX);
19524
19525
19526             
19527             
19528             var thresh = 40;
19529
19530             
19531             
19532             
19533             var scrAmt = (document.all) ? 80 : 30;
19534
19535             
19536             
19537             if ( bot > clientH && toBot < thresh ) {
19538                 window.scrollTo(sl, st + scrAmt);
19539             }
19540
19541             
19542             
19543             if ( y < st && st > 0 && y - st < thresh ) {
19544                 window.scrollTo(sl, st - scrAmt);
19545             }
19546
19547             
19548             
19549             if ( right > clientW && toRight < thresh ) {
19550                 window.scrollTo(sl + scrAmt, st);
19551             }
19552
19553             
19554             
19555             if ( x < sl && sl > 0 && x - sl < thresh ) {
19556                 window.scrollTo(sl - scrAmt, st);
19557             }
19558         }
19559     },
19560
19561     
19562     getTargetCoord: function(iPageX, iPageY) {
19563         var x = iPageX - this.deltaX;
19564         var y = iPageY - this.deltaY;
19565
19566         if (this.constrainX) {
19567             if (x < this.minX) { x = this.minX; }
19568             if (x > this.maxX) { x = this.maxX; }
19569         }
19570
19571         if (this.constrainY) {
19572             if (y < this.minY) { y = this.minY; }
19573             if (y > this.maxY) { y = this.maxY; }
19574         }
19575
19576         x = this.getTick(x, this.xTicks);
19577         y = this.getTick(y, this.yTicks);
19578
19579
19580         return {x:x, y:y};
19581     },
19582
19583     
19584     applyConfig: function() {
19585         Ext.dd.DD.superclass.applyConfig.call(this);
19586         this.scroll = (this.config.scroll !== false);
19587     },
19588
19589     
19590     b4MouseDown: function(e) {
19591         
19592         this.autoOffset(e.getPageX(),
19593                             e.getPageY());
19594     },
19595
19596     
19597     b4Drag: function(e) {
19598         this.setDragElPos(e.getPageX(),
19599                             e.getPageY());
19600     },
19601
19602     toString: function() {
19603         return ("DD " + this.id);
19604     }
19605
19606     
19607     
19608     
19609     
19610
19611 });
19612
19613 Ext.dd.DDProxy = function(id, sGroup, config) {
19614     if (id) {
19615         this.init(id, sGroup, config);
19616         this.initFrame();
19617     }
19618 };
19619
19620
19621 Ext.dd.DDProxy.dragElId = "ygddfdiv";
19622
19623 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
19624
19625     
19626     resizeFrame: true,
19627
19628     
19629     centerFrame: false,
19630
19631     
19632     createFrame: function() {
19633         var self = this;
19634         var body = document.body;
19635
19636         if (!body || !body.firstChild) {
19637             setTimeout( function() { self.createFrame(); }, 50 );
19638             return;
19639         }
19640
19641         var div = this.getDragEl();
19642
19643         if (!div) {
19644             div    = document.createElement("div");
19645             div.id = this.dragElId;
19646             var s  = div.style;
19647
19648             s.position   = "absolute";
19649             s.visibility = "hidden";
19650             s.cursor     = "move";
19651             s.border     = "2px solid #aaa";
19652             s.zIndex     = 999;
19653
19654             
19655             
19656             
19657             body.insertBefore(div, body.firstChild);
19658         }
19659     },
19660
19661     
19662     initFrame: function() {
19663         this.createFrame();
19664     },
19665
19666     applyConfig: function() {
19667         Ext.dd.DDProxy.superclass.applyConfig.call(this);
19668
19669         this.resizeFrame = (this.config.resizeFrame !== false);
19670         this.centerFrame = (this.config.centerFrame);
19671         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
19672     },
19673
19674     
19675     showFrame: function(iPageX, iPageY) {
19676         var el = this.getEl();
19677         var dragEl = this.getDragEl();
19678         var s = dragEl.style;
19679
19680         this._resizeProxy();
19681
19682         if (this.centerFrame) {
19683             this.setDelta( Math.round(parseInt(s.width,  10)/2),
19684                            Math.round(parseInt(s.height, 10)/2) );
19685         }
19686
19687         this.setDragElPos(iPageX, iPageY);
19688
19689         Ext.fly(dragEl).show();
19690     },
19691
19692     
19693     _resizeProxy: function() {
19694         if (this.resizeFrame) {
19695             var el = this.getEl();
19696             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
19697         }
19698     },
19699
19700     
19701     b4MouseDown: function(e) {
19702         var x = e.getPageX();
19703         var y = e.getPageY();
19704         this.autoOffset(x, y);
19705         this.setDragElPos(x, y);
19706     },
19707
19708     
19709     b4StartDrag: function(x, y) {
19710         
19711         this.showFrame(x, y);
19712     },
19713
19714     
19715     b4EndDrag: function(e) {
19716         Ext.fly(this.getDragEl()).hide();
19717     },
19718
19719     
19720     
19721     
19722     endDrag: function(e) {
19723
19724         var lel = this.getEl();
19725         var del = this.getDragEl();
19726
19727         
19728         del.style.visibility = "";
19729
19730         this.beforeMove();
19731         
19732         
19733         lel.style.visibility = "hidden";
19734         Ext.dd.DDM.moveToEl(lel, del);
19735         del.style.visibility = "hidden";
19736         lel.style.visibility = "";
19737
19738         this.afterDrag();
19739     },
19740
19741     beforeMove : function(){
19742
19743     },
19744
19745     afterDrag : function(){
19746
19747     },
19748
19749     toString: function() {
19750         return ("DDProxy " + this.id);
19751     }
19752
19753 });
19754
19755 Ext.dd.DDTarget = function(id, sGroup, config) {
19756     if (id) {
19757         this.initTarget(id, sGroup, config);
19758     }
19759 };
19760
19761
19762 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
19763     
19764     getDragEl: Ext.emptyFn,
19765     
19766     isValidHandleChild: Ext.emptyFn,
19767     
19768     startDrag: Ext.emptyFn,
19769     
19770     endDrag: Ext.emptyFn,
19771     
19772     onDrag: Ext.emptyFn,
19773     
19774     onDragDrop: Ext.emptyFn,
19775     
19776     onDragEnter: Ext.emptyFn,
19777     
19778     onDragOut: Ext.emptyFn,
19779     
19780     onDragOver: Ext.emptyFn,
19781     
19782     onInvalidDrop: Ext.emptyFn,
19783     
19784     onMouseDown: Ext.emptyFn,
19785     
19786     onMouseUp: Ext.emptyFn,
19787     
19788     setXConstraint: Ext.emptyFn,
19789     
19790     setYConstraint: Ext.emptyFn,
19791     
19792     resetConstraints: Ext.emptyFn,
19793     
19794     clearConstraints: Ext.emptyFn,
19795     
19796     clearTicks: Ext.emptyFn,
19797     
19798     setInitPosition: Ext.emptyFn,
19799     
19800     setDragElId: Ext.emptyFn,
19801     
19802     setHandleElId: Ext.emptyFn,
19803     
19804     setOuterHandleElId: Ext.emptyFn,
19805     
19806     addInvalidHandleClass: Ext.emptyFn,
19807     
19808     addInvalidHandleId: Ext.emptyFn,
19809     
19810     addInvalidHandleType: Ext.emptyFn,
19811     
19812     removeInvalidHandleClass: Ext.emptyFn,
19813     
19814     removeInvalidHandleId: Ext.emptyFn,
19815     
19816     removeInvalidHandleType: Ext.emptyFn,
19817
19818     toString: function() {
19819         return ("DDTarget " + this.id);
19820     }
19821 });
19822 Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
19823         
19824     active: false,
19825         
19826     tolerance: 5,
19827         
19828     autoStart: false,
19829     
19830     constructor : function(config){
19831         Ext.apply(this, config);
19832             this.addEvents(
19833                 
19834                 'mousedown',
19835                 
19836                 'mouseup',
19837                 
19838                 'mousemove',
19839                 
19840                 'dragstart',
19841                 
19842                 'dragend',
19843                 
19844                 'drag'
19845             );
19846         
19847             this.dragRegion = new Ext.lib.Region(0,0,0,0);
19848         
19849             if(this.el){
19850                 this.initEl(this.el);
19851             }
19852         Ext.dd.DragTracker.superclass.constructor.call(this, config);
19853     },
19854
19855     initEl: function(el){
19856         this.el = Ext.get(el);
19857         el.on('mousedown', this.onMouseDown, this,
19858                 this.delegate ? {delegate: this.delegate} : undefined);
19859     },
19860
19861     destroy : function(){
19862         this.el.un('mousedown', this.onMouseDown, this);
19863         delete this.el;
19864     },
19865
19866     onMouseDown: function(e, target){
19867         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
19868             this.startXY = this.lastXY = e.getXY();
19869             this.dragTarget = this.delegate ? target : this.el.dom;
19870             if(this.preventDefault !== false){
19871                 e.preventDefault();
19872             }
19873             var doc = Ext.getDoc();
19874             doc.on('mouseup', this.onMouseUp, this);
19875             doc.on('mousemove', this.onMouseMove, this);
19876             doc.on('selectstart', this.stopSelect, this);
19877             if(this.autoStart){
19878                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
19879             }
19880         }
19881     },
19882
19883     onMouseMove: function(e, target){
19884         
19885         if(this.active && Ext.isIE && !e.browserEvent.button){
19886             e.preventDefault();
19887             this.onMouseUp(e);
19888             return;
19889         }
19890
19891         e.preventDefault();
19892         var xy = e.getXY(), s = this.startXY;
19893         this.lastXY = xy;
19894         if(!this.active){
19895             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
19896                 this.triggerStart();
19897             }else{
19898                 return;
19899             }
19900         }
19901         this.fireEvent('mousemove', this, e);
19902         this.onDrag(e);
19903         this.fireEvent('drag', this, e);
19904     },
19905
19906     onMouseUp: function(e) {
19907         var doc = Ext.getDoc();
19908         doc.un('mousemove', this.onMouseMove, this);
19909         doc.un('mouseup', this.onMouseUp, this);
19910         doc.un('selectstart', this.stopSelect, this);
19911         e.preventDefault();
19912         this.clearStart();
19913         var wasActive = this.active;
19914         this.active = false;
19915         delete this.elRegion;
19916         this.fireEvent('mouseup', this, e);
19917         if(wasActive){
19918             this.onEnd(e);
19919             this.fireEvent('dragend', this, e);
19920         }
19921     },
19922
19923     triggerStart: function(isTimer) {
19924         this.clearStart();
19925         this.active = true;
19926         this.onStart(this.startXY);
19927         this.fireEvent('dragstart', this, this.startXY);
19928     },
19929
19930     clearStart : function() {
19931         if(this.timer){
19932             clearTimeout(this.timer);
19933             delete this.timer;
19934         }
19935     },
19936
19937     stopSelect : function(e) {
19938         e.stopEvent();
19939         return false;
19940     },
19941     
19942     
19943     onBeforeStart : function(e) {
19944
19945     },
19946
19947     
19948     onStart : function(xy) {
19949
19950     },
19951
19952     
19953     onDrag : function(e) {
19954
19955     },
19956
19957     
19958     onEnd : function(e) {
19959
19960     },
19961
19962     
19963     getDragTarget : function(){
19964         return this.dragTarget;
19965     },
19966
19967     getDragCt : function(){
19968         return this.el;
19969     },
19970
19971     getXY : function(constrain){
19972         return constrain ?
19973                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
19974     },
19975
19976     getOffset : function(constrain){
19977         var xy = this.getXY(constrain);
19978         var s = this.startXY;
19979         return [s[0]-xy[0], s[1]-xy[1]];
19980     },
19981
19982     constrainModes: {
19983         'point' : function(xy){
19984
19985             if(!this.elRegion){
19986                 this.elRegion = this.getDragCt().getRegion();
19987             }
19988
19989             var dr = this.dragRegion;
19990
19991             dr.left = xy[0];
19992             dr.top = xy[1];
19993             dr.right = xy[0];
19994             dr.bottom = xy[1];
19995
19996             dr.constrainTo(this.elRegion);
19997
19998             return [dr.left, dr.top];
19999         }
20000     }
20001 });
20002 Ext.dd.ScrollManager = function(){
20003     var ddm = Ext.dd.DragDropMgr;
20004     var els = {};
20005     var dragEl = null;
20006     var proc = {};
20007     
20008     var onStop = function(e){
20009         dragEl = null;
20010         clearProc();
20011     };
20012     
20013     var triggerRefresh = function(){
20014         if(ddm.dragCurrent){
20015              ddm.refreshCache(ddm.dragCurrent.groups);
20016         }
20017     };
20018     
20019     var doScroll = function(){
20020         if(ddm.dragCurrent){
20021             var dds = Ext.dd.ScrollManager;
20022             var inc = proc.el.ddScrollConfig ?
20023                       proc.el.ddScrollConfig.increment : dds.increment;
20024             if(!dds.animate){
20025                 if(proc.el.scroll(proc.dir, inc)){
20026                     triggerRefresh();
20027                 }
20028             }else{
20029                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
20030             }
20031         }
20032     };
20033     
20034     var clearProc = function(){
20035         if(proc.id){
20036             clearInterval(proc.id);
20037         }
20038         proc.id = 0;
20039         proc.el = null;
20040         proc.dir = "";
20041     };
20042     
20043     var startProc = function(el, dir){
20044         clearProc();
20045         proc.el = el;
20046         proc.dir = dir;
20047         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
20048                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
20049         proc.id = setInterval(doScroll, freq);
20050     };
20051     
20052     var onFire = function(e, isDrop){
20053         if(isDrop || !ddm.dragCurrent){ return; }
20054         var dds = Ext.dd.ScrollManager;
20055         if(!dragEl || dragEl != ddm.dragCurrent){
20056             dragEl = ddm.dragCurrent;
20057             
20058             dds.refreshCache();
20059         }
20060         
20061         var xy = Ext.lib.Event.getXY(e);
20062         var pt = new Ext.lib.Point(xy[0], xy[1]);
20063         for(var id in els){
20064             var el = els[id], r = el._region;
20065             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
20066             if(r && r.contains(pt) && el.isScrollable()){
20067                 if(r.bottom - pt.y <= c.vthresh){
20068                     if(proc.el != el){
20069                         startProc(el, "down");
20070                     }
20071                     return;
20072                 }else if(r.right - pt.x <= c.hthresh){
20073                     if(proc.el != el){
20074                         startProc(el, "left");
20075                     }
20076                     return;
20077                 }else if(pt.y - r.top <= c.vthresh){
20078                     if(proc.el != el){
20079                         startProc(el, "up");
20080                     }
20081                     return;
20082                 }else if(pt.x - r.left <= c.hthresh){
20083                     if(proc.el != el){
20084                         startProc(el, "right");
20085                     }
20086                     return;
20087                 }
20088             }
20089         }
20090         clearProc();
20091     };
20092     
20093     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
20094     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
20095     
20096     return {
20097         
20098         register : function(el){
20099             if(Ext.isArray(el)){
20100                 for(var i = 0, len = el.length; i < len; i++) {
20101                         this.register(el[i]);
20102                 }
20103             }else{
20104                 el = Ext.get(el);
20105                 els[el.id] = el;
20106             }
20107         },
20108         
20109         
20110         unregister : function(el){
20111             if(Ext.isArray(el)){
20112                 for(var i = 0, len = el.length; i < len; i++) {
20113                         this.unregister(el[i]);
20114                 }
20115             }else{
20116                 el = Ext.get(el);
20117                 delete els[el.id];
20118             }
20119         },
20120         
20121         
20122         vthresh : 25,
20123         
20124         hthresh : 25,
20125
20126         
20127         increment : 100,
20128         
20129         
20130         frequency : 500,
20131         
20132         
20133         animate: true,
20134         
20135         
20136         animDuration: .4,
20137         
20138         
20139         refreshCache : function(){
20140             for(var id in els){
20141                 if(typeof els[id] == 'object'){ 
20142                     els[id]._region = els[id].getRegion();
20143                 }
20144             }
20145         }
20146     };
20147 }();
20148 Ext.dd.Registry = function(){
20149     var elements = {}; 
20150     var handles = {}; 
20151     var autoIdSeed = 0;
20152
20153     var getId = function(el, autogen){
20154         if(typeof el == "string"){
20155             return el;
20156         }
20157         var id = el.id;
20158         if(!id && autogen !== false){
20159             id = "extdd-" + (++autoIdSeed);
20160             el.id = id;
20161         }
20162         return id;
20163     };
20164     
20165     return {
20166     
20167         register : function(el, data){
20168             data = data || {};
20169             if(typeof el == "string"){
20170                 el = document.getElementById(el);
20171             }
20172             data.ddel = el;
20173             elements[getId(el)] = data;
20174             if(data.isHandle !== false){
20175                 handles[data.ddel.id] = data;
20176             }
20177             if(data.handles){
20178                 var hs = data.handles;
20179                 for(var i = 0, len = hs.length; i < len; i++){
20180                         handles[getId(hs[i])] = data;
20181                 }
20182             }
20183         },
20184
20185     
20186         unregister : function(el){
20187             var id = getId(el, false);
20188             var data = elements[id];
20189             if(data){
20190                 delete elements[id];
20191                 if(data.handles){
20192                     var hs = data.handles;
20193                     for(var i = 0, len = hs.length; i < len; i++){
20194                         delete handles[getId(hs[i], false)];
20195                     }
20196                 }
20197             }
20198         },
20199
20200     
20201         getHandle : function(id){
20202             if(typeof id != "string"){ 
20203                 id = id.id;
20204             }
20205             return handles[id];
20206         },
20207
20208     
20209         getHandleFromEvent : function(e){
20210             var t = Ext.lib.Event.getTarget(e);
20211             return t ? handles[t.id] : null;
20212         },
20213
20214     
20215         getTarget : function(id){
20216             if(typeof id != "string"){ 
20217                 id = id.id;
20218             }
20219             return elements[id];
20220         },
20221
20222     
20223         getTargetFromEvent : function(e){
20224             var t = Ext.lib.Event.getTarget(e);
20225             return t ? elements[t.id] || handles[t.id] : null;
20226         }
20227     };
20228 }();
20229 Ext.dd.StatusProxy = function(config){
20230     Ext.apply(this, config);
20231     this.id = this.id || Ext.id();
20232     this.el = new Ext.Layer({
20233         dh: {
20234             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
20235                 {tag: "div", cls: "x-dd-drop-icon"},
20236                 {tag: "div", cls: "x-dd-drag-ghost"}
20237             ]
20238         }, 
20239         shadow: !config || config.shadow !== false
20240     });
20241     this.ghost = Ext.get(this.el.dom.childNodes[1]);
20242     this.dropStatus = this.dropNotAllowed;
20243 };
20244
20245 Ext.dd.StatusProxy.prototype = {
20246     
20247     dropAllowed : "x-dd-drop-ok",
20248     
20249     dropNotAllowed : "x-dd-drop-nodrop",
20250
20251     
20252     setStatus : function(cssClass){
20253         cssClass = cssClass || this.dropNotAllowed;
20254         if(this.dropStatus != cssClass){
20255             this.el.replaceClass(this.dropStatus, cssClass);
20256             this.dropStatus = cssClass;
20257         }
20258     },
20259
20260     
20261     reset : function(clearGhost){
20262         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
20263         this.dropStatus = this.dropNotAllowed;
20264         if(clearGhost){
20265             this.ghost.update("");
20266         }
20267     },
20268
20269     
20270     update : function(html){
20271         if(typeof html == "string"){
20272             this.ghost.update(html);
20273         }else{
20274             this.ghost.update("");
20275             html.style.margin = "0";
20276             this.ghost.dom.appendChild(html);
20277         }
20278         var el = this.ghost.dom.firstChild; 
20279         if(el){
20280             Ext.fly(el).setStyle('float', 'none');
20281         }
20282     },
20283
20284     
20285     getEl : function(){
20286         return this.el;
20287     },
20288
20289     
20290     getGhost : function(){
20291         return this.ghost;
20292     },
20293
20294     
20295     hide : function(clear){
20296         this.el.hide();
20297         if(clear){
20298             this.reset(true);
20299         }
20300     },
20301
20302     
20303     stop : function(){
20304         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
20305             this.anim.stop();
20306         }
20307     },
20308
20309     
20310     show : function(){
20311         this.el.show();
20312     },
20313
20314     
20315     sync : function(){
20316         this.el.sync();
20317     },
20318
20319     
20320     repair : function(xy, callback, scope){
20321         this.callback = callback;
20322         this.scope = scope;
20323         if(xy && this.animRepair !== false){
20324             this.el.addClass("x-dd-drag-repair");
20325             this.el.hideUnders(true);
20326             this.anim = this.el.shift({
20327                 duration: this.repairDuration || .5,
20328                 easing: 'easeOut',
20329                 xy: xy,
20330                 stopFx: true,
20331                 callback: this.afterRepair,
20332                 scope: this
20333             });
20334         }else{
20335             this.afterRepair();
20336         }
20337     },
20338
20339     
20340     afterRepair : function(){
20341         this.hide(true);
20342         if(typeof this.callback == "function"){
20343             this.callback.call(this.scope || this);
20344         }
20345         this.callback = null;
20346         this.scope = null;
20347     },
20348     
20349     destroy: function(){
20350         Ext.destroy(this.ghost, this.el);    
20351     }
20352 };
20353 Ext.dd.DragSource = function(el, config){
20354     this.el = Ext.get(el);
20355     if(!this.dragData){
20356         this.dragData = {};
20357     }
20358     
20359     Ext.apply(this, config);
20360     
20361     if(!this.proxy){
20362         this.proxy = new Ext.dd.StatusProxy();
20363     }
20364     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
20365           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
20366     
20367     this.dragging = false;
20368 };
20369
20370 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
20371     
20372     
20373     dropAllowed : "x-dd-drop-ok",
20374     
20375     dropNotAllowed : "x-dd-drop-nodrop",
20376
20377     
20378     getDragData : function(e){
20379         return this.dragData;
20380     },
20381
20382     
20383     onDragEnter : function(e, id){
20384         var target = Ext.dd.DragDropMgr.getDDById(id);
20385         this.cachedTarget = target;
20386         if(this.beforeDragEnter(target, e, id) !== false){
20387             if(target.isNotifyTarget){
20388                 var status = target.notifyEnter(this, e, this.dragData);
20389                 this.proxy.setStatus(status);
20390             }else{
20391                 this.proxy.setStatus(this.dropAllowed);
20392             }
20393             
20394             if(this.afterDragEnter){
20395                 
20396                 this.afterDragEnter(target, e, id);
20397             }
20398         }
20399     },
20400
20401     
20402     beforeDragEnter : function(target, e, id){
20403         return true;
20404     },
20405
20406     
20407     alignElWithMouse: function() {
20408         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
20409         this.proxy.sync();
20410     },
20411
20412     
20413     onDragOver : function(e, id){
20414         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20415         if(this.beforeDragOver(target, e, id) !== false){
20416             if(target.isNotifyTarget){
20417                 var status = target.notifyOver(this, e, this.dragData);
20418                 this.proxy.setStatus(status);
20419             }
20420
20421             if(this.afterDragOver){
20422                 
20423                 this.afterDragOver(target, e, id);
20424             }
20425         }
20426     },
20427
20428     
20429     beforeDragOver : function(target, e, id){
20430         return true;
20431     },
20432
20433     
20434     onDragOut : function(e, id){
20435         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20436         if(this.beforeDragOut(target, e, id) !== false){
20437             if(target.isNotifyTarget){
20438                 target.notifyOut(this, e, this.dragData);
20439             }
20440             this.proxy.reset();
20441             if(this.afterDragOut){
20442                 
20443                 this.afterDragOut(target, e, id);
20444             }
20445         }
20446         this.cachedTarget = null;
20447     },
20448
20449     
20450     beforeDragOut : function(target, e, id){
20451         return true;
20452     },
20453     
20454     
20455     onDragDrop : function(e, id){
20456         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
20457         if(this.beforeDragDrop(target, e, id) !== false){
20458             if(target.isNotifyTarget){
20459                 if(target.notifyDrop(this, e, this.dragData)){ 
20460                     this.onValidDrop(target, e, id);
20461                 }else{
20462                     this.onInvalidDrop(target, e, id);
20463                 }
20464             }else{
20465                 this.onValidDrop(target, e, id);
20466             }
20467             
20468             if(this.afterDragDrop){
20469                 
20470                 this.afterDragDrop(target, e, id);
20471             }
20472         }
20473         delete this.cachedTarget;
20474     },
20475
20476     
20477     beforeDragDrop : function(target, e, id){
20478         return true;
20479     },
20480
20481     
20482     onValidDrop : function(target, e, id){
20483         this.hideProxy();
20484         if(this.afterValidDrop){
20485             
20486             this.afterValidDrop(target, e, id);
20487         }
20488     },
20489
20490     
20491     getRepairXY : function(e, data){
20492         return this.el.getXY();  
20493     },
20494
20495     
20496     onInvalidDrop : function(target, e, id){
20497         this.beforeInvalidDrop(target, e, id);
20498         if(this.cachedTarget){
20499             if(this.cachedTarget.isNotifyTarget){
20500                 this.cachedTarget.notifyOut(this, e, this.dragData);
20501             }
20502             this.cacheTarget = null;
20503         }
20504         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
20505
20506         if(this.afterInvalidDrop){
20507             
20508             this.afterInvalidDrop(e, id);
20509         }
20510     },
20511
20512     
20513     afterRepair : function(){
20514         if(Ext.enableFx){
20515             this.el.highlight(this.hlColor || "c3daf9");
20516         }
20517         this.dragging = false;
20518     },
20519
20520     
20521     beforeInvalidDrop : function(target, e, id){
20522         return true;
20523     },
20524
20525     
20526     handleMouseDown : function(e){
20527         if(this.dragging) {
20528             return;
20529         }
20530         var data = this.getDragData(e);
20531         if(data && this.onBeforeDrag(data, e) !== false){
20532             this.dragData = data;
20533             this.proxy.stop();
20534             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
20535         } 
20536     },
20537
20538     
20539     onBeforeDrag : function(data, e){
20540         return true;
20541     },
20542
20543     
20544     onStartDrag : Ext.emptyFn,
20545
20546     
20547     startDrag : function(x, y){
20548         this.proxy.reset();
20549         this.dragging = true;
20550         this.proxy.update("");
20551         this.onInitDrag(x, y);
20552         this.proxy.show();
20553     },
20554
20555     
20556     onInitDrag : function(x, y){
20557         var clone = this.el.dom.cloneNode(true);
20558         clone.id = Ext.id(); 
20559         this.proxy.update(clone);
20560         this.onStartDrag(x, y);
20561         return true;
20562     },
20563
20564     
20565     getProxy : function(){
20566         return this.proxy;  
20567     },
20568
20569     
20570     hideProxy : function(){
20571         this.proxy.hide();  
20572         this.proxy.reset(true);
20573         this.dragging = false;
20574     },
20575
20576     
20577     triggerCacheRefresh : function(){
20578         Ext.dd.DDM.refreshCache(this.groups);
20579     },
20580
20581     
20582     b4EndDrag: function(e) {
20583     },
20584
20585     
20586     endDrag : function(e){
20587         this.onEndDrag(this.dragData, e);
20588     },
20589
20590     
20591     onEndDrag : function(data, e){
20592     },
20593     
20594     
20595     autoOffset : function(x, y) {
20596         this.setDelta(-12, -20);
20597     },
20598     
20599     destroy: function(){
20600         Ext.dd.DragSource.superclass.destroy.call(this);
20601         Ext.destroy(this.proxy);
20602     }
20603 });
20604 Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
20605     
20606     constructor : function(el, config){
20607         this.el = Ext.get(el);
20608     
20609         Ext.apply(this, config);
20610     
20611         if(this.containerScroll){
20612             Ext.dd.ScrollManager.register(this.el);
20613         }
20614     
20615         Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
20616               {isTarget: true});        
20617     },
20618     
20619     
20620     
20621     
20622     dropAllowed : "x-dd-drop-ok",
20623     
20624     dropNotAllowed : "x-dd-drop-nodrop",
20625
20626     
20627     isTarget : true,
20628
20629     
20630     isNotifyTarget : true,
20631
20632     
20633     notifyEnter : function(dd, e, data){
20634         if(this.overClass){
20635             this.el.addClass(this.overClass);
20636         }
20637         return this.dropAllowed;
20638     },
20639
20640     
20641     notifyOver : function(dd, e, data){
20642         return this.dropAllowed;
20643     },
20644
20645     
20646     notifyOut : function(dd, e, data){
20647         if(this.overClass){
20648             this.el.removeClass(this.overClass);
20649         }
20650     },
20651
20652     
20653     notifyDrop : function(dd, e, data){
20654         return false;
20655     },
20656     
20657     destroy : function(){
20658         Ext.dd.DropTarget.superclass.destroy.call(this);
20659         if(this.containerScroll){
20660             Ext.dd.ScrollManager.unregister(this.el);
20661         }
20662     }
20663 });
20664 Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
20665     
20666     constructor : function(el, config){
20667         Ext.dd.DragZone.superclass.constructor.call(this, el, config);
20668         if(this.containerScroll){
20669             Ext.dd.ScrollManager.register(this.el);
20670         }
20671     },
20672     
20673     
20674     
20675     
20676
20677     
20678     getDragData : function(e){
20679         return Ext.dd.Registry.getHandleFromEvent(e);
20680     },
20681     
20682     
20683     onInitDrag : function(x, y){
20684         this.proxy.update(this.dragData.ddel.cloneNode(true));
20685         this.onStartDrag(x, y);
20686         return true;
20687     },
20688     
20689     
20690     afterRepair : function(){
20691         if(Ext.enableFx){
20692             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
20693         }
20694         this.dragging = false;
20695     },
20696
20697     
20698     getRepairXY : function(e){
20699         return Ext.Element.fly(this.dragData.ddel).getXY();  
20700     },
20701     
20702     destroy : function(){
20703         Ext.dd.DragZone.superclass.destroy.call(this);
20704         if(this.containerScroll){
20705             Ext.dd.ScrollManager.unregister(this.el);
20706         }
20707     }
20708 });
20709 Ext.dd.DropZone = function(el, config){
20710     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
20711 };
20712
20713 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
20714     
20715     getTargetFromEvent : function(e){
20716         return Ext.dd.Registry.getTargetFromEvent(e);
20717     },
20718
20719     
20720     onNodeEnter : function(n, dd, e, data){
20721         
20722     },
20723
20724     
20725     onNodeOver : function(n, dd, e, data){
20726         return this.dropAllowed;
20727     },
20728
20729     
20730     onNodeOut : function(n, dd, e, data){
20731         
20732     },
20733
20734     
20735     onNodeDrop : function(n, dd, e, data){
20736         return false;
20737     },
20738
20739     
20740     onContainerOver : function(dd, e, data){
20741         return this.dropNotAllowed;
20742     },
20743
20744     
20745     onContainerDrop : function(dd, e, data){
20746         return false;
20747     },
20748
20749     
20750     notifyEnter : function(dd, e, data){
20751         return this.dropNotAllowed;
20752     },
20753
20754     
20755     notifyOver : function(dd, e, data){
20756         var n = this.getTargetFromEvent(e);
20757         if(!n){ 
20758             if(this.lastOverNode){
20759                 this.onNodeOut(this.lastOverNode, dd, e, data);
20760                 this.lastOverNode = null;
20761             }
20762             return this.onContainerOver(dd, e, data);
20763         }
20764         if(this.lastOverNode != n){
20765             if(this.lastOverNode){
20766                 this.onNodeOut(this.lastOverNode, dd, e, data);
20767             }
20768             this.onNodeEnter(n, dd, e, data);
20769             this.lastOverNode = n;
20770         }
20771         return this.onNodeOver(n, dd, e, data);
20772     },
20773
20774     
20775     notifyOut : function(dd, e, data){
20776         if(this.lastOverNode){
20777             this.onNodeOut(this.lastOverNode, dd, e, data);
20778             this.lastOverNode = null;
20779         }
20780     },
20781
20782     
20783     notifyDrop : function(dd, e, data){
20784         if(this.lastOverNode){
20785             this.onNodeOut(this.lastOverNode, dd, e, data);
20786             this.lastOverNode = null;
20787         }
20788         var n = this.getTargetFromEvent(e);
20789         return n ?
20790             this.onNodeDrop(n, dd, e, data) :
20791             this.onContainerDrop(dd, e, data);
20792     },
20793
20794     
20795     triggerCacheRefresh : function(){
20796         Ext.dd.DDM.refreshCache(this.groups);
20797     }  
20798 });
20799 Ext.Element.addMethods({
20800     
20801     initDD : function(group, config, overrides){
20802         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
20803         return Ext.apply(dd, overrides);
20804     },
20805
20806     
20807     initDDProxy : function(group, config, overrides){
20808         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
20809         return Ext.apply(dd, overrides);
20810     },
20811
20812     
20813     initDDTarget : function(group, config, overrides){
20814         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
20815         return Ext.apply(dd, overrides);
20816     }
20817 });
20818
20819 Ext.data.Api = (function() {
20820
20821     
20822     
20823     
20824     
20825     var validActions = {};
20826
20827     return {
20828         
20829         actions : {
20830             create  : 'create',
20831             read    : 'read',
20832             update  : 'update',
20833             destroy : 'destroy'
20834         },
20835
20836         
20837         restActions : {
20838             create  : 'POST',
20839             read    : 'GET',
20840             update  : 'PUT',
20841             destroy : 'DELETE'
20842         },
20843
20844         
20845         isAction : function(action) {
20846             return (Ext.data.Api.actions[action]) ? true : false;
20847         },
20848
20849         
20850         getVerb : function(name) {
20851             if (validActions[name]) {
20852                 return validActions[name];  
20853             }
20854             for (var verb in this.actions) {
20855                 if (this.actions[verb] === name) {
20856                     validActions[name] = verb;
20857                     break;
20858                 }
20859             }
20860             return (validActions[name] !== undefined) ? validActions[name] : null;
20861         },
20862
20863         
20864         isValid : function(api){
20865             var invalid = [];
20866             var crud = this.actions; 
20867             for (var action in api) {
20868                 if (!(action in crud)) {
20869                     invalid.push(action);
20870                 }
20871             }
20872             return (!invalid.length) ? true : invalid;
20873         },
20874
20875         
20876         hasUniqueUrl : function(proxy, verb) {
20877             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
20878             var unique = true;
20879             for (var action in proxy.api) {
20880                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
20881                     break;
20882                 }
20883             }
20884             return unique;
20885         },
20886
20887         
20888         prepare : function(proxy) {
20889             if (!proxy.api) {
20890                 proxy.api = {}; 
20891             }
20892             for (var verb in this.actions) {
20893                 var action = this.actions[verb];
20894                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
20895                 if (typeof(proxy.api[action]) == 'string') {
20896                     proxy.api[action] = {
20897                         url: proxy.api[action],
20898                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
20899                     };
20900                 }
20901             }
20902         },
20903
20904         
20905         restify : function(proxy) {
20906             proxy.restful = true;
20907             for (var verb in this.restActions) {
20908                 proxy.api[this.actions[verb]].method ||
20909                     (proxy.api[this.actions[verb]].method = this.restActions[verb]);
20910             }
20911             
20912             
20913             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
20914                 var reader = o.reader;
20915                 var res = new Ext.data.Response({
20916                     action: action,
20917                     raw: response
20918                 });
20919
20920                 switch (response.status) {
20921                     case 200:   
20922                         return true;
20923                         break;
20924                     case 201:   
20925                         if (Ext.isEmpty(res.raw.responseText)) {
20926                           res.success = true;
20927                         } else {
20928                           
20929                           return true;
20930                         }
20931                         break;
20932                     case 204:  
20933                         res.success = true;
20934                         res.data = null;
20935                         break;
20936                     default:
20937                         return true;
20938                         break;
20939                 }
20940                 if (res.success === true) {
20941                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
20942                 } else {
20943                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
20944                 }
20945                 o.request.callback.call(o.request.scope, res.data, res, res.success);
20946
20947                 return false;   
20948             }, proxy);
20949         }
20950     };
20951 })();
20952
20953
20954 Ext.data.Response = function(params, response) {
20955     Ext.apply(this, params, {
20956         raw: response
20957     });
20958 };
20959 Ext.data.Response.prototype = {
20960     message : null,
20961     success : false,
20962     status : null,
20963     root : null,
20964     raw : null,
20965
20966     getMessage : function() {
20967         return this.message;
20968     },
20969     getSuccess : function() {
20970         return this.success;
20971     },
20972     getStatus : function() {
20973         return this.status;
20974     },
20975     getRoot : function() {
20976         return this.root;
20977     },
20978     getRawResponse : function() {
20979         return this.raw;
20980     }
20981 };
20982
20983
20984 Ext.data.Api.Error = Ext.extend(Ext.Error, {
20985     constructor : function(message, arg) {
20986         this.arg = arg;
20987         Ext.Error.call(this, message);
20988     },
20989     name: 'Ext.data.Api'
20990 });
20991 Ext.apply(Ext.data.Api.Error.prototype, {
20992     lang: {
20993         '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.',
20994         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
20995         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
20996         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
20997     }
20998 });
20999
21000
21001
21002
21003 Ext.data.SortTypes = {
21004     
21005     none : function(s){
21006         return s;
21007     },
21008     
21009     
21010     stripTagsRE : /<\/?[^>]+>/gi,
21011     
21012     
21013     asText : function(s){
21014         return String(s).replace(this.stripTagsRE, "");
21015     },
21016     
21017     
21018     asUCText : function(s){
21019         return String(s).toUpperCase().replace(this.stripTagsRE, "");
21020     },
21021     
21022     
21023     asUCString : function(s) {
21024         return String(s).toUpperCase();
21025     },
21026     
21027     
21028     asDate : function(s) {
21029         if(!s){
21030             return 0;
21031         }
21032         if(Ext.isDate(s)){
21033             return s.getTime();
21034         }
21035         return Date.parse(String(s));
21036     },
21037     
21038     
21039     asFloat : function(s) {
21040         var val = parseFloat(String(s).replace(/,/g, ""));
21041         return isNaN(val) ? 0 : val;
21042     },
21043     
21044     
21045     asInt : function(s) {
21046         var val = parseInt(String(s).replace(/,/g, ""), 10);
21047         return isNaN(val) ? 0 : val;
21048     }
21049 };
21050 Ext.data.Record = function(data, id){
21051     
21052     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
21053     this.data = data || {};
21054 };
21055
21056
21057 Ext.data.Record.create = function(o){
21058     var f = Ext.extend(Ext.data.Record, {});
21059     var p = f.prototype;
21060     p.fields = new Ext.util.MixedCollection(false, function(field){
21061         return field.name;
21062     });
21063     for(var i = 0, len = o.length; i < len; i++){
21064         p.fields.add(new Ext.data.Field(o[i]));
21065     }
21066     f.getField = function(name){
21067         return p.fields.get(name);
21068     };
21069     return f;
21070 };
21071
21072 Ext.data.Record.PREFIX = 'ext-record';
21073 Ext.data.Record.AUTO_ID = 1;
21074 Ext.data.Record.EDIT = 'edit';
21075 Ext.data.Record.REJECT = 'reject';
21076 Ext.data.Record.COMMIT = 'commit';
21077
21078
21079
21080 Ext.data.Record.id = function(rec) {
21081     rec.phantom = true;
21082     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
21083 };
21084
21085 Ext.data.Record.prototype = {
21086     
21087     
21088     
21089     
21090     
21091     
21092     dirty : false,
21093     editing : false,
21094     error : null,
21095     
21096     modified : null,
21097     
21098     phantom : false,
21099
21100     
21101     join : function(store){
21102         
21103         this.store = store;
21104     },
21105
21106     
21107     set : function(name, value){
21108         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
21109         if(encode(this.data[name]) == encode(value)) {
21110             return;
21111         }        
21112         this.dirty = true;
21113         if(!this.modified){
21114             this.modified = {};
21115         }
21116         if(this.modified[name] === undefined){
21117             this.modified[name] = this.data[name];
21118         }
21119         this.data[name] = value;
21120         if(!this.editing){
21121             this.afterEdit();
21122         }
21123     },
21124
21125     
21126     afterEdit : function(){
21127         if (this.store != undefined && typeof this.store.afterEdit == "function") {
21128             this.store.afterEdit(this);
21129         }
21130     },
21131
21132     
21133     afterReject : function(){
21134         if(this.store){
21135             this.store.afterReject(this);
21136         }
21137     },
21138
21139     
21140     afterCommit : function(){
21141         if(this.store){
21142             this.store.afterCommit(this);
21143         }
21144     },
21145
21146     
21147     get : function(name){
21148         return this.data[name];
21149     },
21150
21151     
21152     beginEdit : function(){
21153         this.editing = true;
21154         this.modified = this.modified || {};
21155     },
21156
21157     
21158     cancelEdit : function(){
21159         this.editing = false;
21160         delete this.modified;
21161     },
21162
21163     
21164     endEdit : function(){
21165         this.editing = false;
21166         if(this.dirty){
21167             this.afterEdit();
21168         }
21169     },
21170
21171     
21172     reject : function(silent){
21173         var m = this.modified;
21174         for(var n in m){
21175             if(typeof m[n] != "function"){
21176                 this.data[n] = m[n];
21177             }
21178         }
21179         this.dirty = false;
21180         delete this.modified;
21181         this.editing = false;
21182         if(silent !== true){
21183             this.afterReject();
21184         }
21185     },
21186
21187     
21188     commit : function(silent){
21189         this.dirty = false;
21190         delete this.modified;
21191         this.editing = false;
21192         if(silent !== true){
21193             this.afterCommit();
21194         }
21195     },
21196
21197     
21198     getChanges : function(){
21199         var m = this.modified, cs = {};
21200         for(var n in m){
21201             if(m.hasOwnProperty(n)){
21202                 cs[n] = this.data[n];
21203             }
21204         }
21205         return cs;
21206     },
21207
21208     
21209     hasError : function(){
21210         return this.error !== null;
21211     },
21212
21213     
21214     clearError : function(){
21215         this.error = null;
21216     },
21217
21218     
21219     copy : function(newId) {
21220         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
21221     },
21222
21223     
21224     isModified : function(fieldName){
21225         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
21226     },
21227
21228     
21229     isValid : function() {
21230         return this.fields.find(function(f) {
21231             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
21232         },this) ? false : true;
21233     },
21234
21235     
21236     markDirty : function(){
21237         this.dirty = true;
21238         if(!this.modified){
21239             this.modified = {};
21240         }
21241         this.fields.each(function(f) {
21242             this.modified[f.name] = this.data[f.name];
21243         },this);
21244     }
21245 };
21246
21247 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
21248     
21249
21250     
21251     register : function(){
21252         for(var i = 0, s; (s = arguments[i]); i++){
21253             this.add(s);
21254         }
21255     },
21256
21257     
21258     unregister : function(){
21259         for(var i = 0, s; (s = arguments[i]); i++){
21260             this.remove(this.lookup(s));
21261         }
21262     },
21263
21264     
21265     lookup : function(id){
21266         if(Ext.isArray(id)){
21267             var fields = ['field1'], expand = !Ext.isArray(id[0]);
21268             if(!expand){
21269                 for(var i = 2, len = id[0].length; i <= len; ++i){
21270                     fields.push('field' + i);
21271                 }
21272             }
21273             return new Ext.data.ArrayStore({
21274                 fields: fields,
21275                 data: id,
21276                 expandData: expand,
21277                 autoDestroy: true,
21278                 autoCreated: true
21279
21280             });
21281         }
21282         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
21283     },
21284
21285     
21286     getKey : function(o){
21287          return o.storeId;
21288     }
21289 });
21290 Ext.data.Store = Ext.extend(Ext.util.Observable, {
21291     
21292     
21293     
21294     
21295     
21296     
21297     
21298     writer : undefined,
21299     
21300     
21301     
21302     remoteSort : false,
21303
21304     
21305     autoDestroy : false,
21306
21307     
21308     pruneModifiedRecords : false,
21309
21310     
21311     lastOptions : null,
21312
21313     
21314     autoSave : true,
21315
21316     
21317     batch : true,
21318
21319     
21320     restful: false,
21321
21322     
21323     paramNames : undefined,
21324
21325     
21326     defaultParamNames : {
21327         start : 'start',
21328         limit : 'limit',
21329         sort : 'sort',
21330         dir : 'dir'
21331     },
21332
21333     
21334     isDestroyed: false,
21335
21336     
21337     hasMultiSort: false,
21338
21339     
21340     batchKey : '_ext_batch_',
21341
21342     constructor : function(config){
21343         this.data = new Ext.util.MixedCollection(false);
21344         this.data.getKey = function(o){
21345             return o.id;
21346         };
21347
21348
21349         
21350         this.removed = [];
21351
21352         if(config && config.data){
21353             this.inlineData = config.data;
21354             delete config.data;
21355         }
21356
21357         Ext.apply(this, config);
21358
21359         
21360         this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
21361
21362         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
21363
21364         if((this.url || this.api) && !this.proxy){
21365             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
21366         }
21367         
21368         if (this.restful === true && this.proxy) {
21369             
21370             
21371             this.batch = false;
21372             Ext.data.Api.restify(this.proxy);
21373         }
21374
21375         if(this.reader){ 
21376             if(!this.recordType){
21377                 this.recordType = this.reader.recordType;
21378             }
21379             if(this.reader.onMetaChange){
21380                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
21381             }
21382             if (this.writer) { 
21383                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
21384                     this.writer = this.buildWriter(this.writer);
21385                 }
21386                 this.writer.meta = this.reader.meta;
21387                 this.pruneModifiedRecords = true;
21388             }
21389         }
21390
21391         
21392
21393         if(this.recordType){
21394             
21395             this.fields = this.recordType.prototype.fields;
21396         }
21397         this.modified = [];
21398
21399         this.addEvents(
21400             
21401             'datachanged',
21402             
21403             'metachange',
21404             
21405             'add',
21406             
21407             'remove',
21408             
21409             'update',
21410             
21411             'clear',
21412             
21413             'exception',
21414             
21415             'beforeload',
21416             
21417             'load',
21418             
21419             'loadexception',
21420             
21421             'beforewrite',
21422             
21423             'write',
21424             
21425             'beforesave',
21426             
21427             'save'
21428
21429         );
21430
21431         if(this.proxy){
21432             
21433             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
21434         }
21435         
21436         if (this.writer) {
21437             this.on({
21438                 scope: this,
21439                 add: this.createRecords,
21440                 remove: this.destroyRecord,
21441                 update: this.updateRecord,
21442                 clear: this.onClear
21443             });
21444         }
21445
21446         this.sortToggle = {};
21447         if(this.sortField){
21448             this.setDefaultSort(this.sortField, this.sortDir);
21449         }else if(this.sortInfo){
21450             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
21451         }
21452
21453         Ext.data.Store.superclass.constructor.call(this);
21454
21455         if(this.id){
21456             this.storeId = this.id;
21457             delete this.id;
21458         }
21459         if(this.storeId){
21460             Ext.StoreMgr.register(this);
21461         }
21462         if(this.inlineData){
21463             this.loadData(this.inlineData);
21464             delete this.inlineData;
21465         }else if(this.autoLoad){
21466             this.load.defer(10, this, [
21467                 typeof this.autoLoad == 'object' ?
21468                     this.autoLoad : undefined]);
21469         }
21470         
21471         this.batchCounter = 0;
21472         this.batches = {};
21473     },
21474
21475     
21476     buildWriter : function(config) {
21477         var klass = undefined,
21478             type = (config.format || 'json').toLowerCase();
21479         switch (type) {
21480             case 'json':
21481                 klass = Ext.data.JsonWriter;
21482                 break;
21483             case 'xml':
21484                 klass = Ext.data.XmlWriter;
21485                 break;
21486             default:
21487                 klass = Ext.data.JsonWriter;
21488         }
21489         return new klass(config);
21490     },
21491
21492     
21493     destroy : function(){
21494         if(!this.isDestroyed){
21495             if(this.storeId){
21496                 Ext.StoreMgr.unregister(this);
21497             }
21498             this.clearData();
21499             this.data = null;
21500             Ext.destroy(this.proxy);
21501             this.reader = this.writer = null;
21502             this.purgeListeners();
21503             this.isDestroyed = true;
21504         }
21505     },
21506
21507     
21508     add : function(records){
21509         records = [].concat(records);
21510         if(records.length < 1){
21511             return;
21512         }
21513         for(var i = 0, len = records.length; i < len; i++){
21514             records[i].join(this);
21515         }
21516         var index = this.data.length;
21517         this.data.addAll(records);
21518         if(this.snapshot){
21519             this.snapshot.addAll(records);
21520         }
21521         this.fireEvent('add', this, records, index);
21522     },
21523
21524     
21525     addSorted : function(record){
21526         var index = this.findInsertIndex(record);
21527         this.insert(index, record);
21528     },
21529
21530     
21531     remove : function(record){
21532         if(Ext.isArray(record)){
21533             Ext.each(record, function(r){
21534                 this.remove(r);
21535             }, this);
21536             return;
21537         }
21538         var index = this.data.indexOf(record);
21539         if(index > -1){
21540             record.join(null);
21541             this.data.removeAt(index);
21542         }
21543         if(this.pruneModifiedRecords){
21544             this.modified.remove(record);
21545         }
21546         if(this.snapshot){
21547             this.snapshot.remove(record);
21548         }
21549         if(index > -1){
21550             this.fireEvent('remove', this, record, index);
21551         }
21552     },
21553
21554     
21555     removeAt : function(index){
21556         this.remove(this.getAt(index));
21557     },
21558
21559     
21560     removeAll : function(silent){
21561         var items = [];
21562         this.each(function(rec){
21563             items.push(rec);
21564         });
21565         this.clearData();
21566         if(this.snapshot){
21567             this.snapshot.clear();
21568         }
21569         if(this.pruneModifiedRecords){
21570             this.modified = [];
21571         }
21572         if (silent !== true) {  
21573             this.fireEvent('clear', this, items);
21574         }
21575     },
21576
21577     
21578     onClear: function(store, records){
21579         Ext.each(records, function(rec, index){
21580             this.destroyRecord(this, rec, index);
21581         }, this);
21582     },
21583
21584     
21585     insert : function(index, records){
21586         records = [].concat(records);
21587         for(var i = 0, len = records.length; i < len; i++){
21588             this.data.insert(index, records[i]);
21589             records[i].join(this);
21590         }
21591         if(this.snapshot){
21592             this.snapshot.addAll(records);
21593         }
21594         this.fireEvent('add', this, records, index);
21595     },
21596
21597     
21598     indexOf : function(record){
21599         return this.data.indexOf(record);
21600     },
21601
21602     
21603     indexOfId : function(id){
21604         return this.data.indexOfKey(id);
21605     },
21606
21607     
21608     getById : function(id){
21609         return (this.snapshot || this.data).key(id);
21610     },
21611
21612     
21613     getAt : function(index){
21614         return this.data.itemAt(index);
21615     },
21616
21617     
21618     getRange : function(start, end){
21619         return this.data.getRange(start, end);
21620     },
21621
21622     
21623     storeOptions : function(o){
21624         o = Ext.apply({}, o);
21625         delete o.callback;
21626         delete o.scope;
21627         this.lastOptions = o;
21628     },
21629
21630     
21631     clearData: function(){
21632         this.data.each(function(rec) {
21633             rec.join(null);
21634         });
21635         this.data.clear();
21636     },
21637
21638     
21639     load : function(options) {
21640         options = Ext.apply({}, options);
21641         this.storeOptions(options);
21642         if(this.sortInfo && this.remoteSort){
21643             var pn = this.paramNames;
21644             options.params = Ext.apply({}, options.params);
21645             options.params[pn.sort] = this.sortInfo.field;
21646             options.params[pn.dir] = this.sortInfo.direction;
21647         }
21648         try {
21649             return this.execute('read', null, options); 
21650         } catch(e) {
21651             this.handleException(e);
21652             return false;
21653         }
21654     },
21655
21656     
21657     updateRecord : function(store, record, action) {
21658         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
21659             this.save();
21660         }
21661     },
21662
21663     
21664     createRecords : function(store, rs, index) {
21665         for (var i = 0, len = rs.length; i < len; i++) {
21666             if (rs[i].phantom && rs[i].isValid()) {
21667                 rs[i].markDirty();  
21668                 this.modified.push(rs[i]);  
21669             }
21670         }
21671         if (this.autoSave === true) {
21672             this.save();
21673         }
21674     },
21675
21676     
21677     destroyRecord : function(store, record, index) {
21678         if (this.modified.indexOf(record) != -1) {  
21679             this.modified.remove(record);
21680         }
21681         if (!record.phantom) {
21682             this.removed.push(record);
21683
21684             
21685             
21686             
21687             record.lastIndex = index;
21688
21689             if (this.autoSave === true) {
21690                 this.save();
21691             }
21692         }
21693     },
21694
21695     
21696     execute : function(action, rs, options,  batch) {
21697         
21698         if (!Ext.data.Api.isAction(action)) {
21699             throw new Ext.data.Api.Error('execute', action);
21700         }
21701         
21702         options = Ext.applyIf(options||{}, {
21703             params: {}
21704         });
21705         if(batch !== undefined){
21706             this.addToBatch(batch);
21707         }
21708         
21709         
21710         var doRequest = true;
21711
21712         if (action === 'read') {
21713             doRequest = this.fireEvent('beforeload', this, options);
21714             Ext.applyIf(options.params, this.baseParams);
21715         }
21716         else {
21717             
21718             
21719             if (this.writer.listful === true && this.restful !== true) {
21720                 rs = (Ext.isArray(rs)) ? rs : [rs];
21721             }
21722             
21723             else if (Ext.isArray(rs) && rs.length == 1) {
21724                 rs = rs.shift();
21725             }
21726             
21727             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
21728                 this.writer.apply(options.params, this.baseParams, action, rs);
21729             }
21730         }
21731         if (doRequest !== false) {
21732             
21733             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
21734                 options.params.xaction = action;    
21735             }
21736             
21737             
21738             
21739             
21740             
21741             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
21742         }
21743         return doRequest;
21744     },
21745
21746     
21747     save : function() {
21748         if (!this.writer) {
21749             throw new Ext.data.Store.Error('writer-undefined');
21750         }
21751
21752         var queue = [],
21753             len,
21754             trans,
21755             batch,
21756             data = {};
21757         
21758         if(this.removed.length){
21759             queue.push(['destroy', this.removed]);
21760         }
21761
21762         
21763         var rs = [].concat(this.getModifiedRecords());
21764         if(rs.length){
21765             
21766             var phantoms = [];
21767             for(var i = rs.length-1; i >= 0; i--){
21768                 if(rs[i].phantom === true){
21769                     var rec = rs.splice(i, 1).shift();
21770                     if(rec.isValid()){
21771                         phantoms.push(rec);
21772                     }
21773                 }else if(!rs[i].isValid()){ 
21774                     rs.splice(i,1);
21775                 }
21776             }
21777             
21778             if(phantoms.length){
21779                 queue.push(['create', phantoms]);
21780             }
21781
21782             
21783             if(rs.length){
21784                 queue.push(['update', rs]);
21785             }
21786         }
21787         len = queue.length;
21788         if(len){
21789             batch = ++this.batchCounter;
21790             for(var i = 0; i < len; ++i){
21791                 trans = queue[i];
21792                 data[trans[0]] = trans[1];
21793             }
21794             if(this.fireEvent('beforesave', this, data) !== false){
21795                 for(var i = 0; i < len; ++i){
21796                     trans = queue[i];
21797                     this.doTransaction(trans[0], trans[1], batch);
21798                 }
21799                 return batch;
21800             }
21801         }
21802         return -1;
21803     },
21804
21805     
21806     doTransaction : function(action, rs, batch) {
21807         function transaction(records) {
21808             try{
21809                 this.execute(action, records, undefined, batch);
21810             }catch (e){
21811                 this.handleException(e);
21812             }
21813         }
21814         if(this.batch === false){
21815             for(var i = 0, len = rs.length; i < len; i++){
21816                 transaction.call(this, rs[i]);
21817             }
21818         }else{
21819             transaction.call(this, rs);
21820         }
21821     },
21822
21823     
21824     addToBatch : function(batch){
21825         var b = this.batches,
21826             key = this.batchKey + batch,
21827             o = b[key];
21828
21829         if(!o){
21830             b[key] = o = {
21831                 id: batch,
21832                 count: 0,
21833                 data: {}
21834             };
21835         }
21836         ++o.count;
21837     },
21838
21839     removeFromBatch : function(batch, action, data){
21840         var b = this.batches,
21841             key = this.batchKey + batch,
21842             o = b[key],
21843             data,
21844             arr;
21845
21846
21847         if(o){
21848             arr = o.data[action] || [];
21849             o.data[action] = arr.concat(data);
21850             if(o.count === 1){
21851                 data = o.data;
21852                 delete b[key];
21853                 this.fireEvent('save', this, batch, data);
21854             }else{
21855                 --o.count;
21856             }
21857         }
21858     },
21859
21860     
21861     
21862     createCallback : function(action, rs, batch) {
21863         var actions = Ext.data.Api.actions;
21864         return (action == 'read') ? this.loadRecords : function(data, response, success) {
21865             
21866             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
21867             
21868             if (success === true) {
21869                 this.fireEvent('write', this, action, data, response, rs);
21870             }
21871             this.removeFromBatch(batch, action, data);
21872         };
21873     },
21874
21875     
21876     
21877     
21878     clearModified : function(rs) {
21879         if (Ext.isArray(rs)) {
21880             for (var n=rs.length-1;n>=0;n--) {
21881                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
21882             }
21883         } else {
21884             this.modified.splice(this.modified.indexOf(rs), 1);
21885         }
21886     },
21887
21888     
21889     reMap : function(record) {
21890         if (Ext.isArray(record)) {
21891             for (var i = 0, len = record.length; i < len; i++) {
21892                 this.reMap(record[i]);
21893             }
21894         } else {
21895             delete this.data.map[record._phid];
21896             this.data.map[record.id] = record;
21897             var index = this.data.keys.indexOf(record._phid);
21898             this.data.keys.splice(index, 1, record.id);
21899             delete record._phid;
21900         }
21901     },
21902
21903     
21904     onCreateRecords : function(success, rs, data) {
21905         if (success === true) {
21906             try {
21907                 this.reader.realize(rs, data);
21908                 this.reMap(rs);
21909             }
21910             catch (e) {
21911                 this.handleException(e);
21912                 if (Ext.isArray(rs)) {
21913                     
21914                     this.onCreateRecords(success, rs, data);
21915                 }
21916             }
21917         }
21918     },
21919
21920     
21921     onUpdateRecords : function(success, rs, data) {
21922         if (success === true) {
21923             try {
21924                 this.reader.update(rs, data);
21925             } catch (e) {
21926                 this.handleException(e);
21927                 if (Ext.isArray(rs)) {
21928                     
21929                     this.onUpdateRecords(success, rs, data);
21930                 }
21931             }
21932         }
21933     },
21934
21935     
21936     onDestroyRecords : function(success, rs, data) {
21937         
21938         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
21939         for (var i=0,len=rs.length;i<len;i++) {
21940             this.removed.splice(this.removed.indexOf(rs[i]), 1);
21941         }
21942         if (success === false) {
21943             
21944             
21945             for (i=rs.length-1;i>=0;i--) {
21946                 this.insert(rs[i].lastIndex, rs[i]);    
21947             }
21948         }
21949     },
21950
21951     
21952     handleException : function(e) {
21953         
21954         Ext.handleError(e);
21955     },
21956
21957     
21958     reload : function(options){
21959         this.load(Ext.applyIf(options||{}, this.lastOptions));
21960     },
21961
21962     
21963     
21964     loadRecords : function(o, options, success){
21965         if (this.isDestroyed === true) {
21966             return;
21967         }
21968         if(!o || success === false){
21969             if(success !== false){
21970                 this.fireEvent('load', this, [], options);
21971             }
21972             if(options.callback){
21973                 options.callback.call(options.scope || this, [], options, false, o);
21974             }
21975             return;
21976         }
21977         var r = o.records, t = o.totalRecords || r.length;
21978         if(!options || options.add !== true){
21979             if(this.pruneModifiedRecords){
21980                 this.modified = [];
21981             }
21982             for(var i = 0, len = r.length; i < len; i++){
21983                 r[i].join(this);
21984             }
21985             if(this.snapshot){
21986                 this.data = this.snapshot;
21987                 delete this.snapshot;
21988             }
21989             this.clearData();
21990             this.data.addAll(r);
21991             this.totalLength = t;
21992             this.applySort();
21993             this.fireEvent('datachanged', this);
21994         }else{
21995             this.totalLength = Math.max(t, this.data.length+r.length);
21996             this.add(r);
21997         }
21998         this.fireEvent('load', this, r, options);
21999         if(options.callback){
22000             options.callback.call(options.scope || this, r, options, true);
22001         }
22002     },
22003
22004     
22005     loadData : function(o, append){
22006         var r = this.reader.readRecords(o);
22007         this.loadRecords(r, {add: append}, true);
22008     },
22009
22010     
22011     getCount : function(){
22012         return this.data.length || 0;
22013     },
22014
22015     
22016     getTotalCount : function(){
22017         return this.totalLength || 0;
22018     },
22019
22020     
22021     getSortState : function(){
22022         return this.sortInfo;
22023     },
22024
22025     
22026     applySort : function(){
22027         if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
22028             this.sortData();
22029         }
22030     },
22031
22032     
22033     sortData : function() {
22034         var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
22035             direction = sortInfo.direction || "ASC",
22036             sorters   = sortInfo.sorters,
22037             sortFns   = [];
22038
22039         
22040         if (!this.hasMultiSort) {
22041             sorters = [{direction: direction, field: sortInfo.field}];
22042         }
22043
22044         
22045         for (var i=0, j = sorters.length; i < j; i++) {
22046             sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
22047         }
22048         
22049         if (sortFns.length == 0) {
22050             return;
22051         }
22052
22053         
22054         
22055         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
22056
22057         
22058         var fn = function(r1, r2) {
22059           var result = sortFns[0].call(this, r1, r2);
22060
22061           
22062           if (sortFns.length > 1) {
22063               for (var i=1, j = sortFns.length; i < j; i++) {
22064                   result = result || sortFns[i].call(this, r1, r2);
22065               }
22066           }
22067
22068           return directionModifier * result;
22069         };
22070
22071         
22072         this.data.sort(direction, fn);
22073         if (this.snapshot && this.snapshot != this.data) {
22074             this.snapshot.sort(direction, fn);
22075         }
22076     },
22077
22078     
22079     createSortFunction: function(field, direction) {
22080         direction = direction || "ASC";
22081         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
22082
22083         var sortType = this.fields.get(field).sortType;
22084
22085         
22086         
22087         return function(r1, r2) {
22088             var v1 = sortType(r1.data[field]),
22089                 v2 = sortType(r2.data[field]);
22090
22091             return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
22092         };
22093     },
22094
22095     
22096     setDefaultSort : function(field, dir) {
22097         dir = dir ? dir.toUpperCase() : 'ASC';
22098         this.sortInfo = {field: field, direction: dir};
22099         this.sortToggle[field] = dir;
22100     },
22101
22102     
22103     sort : function(fieldName, dir) {
22104         if (Ext.isArray(arguments[0])) {
22105             return this.multiSort.call(this, fieldName, dir);
22106         } else {
22107             return this.singleSort(fieldName, dir);
22108         }
22109     },
22110
22111     
22112     singleSort: function(fieldName, dir) {
22113         var field = this.fields.get(fieldName);
22114         if (!field) return false;
22115
22116         var name       = field.name,
22117             sortInfo   = this.sortInfo || null,
22118             sortToggle = this.sortToggle ? this.sortToggle[name] : null;
22119
22120         if (!dir) {
22121             if (sortInfo && sortInfo.field == name) { 
22122                 dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
22123             } else {
22124                 dir = field.sortDir;
22125             }
22126         }
22127
22128         this.sortToggle[name] = dir;
22129         this.sortInfo = {field: name, direction: dir};
22130         this.hasMultiSort = false;
22131
22132         if (this.remoteSort) {
22133             if (!this.load(this.lastOptions)) {
22134                 if (sortToggle) {
22135                     this.sortToggle[name] = sortToggle;
22136                 }
22137                 if (sortInfo) {
22138                     this.sortInfo = sortInfo;
22139                 }
22140             }
22141         } else {
22142             this.applySort();
22143             this.fireEvent('datachanged', this);
22144         }
22145     },
22146
22147     
22148     multiSort: function(sorters, direction) {
22149         this.hasMultiSort = true;
22150         direction = direction || "ASC";
22151
22152         
22153         if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
22154             direction = direction.toggle("ASC", "DESC");
22155         }
22156
22157         
22158         this.multiSortInfo = {
22159             sorters  : sorters,
22160             direction: direction
22161         };
22162         
22163         if (this.remoteSort) {
22164             this.singleSort(sorters[0].field, sorters[0].direction);
22165
22166         } else {
22167             this.applySort();
22168             this.fireEvent('datachanged', this);
22169         }
22170     },
22171
22172     
22173     each : function(fn, scope){
22174         this.data.each(fn, scope);
22175     },
22176
22177     
22178     getModifiedRecords : function(){
22179         return this.modified;
22180     },
22181
22182     
22183     sum : function(property, start, end){
22184         var rs = this.data.items, v = 0;
22185         start = start || 0;
22186         end = (end || end === 0) ? end : rs.length-1;
22187
22188         for(var i = start; i <= end; i++){
22189             v += (rs[i].data[property] || 0);
22190         }
22191         return v;
22192     },
22193
22194     
22195     createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
22196         if(Ext.isEmpty(value, false)){
22197             return false;
22198         }
22199         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
22200         return function(r) {
22201             return value.test(r.data[property]);
22202         };
22203     },
22204
22205     
22206     createMultipleFilterFn: function(filters) {
22207         return function(record) {
22208             var isMatch = true;
22209
22210             for (var i=0, j = filters.length; i < j; i++) {
22211                 var filter = filters[i],
22212                     fn     = filter.fn,
22213                     scope  = filter.scope;
22214
22215                 isMatch = isMatch && fn.call(scope, record);
22216             }
22217
22218             return isMatch;
22219         };
22220     },
22221
22222     
22223     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
22224         
22225         if (Ext.isObject(property)) {
22226             property = [property];
22227         }
22228
22229         if (Ext.isArray(property)) {
22230             var filters = [];
22231
22232             
22233             for (var i=0, j = property.length; i < j; i++) {
22234                 var filter = property[i],
22235                     func   = filter.fn,
22236                     scope  = filter.scope || this;
22237
22238                 
22239                 if (!Ext.isFunction(func)) {
22240                     func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
22241                 }
22242
22243                 filters.push({fn: func, scope: scope});
22244             }
22245
22246             var fn = this.createMultipleFilterFn(filters);
22247         } else {
22248             
22249             var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
22250         }
22251
22252         return fn ? this.filterBy(fn) : this.clearFilter();
22253     },
22254
22255     
22256     filterBy : function(fn, scope){
22257         this.snapshot = this.snapshot || this.data;
22258         this.data = this.queryBy(fn, scope||this);
22259         this.fireEvent('datachanged', this);
22260     },
22261
22262     
22263     clearFilter : function(suppressEvent){
22264         if(this.isFiltered()){
22265             this.data = this.snapshot;
22266             delete this.snapshot;
22267             if(suppressEvent !== true){
22268                 this.fireEvent('datachanged', this);
22269             }
22270         }
22271     },
22272
22273     
22274     isFiltered : function(){
22275         return !!this.snapshot && this.snapshot != this.data;
22276     },
22277
22278     
22279     query : function(property, value, anyMatch, caseSensitive){
22280         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
22281         return fn ? this.queryBy(fn) : this.data.clone();
22282     },
22283
22284     
22285     queryBy : function(fn, scope){
22286         var data = this.snapshot || this.data;
22287         return data.filterBy(fn, scope||this);
22288     },
22289
22290     
22291     find : function(property, value, start, anyMatch, caseSensitive){
22292         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
22293         return fn ? this.data.findIndexBy(fn, null, start) : -1;
22294     },
22295
22296     
22297     findExact: function(property, value, start){
22298         return this.data.findIndexBy(function(rec){
22299             return rec.get(property) === value;
22300         }, this, start);
22301     },
22302
22303     
22304     findBy : function(fn, scope, start){
22305         return this.data.findIndexBy(fn, scope, start);
22306     },
22307
22308     
22309     collect : function(dataIndex, allowNull, bypassFilter){
22310         var d = (bypassFilter === true && this.snapshot) ?
22311                 this.snapshot.items : this.data.items;
22312         var v, sv, r = [], l = {};
22313         for(var i = 0, len = d.length; i < len; i++){
22314             v = d[i].data[dataIndex];
22315             sv = String(v);
22316             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
22317                 l[sv] = true;
22318                 r[r.length] = v;
22319             }
22320         }
22321         return r;
22322     },
22323
22324     
22325     afterEdit : function(record){
22326         if(this.modified.indexOf(record) == -1){
22327             this.modified.push(record);
22328         }
22329         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
22330     },
22331
22332     
22333     afterReject : function(record){
22334         this.modified.remove(record);
22335         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
22336     },
22337
22338     
22339     afterCommit : function(record){
22340         this.modified.remove(record);
22341         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
22342     },
22343
22344     
22345     commitChanges : function(){
22346         var m = this.modified.slice(0);
22347         this.modified = [];
22348         for(var i = 0, len = m.length; i < len; i++){
22349             m[i].commit();
22350         }
22351     },
22352
22353     
22354     rejectChanges : function(){
22355         var m = this.modified.slice(0);
22356         this.modified = [];
22357         for(var i = 0, len = m.length; i < len; i++){
22358             m[i].reject();
22359         }
22360         var m = this.removed.slice(0).reverse();
22361         this.removed = [];
22362         for(var i = 0, len = m.length; i < len; i++){
22363             this.insert(m[i].lastIndex||0, m[i]);
22364             m[i].reject();
22365         }
22366     },
22367
22368     
22369     onMetaChange : function(meta){
22370         this.recordType = this.reader.recordType;
22371         this.fields = this.recordType.prototype.fields;
22372         delete this.snapshot;
22373         if(this.reader.meta.sortInfo){
22374             this.sortInfo = this.reader.meta.sortInfo;
22375         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
22376             delete this.sortInfo;
22377         }
22378         if(this.writer){
22379             this.writer.meta = this.reader.meta;
22380         }
22381         this.modified = [];
22382         this.fireEvent('metachange', this, this.reader.meta);
22383     },
22384
22385     
22386     findInsertIndex : function(record){
22387         this.suspendEvents();
22388         var data = this.data.clone();
22389         this.data.add(record);
22390         this.applySort();
22391         var index = this.data.indexOf(record);
22392         this.data = data;
22393         this.resumeEvents();
22394         return index;
22395     },
22396
22397     
22398     setBaseParam : function (name, value){
22399         this.baseParams = this.baseParams || {};
22400         this.baseParams[name] = value;
22401     }
22402 });
22403
22404 Ext.reg('store', Ext.data.Store);
22405
22406
22407 Ext.data.Store.Error = Ext.extend(Ext.Error, {
22408     name: 'Ext.data.Store'
22409 });
22410 Ext.apply(Ext.data.Store.Error.prototype, {
22411     lang: {
22412         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
22413     }
22414 });
22415
22416 Ext.data.Field = Ext.extend(Object, {
22417     
22418     constructor : function(config){
22419         if(Ext.isString(config)){
22420             config = {name: config};
22421         }
22422         Ext.apply(this, config);
22423         
22424         var types = Ext.data.Types,
22425             st = this.sortType,
22426             t;
22427
22428         if(this.type){
22429             if(Ext.isString(this.type)){
22430                 this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
22431             }
22432         }else{
22433             this.type = types.AUTO;
22434         }
22435
22436         
22437         if(Ext.isString(st)){
22438             this.sortType = Ext.data.SortTypes[st];
22439         }else if(Ext.isEmpty(st)){
22440             this.sortType = this.type.sortType;
22441         }
22442
22443         if(!this.convert){
22444             this.convert = this.type.convert;
22445         }
22446     },
22447     
22448     
22449     
22450     
22451     
22452     dateFormat: null,
22453     
22454     defaultValue: "",
22455     
22456     mapping: null,
22457     
22458     sortType : null,
22459     
22460     sortDir : "ASC",
22461     
22462     allowBlank : true
22463 });
22464
22465 Ext.data.DataReader = function(meta, recordType){
22466     
22467     this.meta = meta;
22468     
22469     this.recordType = Ext.isArray(recordType) ?
22470         Ext.data.Record.create(recordType) : recordType;
22471
22472     
22473     if (this.recordType){
22474         this.buildExtractors();
22475     }
22476 };
22477
22478 Ext.data.DataReader.prototype = {
22479     
22480     
22481     getTotal: Ext.emptyFn,
22482     
22483     getRoot: Ext.emptyFn,
22484     
22485     getMessage: Ext.emptyFn,
22486     
22487     getSuccess: Ext.emptyFn,
22488     
22489     getId: Ext.emptyFn,
22490     
22491     buildExtractors : Ext.emptyFn,
22492     
22493     extractValues : Ext.emptyFn,
22494
22495     
22496     realize: function(rs, data){
22497         if (Ext.isArray(rs)) {
22498             for (var i = rs.length - 1; i >= 0; i--) {
22499                 
22500                 if (Ext.isArray(data)) {
22501                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
22502                 }
22503                 else {
22504                     
22505                     
22506                     this.realize(rs.splice(i,1).shift(), data);
22507                 }
22508             }
22509         }
22510         else {
22511             
22512             if (Ext.isArray(data) && data.length == 1) {
22513                 data = data.shift();
22514             }
22515             if (!this.isData(data)) {
22516                 
22517                 
22518                 throw new Ext.data.DataReader.Error('realize', rs);
22519             }
22520             rs.phantom = false; 
22521             rs._phid = rs.id;  
22522             rs.id = this.getId(data);
22523             rs.data = data;
22524
22525             rs.commit();
22526         }
22527     },
22528
22529     
22530     update : function(rs, data) {
22531         if (Ext.isArray(rs)) {
22532             for (var i=rs.length-1; i >= 0; i--) {
22533                 if (Ext.isArray(data)) {
22534                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
22535                 }
22536                 else {
22537                     
22538                     
22539                     this.update(rs.splice(i,1).shift(), data);
22540                 }
22541             }
22542         }
22543         else {
22544             
22545             if (Ext.isArray(data) && data.length == 1) {
22546                 data = data.shift();
22547             }
22548             if (this.isData(data)) {
22549                 rs.data = Ext.apply(rs.data, data);
22550             }
22551             rs.commit();
22552         }
22553     },
22554
22555     
22556     extractData : function(root, returnRecords) {
22557         
22558         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
22559
22560         var rs = [];
22561
22562         
22563         
22564         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
22565             root = [root];
22566         }
22567         var f       = this.recordType.prototype.fields,
22568             fi      = f.items,
22569             fl      = f.length,
22570             rs      = [];
22571         if (returnRecords === true) {
22572             var Record = this.recordType;
22573             for (var i = 0; i < root.length; i++) {
22574                 var n = root[i];
22575                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
22576                 record[rawName] = n;    
22577                 rs.push(record);
22578             }
22579         }
22580         else {
22581             for (var i = 0; i < root.length; i++) {
22582                 var data = this.extractValues(root[i], fi, fl);
22583                 data[this.meta.idProperty] = this.getId(root[i]);
22584                 rs.push(data);
22585             }
22586         }
22587         return rs;
22588     },
22589
22590     
22591     isData : function(data) {
22592         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
22593     },
22594
22595     
22596     onMetaChange : function(meta){
22597         delete this.ef;
22598         this.meta = meta;
22599         this.recordType = Ext.data.Record.create(meta.fields);
22600         this.buildExtractors();
22601     }
22602 };
22603
22604
22605 Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
22606     constructor : function(message, arg) {
22607         this.arg = arg;
22608         Ext.Error.call(this, message);
22609     },
22610     name: 'Ext.data.DataReader'
22611 });
22612 Ext.apply(Ext.data.DataReader.Error.prototype, {
22613     lang : {
22614         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
22615         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
22616         'invalid-response': "#readResponse received an invalid response from the server."
22617     }
22618 });
22619
22620 Ext.data.DataWriter = function(config){
22621     Ext.apply(this, config);
22622 };
22623 Ext.data.DataWriter.prototype = {
22624
22625     
22626     writeAllFields : false,
22627     
22628     listful : false,    
22629
22630     
22631     apply : function(params, baseParams, action, rs) {
22632         var data    = [],
22633         renderer    = action + 'Record';
22634         
22635         if (Ext.isArray(rs)) {
22636             Ext.each(rs, function(rec){
22637                 data.push(this[renderer](rec));
22638             }, this);
22639         }
22640         else if (rs instanceof Ext.data.Record) {
22641             data = this[renderer](rs);
22642         }
22643         this.render(params, baseParams, data);
22644     },
22645
22646     
22647     render : Ext.emptyFn,
22648
22649     
22650     updateRecord : Ext.emptyFn,
22651
22652     
22653     createRecord : Ext.emptyFn,
22654
22655     
22656     destroyRecord : Ext.emptyFn,
22657
22658     
22659     toHash : function(rec, config) {
22660         var map = rec.fields.map,
22661             data = {},
22662             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
22663             m;
22664         Ext.iterate(raw, function(prop, value){
22665             if((m = map[prop])){
22666                 data[m.mapping ? m.mapping : m.name] = value;
22667             }
22668         });
22669         
22670         
22671         
22672         if (rec.phantom) {
22673             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
22674                 delete data[this.meta.idProperty];
22675             }
22676         } else {
22677             data[this.meta.idProperty] = rec.id
22678         }
22679         return data;
22680     },
22681
22682     
22683     toArray : function(data) {
22684         var fields = [];
22685         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
22686         return fields;
22687     }
22688 };
22689 Ext.data.DataProxy = function(conn){
22690     
22691     
22692     conn = conn || {};
22693
22694     
22695     
22696     
22697
22698     this.api     = conn.api;
22699     this.url     = conn.url;
22700     this.restful = conn.restful;
22701     this.listeners = conn.listeners;
22702
22703     
22704     this.prettyUrls = conn.prettyUrls;
22705
22706     
22707
22708     this.addEvents(
22709         
22710         'exception',
22711         
22712         'beforeload',
22713         
22714         'load',
22715         
22716         'loadexception',
22717         
22718         'beforewrite',
22719         
22720         'write'
22721     );
22722     Ext.data.DataProxy.superclass.constructor.call(this);
22723
22724     
22725     try {
22726         Ext.data.Api.prepare(this);
22727     } catch (e) {
22728         if (e instanceof Ext.data.Api.Error) {
22729             e.toConsole();
22730         }
22731     }
22732     
22733     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
22734 };
22735
22736 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
22737     
22738     restful: false,
22739
22740     
22741     setApi : function() {
22742         if (arguments.length == 1) {
22743             var valid = Ext.data.Api.isValid(arguments[0]);
22744             if (valid === true) {
22745                 this.api = arguments[0];
22746             }
22747             else {
22748                 throw new Ext.data.Api.Error('invalid', valid);
22749             }
22750         }
22751         else if (arguments.length == 2) {
22752             if (!Ext.data.Api.isAction(arguments[0])) {
22753                 throw new Ext.data.Api.Error('invalid', arguments[0]);
22754             }
22755             this.api[arguments[0]] = arguments[1];
22756         }
22757         Ext.data.Api.prepare(this);
22758     },
22759
22760     
22761     isApiAction : function(action) {
22762         return (this.api[action]) ? true : false;
22763     },
22764
22765     
22766     request : function(action, rs, params, reader, callback, scope, options) {
22767         if (!this.api[action] && !this.load) {
22768             throw new Ext.data.DataProxy.Error('action-undefined', action);
22769         }
22770         params = params || {};
22771         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
22772             this.doRequest.apply(this, arguments);
22773         }
22774         else {
22775             callback.call(scope || this, null, options, false);
22776         }
22777     },
22778
22779
22780     
22781     load : null,
22782
22783     
22784     doRequest : function(action, rs, params, reader, callback, scope, options) {
22785         
22786         
22787         
22788         this.load(params, reader, callback, scope, options);
22789     },
22790
22791     
22792     onRead : Ext.emptyFn,
22793     
22794     onWrite : Ext.emptyFn,
22795     
22796     buildUrl : function(action, record) {
22797         record = record || null;
22798
22799         
22800         
22801         
22802         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
22803         if (!url) {
22804             throw new Ext.data.Api.Error('invalid-url', action);
22805         }
22806
22807         
22808         
22809         
22810         
22811         
22812         
22813         var provides = null;
22814         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
22815         if (m) {
22816             provides = m[2];    
22817             url      = m[1];    
22818         }
22819         
22820         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
22821             url += '/' + record.id;
22822         }
22823         return (provides === null) ? url : url + provides;
22824     },
22825
22826     
22827     destroy: function(){
22828         this.purgeListeners();
22829     }
22830 });
22831
22832
22833
22834 Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
22835 Ext.util.Observable.call(Ext.data.DataProxy);
22836
22837
22838 Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
22839     constructor : function(message, arg) {
22840         this.arg = arg;
22841         Ext.Error.call(this, message);
22842     },
22843     name: 'Ext.data.DataProxy'
22844 });
22845 Ext.apply(Ext.data.DataProxy.Error.prototype, {
22846     lang: {
22847         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
22848         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
22849     }
22850 });
22851
22852
22853
22854 Ext.data.Request = function(params) {
22855     Ext.apply(this, params);
22856 };
22857 Ext.data.Request.prototype = {
22858     
22859     action : undefined,
22860     
22861     rs : undefined,
22862     
22863     params: undefined,
22864     
22865     callback : Ext.emptyFn,
22866     
22867     scope : undefined,
22868     
22869     reader : undefined
22870 };
22871
22872 Ext.data.Response = function(params) {
22873     Ext.apply(this, params);
22874 };
22875 Ext.data.Response.prototype = {
22876     
22877     action: undefined,
22878     
22879     success : undefined,
22880     
22881     message : undefined,
22882     
22883     data: undefined,
22884     
22885     raw: undefined,
22886     
22887     records: undefined
22888 };
22889
22890 Ext.data.ScriptTagProxy = function(config){
22891     Ext.apply(this, config);
22892
22893     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
22894
22895     this.head = document.getElementsByTagName("head")[0];
22896
22897     
22898 };
22899
22900 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
22901
22902 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
22903     
22904     
22905     timeout : 30000,
22906     
22907     callbackParam : "callback",
22908     
22909     nocache : true,
22910
22911     
22912     doRequest : function(action, rs, params, reader, callback, scope, arg) {
22913         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
22914
22915         var url = this.buildUrl(action, rs);
22916         if (!url) {
22917             throw new Ext.data.Api.Error('invalid-url', url);
22918         }
22919         url = Ext.urlAppend(url, p);
22920
22921         if(this.nocache){
22922             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
22923         }
22924         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
22925         var trans = {
22926             id : transId,
22927             action: action,
22928             cb : "stcCallback"+transId,
22929             scriptId : "stcScript"+transId,
22930             params : params,
22931             arg : arg,
22932             url : url,
22933             callback : callback,
22934             scope : scope,
22935             reader : reader
22936         };
22937         window[trans.cb] = this.createCallback(action, rs, trans);
22938         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
22939         if(this.autoAbort !== false){
22940             this.abort();
22941         }
22942
22943         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
22944
22945         var script = document.createElement("script");
22946         script.setAttribute("src", url);
22947         script.setAttribute("type", "text/javascript");
22948         script.setAttribute("id", trans.scriptId);
22949         this.head.appendChild(script);
22950
22951         this.trans = trans;
22952     },
22953
22954     
22955     createCallback : function(action, rs, trans) {
22956         var self = this;
22957         return function(res) {
22958             self.trans = false;
22959             self.destroyTrans(trans, true);
22960             if (action === Ext.data.Api.actions.read) {
22961                 self.onRead.call(self, action, trans, res);
22962             } else {
22963                 self.onWrite.call(self, action, trans, res, rs);
22964             }
22965         };
22966     },
22967     
22968     onRead : function(action, trans, res) {
22969         var result;
22970         try {
22971             result = trans.reader.readRecords(res);
22972         }catch(e){
22973             
22974             this.fireEvent("loadexception", this, trans, res, e);
22975
22976             this.fireEvent('exception', this, 'response', action, trans, res, e);
22977             trans.callback.call(trans.scope||window, null, trans.arg, false);
22978             return;
22979         }
22980         if (result.success === false) {
22981             
22982             this.fireEvent('loadexception', this, trans, res);
22983
22984             this.fireEvent('exception', this, 'remote', action, trans, res, null);
22985         } else {
22986             this.fireEvent("load", this, res, trans.arg);
22987         }
22988         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
22989     },
22990     
22991     onWrite : function(action, trans, response, rs) {
22992         var reader = trans.reader;
22993         try {
22994             
22995             var res = reader.readResponse(action, response);
22996         } catch (e) {
22997             this.fireEvent('exception', this, 'response', action, trans, res, e);
22998             trans.callback.call(trans.scope||window, null, res, false);
22999             return;
23000         }
23001         if(!res.success === true){
23002             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
23003             trans.callback.call(trans.scope||window, null, res, false);
23004             return;
23005         }
23006         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
23007         trans.callback.call(trans.scope||window, res.data, res, true);
23008     },
23009
23010     
23011     isLoading : function(){
23012         return this.trans ? true : false;
23013     },
23014
23015     
23016     abort : function(){
23017         if(this.isLoading()){
23018             this.destroyTrans(this.trans);
23019         }
23020     },
23021
23022     
23023     destroyTrans : function(trans, isLoaded){
23024         this.head.removeChild(document.getElementById(trans.scriptId));
23025         clearTimeout(trans.timeoutId);
23026         if(isLoaded){
23027             window[trans.cb] = undefined;
23028             try{
23029                 delete window[trans.cb];
23030             }catch(e){}
23031         }else{
23032             
23033             window[trans.cb] = function(){
23034                 window[trans.cb] = undefined;
23035                 try{
23036                     delete window[trans.cb];
23037                 }catch(e){}
23038             };
23039         }
23040     },
23041
23042     
23043     handleFailure : function(trans){
23044         this.trans = false;
23045         this.destroyTrans(trans, false);
23046         if (trans.action === Ext.data.Api.actions.read) {
23047             
23048             this.fireEvent("loadexception", this, null, trans.arg);
23049         }
23050
23051         this.fireEvent('exception', this, 'response', trans.action, {
23052             response: null,
23053             options: trans.arg
23054         });
23055         trans.callback.call(trans.scope||window, null, trans.arg, false);
23056     },
23057
23058     
23059     destroy: function(){
23060         this.abort();
23061         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
23062     }
23063 });
23064 Ext.data.HttpProxy = function(conn){
23065     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
23066
23067     
23068     this.conn = conn;
23069
23070     
23071     
23072     
23073     
23074     this.conn.url = null;
23075
23076     this.useAjax = !conn || !conn.events;
23077
23078     
23079     var actions = Ext.data.Api.actions;
23080     this.activeRequest = {};
23081     for (var verb in actions) {
23082         this.activeRequest[actions[verb]] = undefined;
23083     }
23084 };
23085
23086 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
23087     
23088     getConnection : function() {
23089         return this.useAjax ? Ext.Ajax : this.conn;
23090     },
23091
23092     
23093     setUrl : function(url, makePermanent) {
23094         this.conn.url = url;
23095         if (makePermanent === true) {
23096             this.url = url;
23097             this.api = null;
23098             Ext.data.Api.prepare(this);
23099         }
23100     },
23101
23102     
23103     doRequest : function(action, rs, params, reader, cb, scope, arg) {
23104         var  o = {
23105             method: (this.api[action]) ? this.api[action]['method'] : undefined,
23106             request: {
23107                 callback : cb,
23108                 scope : scope,
23109                 arg : arg
23110             },
23111             reader: reader,
23112             callback : this.createCallback(action, rs),
23113             scope: this
23114         };
23115
23116         
23117         
23118         if (params.jsonData) {
23119             o.jsonData = params.jsonData;
23120         } else if (params.xmlData) {
23121             o.xmlData = params.xmlData;
23122         } else {
23123             o.params = params || {};
23124         }
23125         
23126         
23127         
23128         this.conn.url = this.buildUrl(action, rs);
23129
23130         if(this.useAjax){
23131
23132             Ext.applyIf(o, this.conn);
23133
23134             
23135             if (this.activeRequest[action]) {
23136                 
23137                 
23138                 
23139                 
23140                 
23141             }
23142             this.activeRequest[action] = Ext.Ajax.request(o);
23143         }else{
23144             this.conn.request(o);
23145         }
23146         
23147         this.conn.url = null;
23148     },
23149
23150     
23151     createCallback : function(action, rs) {
23152         return function(o, success, response) {
23153             this.activeRequest[action] = undefined;
23154             if (!success) {
23155                 if (action === Ext.data.Api.actions.read) {
23156                     
23157                     
23158                     this.fireEvent('loadexception', this, o, response);
23159                 }
23160                 this.fireEvent('exception', this, 'response', action, o, response);
23161                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
23162                 return;
23163             }
23164             if (action === Ext.data.Api.actions.read) {
23165                 this.onRead(action, o, response);
23166             } else {
23167                 this.onWrite(action, o, response, rs);
23168             }
23169         };
23170     },
23171
23172     
23173     onRead : function(action, o, response) {
23174         var result;
23175         try {
23176             result = o.reader.read(response);
23177         }catch(e){
23178             
23179             
23180             this.fireEvent('loadexception', this, o, response, e);
23181
23182             this.fireEvent('exception', this, 'response', action, o, response, e);
23183             o.request.callback.call(o.request.scope, null, o.request.arg, false);
23184             return;
23185         }
23186         if (result.success === false) {
23187             
23188             
23189             this.fireEvent('loadexception', this, o, response);
23190
23191             
23192             var res = o.reader.readResponse(action, response);
23193             this.fireEvent('exception', this, 'remote', action, o, res, null);
23194         }
23195         else {
23196             this.fireEvent('load', this, o, o.request.arg);
23197         }
23198         
23199         
23200         
23201         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
23202     },
23203     
23204     onWrite : function(action, o, response, rs) {
23205         var reader = o.reader;
23206         var res;
23207         try {
23208             res = reader.readResponse(action, response);
23209         } catch (e) {
23210             this.fireEvent('exception', this, 'response', action, o, response, e);
23211             o.request.callback.call(o.request.scope, null, o.request.arg, false);
23212             return;
23213         }
23214         if (res.success === true) {
23215             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
23216         } else {
23217             this.fireEvent('exception', this, 'remote', action, o, res, rs);
23218         }
23219         
23220         
23221         
23222         o.request.callback.call(o.request.scope, res.data, res, res.success);
23223     },
23224
23225     
23226     destroy: function(){
23227         if(!this.useAjax){
23228             this.conn.abort();
23229         }else if(this.activeRequest){
23230             var actions = Ext.data.Api.actions;
23231             for (var verb in actions) {
23232                 if(this.activeRequest[actions[verb]]){
23233                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
23234                 }
23235             }
23236         }
23237         Ext.data.HttpProxy.superclass.destroy.call(this);
23238     }
23239 });
23240 Ext.data.MemoryProxy = function(data){
23241     
23242     var api = {};
23243     api[Ext.data.Api.actions.read] = true;
23244     Ext.data.MemoryProxy.superclass.constructor.call(this, {
23245         api: api
23246     });
23247     this.data = data;
23248 };
23249
23250 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
23251     
23252
23253        
23254     doRequest : function(action, rs, params, reader, callback, scope, arg) {
23255         
23256         params = params || {};
23257         var result;
23258         try {
23259             result = reader.readRecords(this.data);
23260         }catch(e){
23261             
23262             this.fireEvent("loadexception", this, null, arg, e);
23263
23264             this.fireEvent('exception', this, 'response', action, arg, null, e);
23265             callback.call(scope, null, arg, false);
23266             return;
23267         }
23268         callback.call(scope, result, arg, true);
23269     }
23270 });
23271 Ext.data.Types = new function(){
23272     var st = Ext.data.SortTypes;
23273     Ext.apply(this, {
23274         
23275         stripRe: /[\$,%]/g,
23276         
23277         
23278         AUTO: {
23279             convert: function(v){ return v; },
23280             sortType: st.none,
23281             type: 'auto'
23282         },
23283
23284         
23285         STRING: {
23286             convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
23287             sortType: st.asUCString,
23288             type: 'string'
23289         },
23290
23291         
23292         INT: {
23293             convert: function(v){
23294                 return v !== undefined && v !== null && v !== '' ?
23295                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
23296             },
23297             sortType: st.none,
23298             type: 'int'
23299         },
23300         
23301         
23302         FLOAT: {
23303             convert: function(v){
23304                 return v !== undefined && v !== null && v !== '' ?
23305                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
23306             },
23307             sortType: st.none,
23308             type: 'float'
23309         },
23310         
23311         
23312         BOOL: {
23313             convert: function(v){ return v === true || v === 'true' || v == 1; },
23314             sortType: st.none,
23315             type: 'bool'
23316         },
23317         
23318         
23319         DATE: {
23320             convert: function(v){
23321                 var df = this.dateFormat;
23322                 if(!v){
23323                     return null;
23324                 }
23325                 if(Ext.isDate(v)){
23326                     return v;
23327                 }
23328                 if(df){
23329                     if(df == 'timestamp'){
23330                         return new Date(v*1000);
23331                     }
23332                     if(df == 'time'){
23333                         return new Date(parseInt(v, 10));
23334                     }
23335                     return Date.parseDate(v, df);
23336                 }
23337                 var parsed = Date.parse(v);
23338                 return parsed ? new Date(parsed) : null;
23339             },
23340             sortType: st.asDate,
23341             type: 'date'
23342         }
23343     });
23344     
23345     Ext.apply(this, {
23346         
23347         BOOLEAN: this.BOOL,
23348         
23349         INTEGER: this.INT,
23350         
23351         NUMBER: this.FLOAT    
23352     });
23353 };
23354 Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
23355     
23356     encode : true,
23357     
23358     encodeDelete: false,
23359     
23360     constructor : function(config){
23361         Ext.data.JsonWriter.superclass.constructor.call(this, config);    
23362     },
23363
23364     
23365     render : function(params, baseParams, data) {
23366         if (this.encode === true) {
23367             
23368             Ext.apply(params, baseParams);
23369             params[this.meta.root] = Ext.encode(data);
23370         } else {
23371             
23372             var jdata = Ext.apply({}, baseParams);
23373             jdata[this.meta.root] = data;
23374             params.jsonData = jdata;
23375         }
23376     },
23377     
23378     createRecord : function(rec) {
23379        return this.toHash(rec);
23380     },
23381     
23382     updateRecord : function(rec) {
23383         return this.toHash(rec);
23384
23385     },
23386     
23387     destroyRecord : function(rec){
23388         if(this.encodeDelete){
23389             var data = {};
23390             data[this.meta.idProperty] = rec.id;
23391             return data;
23392         }else{
23393             return rec.id;
23394         }
23395     }
23396 });
23397 Ext.data.JsonReader = function(meta, recordType){
23398     meta = meta || {};
23399     
23400     
23401     
23402     
23403     Ext.applyIf(meta, {
23404         idProperty: 'id',
23405         successProperty: 'success',
23406         totalProperty: 'total'
23407     });
23408
23409     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
23410 };
23411 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
23412     
23413     
23414     read : function(response){
23415         var json = response.responseText;
23416         var o = Ext.decode(json);
23417         if(!o) {
23418             throw {message: 'JsonReader.read: Json object not found'};
23419         }
23420         return this.readRecords(o);
23421     },
23422
23423     
23424     
23425     readResponse : function(action, response) {
23426         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
23427         if(!o) {
23428             throw new Ext.data.JsonReader.Error('response');
23429         }
23430
23431         var root = this.getRoot(o);
23432         if (action === Ext.data.Api.actions.create) {
23433             var def = Ext.isDefined(root);
23434             if (def && Ext.isEmpty(root)) {
23435                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
23436             }
23437             else if (!def) {
23438                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
23439             }
23440         }
23441
23442         
23443         var res = new Ext.data.Response({
23444             action: action,
23445             success: this.getSuccess(o),
23446             data: (root) ? this.extractData(root, false) : [],
23447             message: this.getMessage(o),
23448             raw: o
23449         });
23450
23451         
23452         if (Ext.isEmpty(res.success)) {
23453             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
23454         }
23455         return res;
23456     },
23457
23458     
23459     readRecords : function(o){
23460         
23461         this.jsonData = o;
23462         if(o.metaData){
23463             this.onMetaChange(o.metaData);
23464         }
23465         var s = this.meta, Record = this.recordType,
23466             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
23467
23468         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
23469         if(s.totalProperty){
23470             v = parseInt(this.getTotal(o), 10);
23471             if(!isNaN(v)){
23472                 totalRecords = v;
23473             }
23474         }
23475         if(s.successProperty){
23476             v = this.getSuccess(o);
23477             if(v === false || v === 'false'){
23478                 success = false;
23479             }
23480         }
23481
23482         
23483         return {
23484             success : success,
23485             records : this.extractData(root, true), 
23486             totalRecords : totalRecords
23487         };
23488     },
23489
23490     
23491     buildExtractors : function() {
23492         if(this.ef){
23493             return;
23494         }
23495         var s = this.meta, Record = this.recordType,
23496             f = Record.prototype.fields, fi = f.items, fl = f.length;
23497
23498         if(s.totalProperty) {
23499             this.getTotal = this.createAccessor(s.totalProperty);
23500         }
23501         if(s.successProperty) {
23502             this.getSuccess = this.createAccessor(s.successProperty);
23503         }
23504         if (s.messageProperty) {
23505             this.getMessage = this.createAccessor(s.messageProperty);
23506         }
23507         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
23508         if (s.id || s.idProperty) {
23509             var g = this.createAccessor(s.id || s.idProperty);
23510             this.getId = function(rec) {
23511                 var r = g(rec);
23512                 return (r === undefined || r === '') ? null : r;
23513             };
23514         } else {
23515             this.getId = function(){return null;};
23516         }
23517         var ef = [];
23518         for(var i = 0; i < fl; i++){
23519             f = fi[i];
23520             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
23521             ef.push(this.createAccessor(map));
23522         }
23523         this.ef = ef;
23524     },
23525
23526     
23527     simpleAccess : function(obj, subsc) {
23528         return obj[subsc];
23529     },
23530
23531     
23532     createAccessor : function(){
23533         var re = /[\[\.]/;
23534         return function(expr) {
23535             if(Ext.isEmpty(expr)){
23536                 return Ext.emptyFn;
23537             }
23538             if(Ext.isFunction(expr)){
23539                 return expr;
23540             }
23541             var i = String(expr).search(re);
23542             if(i >= 0){
23543                 return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
23544             }
23545             return function(obj){
23546                 return obj[expr];
23547             };
23548
23549         };
23550     }(),
23551
23552     
23553     extractValues : function(data, items, len) {
23554         var f, values = {};
23555         for(var j = 0; j < len; j++){
23556             f = items[j];
23557             var v = this.ef[j](data);
23558             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
23559         }
23560         return values;
23561     }
23562 });
23563
23564
23565 Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
23566     constructor : function(message, arg) {
23567         this.arg = arg;
23568         Ext.Error.call(this, message);
23569     },
23570     name : 'Ext.data.JsonReader'
23571 });
23572 Ext.apply(Ext.data.JsonReader.Error.prototype, {
23573     lang: {
23574         'response': 'An error occurred while json-decoding your server response',
23575         '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.',
23576         '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.',
23577         '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.',
23578         '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.'
23579     }
23580 });
23581
23582 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
23583     
23584     
23585     
23586     
23587     readRecords : function(o){
23588         this.arrayData = o;
23589         var s = this.meta,
23590             sid = s ? Ext.num(s.idIndex, s.id) : null,
23591             recordType = this.recordType,
23592             fields = recordType.prototype.fields,
23593             records = [],
23594             success = true,
23595             v;
23596
23597         var root = this.getRoot(o);
23598
23599         for(var i = 0, len = root.length; i < len; i++) {
23600             var n = root[i],
23601                 values = {},
23602                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
23603             for(var j = 0, jlen = fields.length; j < jlen; j++) {
23604                 var f = fields.items[j],
23605                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
23606                 v = n[k] !== undefined ? n[k] : f.defaultValue;
23607                 v = f.convert(v, n);
23608                 values[f.name] = v;
23609             }
23610             var record = new recordType(values, id);
23611             record.json = n;
23612             records[records.length] = record;
23613         }
23614
23615         var totalRecords = records.length;
23616
23617         if(s.totalProperty) {
23618             v = parseInt(this.getTotal(o), 10);
23619             if(!isNaN(v)) {
23620                 totalRecords = v;
23621             }
23622         }
23623         if(s.successProperty){
23624             v = this.getSuccess(o);
23625             if(v === false || v === 'false'){
23626                 success = false;
23627             }
23628         }
23629
23630         return {
23631             success : success,
23632             records : records,
23633             totalRecords : totalRecords
23634         };
23635     }
23636 });
23637 Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
23638     
23639     constructor: function(config){
23640         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
23641             reader: new Ext.data.ArrayReader(config)
23642         }));
23643     },
23644
23645     loadData : function(data, append){
23646         if(this.expandData === true){
23647             var r = [];
23648             for(var i = 0, len = data.length; i < len; i++){
23649                 r[r.length] = [data[i]];
23650             }
23651             data = r;
23652         }
23653         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
23654     }
23655 });
23656 Ext.reg('arraystore', Ext.data.ArrayStore);
23657
23658
23659 Ext.data.SimpleStore = Ext.data.ArrayStore;
23660 Ext.reg('simplestore', Ext.data.SimpleStore);
23661 Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
23662     
23663     constructor: function(config){
23664         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
23665             reader: new Ext.data.JsonReader(config)
23666         }));
23667     }
23668 });
23669 Ext.reg('jsonstore', Ext.data.JsonStore);
23670 Ext.data.XmlWriter = function(params) {
23671     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
23672     
23673     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
23674 };
23675 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
23676     
23677     documentRoot: 'xrequest',
23678     
23679     forceDocumentRoot: false,
23680     
23681     root: 'records',
23682     
23683     xmlVersion : '1.0',
23684     
23685     xmlEncoding: 'ISO-8859-15',
23686     
23687     
23688     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>',
23689
23690
23691     
23692     render : function(params, baseParams, data) {
23693         baseParams = this.toArray(baseParams);
23694         params.xmlData = this.tpl.applyTemplate({
23695             version: this.xmlVersion,
23696             encoding: this.xmlEncoding,
23697             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
23698             record: this.meta.record,
23699             root: this.root,
23700             baseParams: baseParams,
23701             records: (Ext.isArray(data[0])) ? data : [data]
23702         });
23703     },
23704
23705     
23706     createRecord : function(rec) {
23707         return this.toArray(this.toHash(rec));
23708     },
23709
23710     
23711     updateRecord : function(rec) {
23712         return this.toArray(this.toHash(rec));
23713
23714     },
23715     
23716     destroyRecord : function(rec) {
23717         var data = {};
23718         data[this.meta.idProperty] = rec.id;
23719         return this.toArray(data);
23720     }
23721 });
23722
23723 Ext.data.XmlReader = function(meta, recordType){
23724     meta = meta || {};
23725
23726     
23727     Ext.applyIf(meta, {
23728         idProperty: meta.idProperty || meta.idPath || meta.id,
23729         successProperty: meta.successProperty || meta.success
23730     });
23731
23732     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
23733 };
23734 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
23735     
23736     read : function(response){
23737         var doc = response.responseXML;
23738         if(!doc) {
23739             throw {message: "XmlReader.read: XML Document not available"};
23740         }
23741         return this.readRecords(doc);
23742     },
23743
23744     
23745     readRecords : function(doc){
23746         
23747         this.xmlData = doc;
23748
23749         var root    = doc.documentElement || doc,
23750             q       = Ext.DomQuery,
23751             totalRecords = 0,
23752             success = true;
23753
23754         if(this.meta.totalProperty){
23755             totalRecords = this.getTotal(root, 0);
23756         }
23757         if(this.meta.successProperty){
23758             success = this.getSuccess(root);
23759         }
23760
23761         var records = this.extractData(q.select(this.meta.record, root), true); 
23762
23763         
23764         return {
23765             success : success,
23766             records : records,
23767             totalRecords : totalRecords || records.length
23768         };
23769     },
23770
23771     
23772     readResponse : function(action, response) {
23773         var q = Ext.DomQuery,
23774             doc = response.responseXML,
23775             root = doc.documentElement || doc;
23776
23777         
23778         var res = new Ext.data.Response({
23779             action: action,
23780             success : this.getSuccess(root),
23781             message: this.getMessage(root),
23782             data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
23783             raw: doc
23784         });
23785
23786         if (Ext.isEmpty(res.success)) {
23787             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
23788         }
23789
23790         
23791         if (action === Ext.data.Api.actions.create) {
23792             var def = Ext.isDefined(res.data);
23793             if (def && Ext.isEmpty(res.data)) {
23794                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
23795             }
23796             else if (!def) {
23797                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
23798             }
23799         }
23800         return res;
23801     },
23802
23803     getSuccess : function() {
23804         return true;
23805     },
23806
23807     
23808     buildExtractors : function() {
23809         if(this.ef){
23810             return;
23811         }
23812         var s       = this.meta,
23813             Record  = this.recordType,
23814             f       = Record.prototype.fields,
23815             fi      = f.items,
23816             fl      = f.length;
23817
23818         if(s.totalProperty) {
23819             this.getTotal = this.createAccessor(s.totalProperty);
23820         }
23821         if(s.successProperty) {
23822             this.getSuccess = this.createAccessor(s.successProperty);
23823         }
23824         if (s.messageProperty) {
23825             this.getMessage = this.createAccessor(s.messageProperty);
23826         }
23827         this.getRoot = function(res) {
23828             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
23829         };
23830         if (s.idPath || s.idProperty) {
23831             var g = this.createAccessor(s.idPath || s.idProperty);
23832             this.getId = function(rec) {
23833                 var id = g(rec) || rec.id;
23834                 return (id === undefined || id === '') ? null : id;
23835             };
23836         } else {
23837             this.getId = function(){return null;};
23838         }
23839         var ef = [];
23840         for(var i = 0; i < fl; i++){
23841             f = fi[i];
23842             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
23843             ef.push(this.createAccessor(map));
23844         }
23845         this.ef = ef;
23846     },
23847
23848     
23849     createAccessor : function(){
23850         var q = Ext.DomQuery;
23851         return function(key) {
23852             switch(key) {
23853                 case this.meta.totalProperty:
23854                     return function(root, def){
23855                         return q.selectNumber(key, root, def);
23856                     };
23857                     break;
23858                 case this.meta.successProperty:
23859                     return function(root, def) {
23860                         var sv = q.selectValue(key, root, true);
23861                         var success = sv !== false && sv !== 'false';
23862                         return success;
23863                     };
23864                     break;
23865                 default:
23866                     return function(root, def) {
23867                         return q.selectValue(key, root, def);
23868                     };
23869                     break;
23870             }
23871         };
23872     }(),
23873
23874     
23875     extractValues : function(data, items, len) {
23876         var f, values = {};
23877         for(var j = 0; j < len; j++){
23878             f = items[j];
23879             var v = this.ef[j](data);
23880             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
23881         }
23882         return values;
23883     }
23884 });
23885 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
23886     
23887     constructor: function(config){
23888         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
23889             reader: new Ext.data.XmlReader(config)
23890         }));
23891     }
23892 });
23893 Ext.reg('xmlstore', Ext.data.XmlStore);
23894 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
23895
23896     
23897     constructor: function(config) {
23898         config = config || {};
23899
23900         
23901         
23902         
23903         
23904         this.hasMultiSort  = true;
23905         this.multiSortInfo = this.multiSortInfo || {sorters: []};
23906
23907         var sorters    = this.multiSortInfo.sorters,
23908             groupField = config.groupField || this.groupField,
23909             sortInfo   = config.sortInfo || this.sortInfo,
23910             groupDir   = config.groupDir || this.groupDir;
23911
23912         
23913         if(groupField){
23914             sorters.push({
23915                 field    : groupField,
23916                 direction: groupDir
23917             });
23918         }
23919
23920         
23921         if (sortInfo) {
23922             sorters.push(sortInfo);
23923         }
23924
23925         Ext.data.GroupingStore.superclass.constructor.call(this, config);
23926
23927         this.addEvents(
23928           
23929           'groupchange'
23930         );
23931
23932         this.applyGroupField();
23933     },
23934
23935     
23936     
23937     remoteGroup : false,
23938     
23939     groupOnSort:false,
23940
23941     groupDir : 'ASC',
23942
23943     
23944     clearGrouping : function(){
23945         this.groupField = false;
23946
23947         if(this.remoteGroup){
23948             if(this.baseParams){
23949                 delete this.baseParams.groupBy;
23950                 delete this.baseParams.groupDir;
23951             }
23952             var lo = this.lastOptions;
23953             if(lo && lo.params){
23954                 delete lo.params.groupBy;
23955                 delete lo.params.groupDir;
23956             }
23957
23958             this.reload();
23959         }else{
23960             this.sort();
23961             this.fireEvent('datachanged', this);
23962         }
23963     },
23964
23965     
23966     groupBy : function(field, forceRegroup, direction) {
23967         direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
23968
23969         if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
23970             return; 
23971         }
23972
23973         
23974         
23975         var sorters = this.multiSortInfo.sorters;
23976         if (sorters.length > 0 && sorters[0].field == this.groupField) {
23977             sorters.shift();
23978         }
23979
23980         this.groupField = field;
23981         this.groupDir = direction;
23982         this.applyGroupField();
23983
23984         var fireGroupEvent = function() {
23985             this.fireEvent('groupchange', this, this.getGroupState());
23986         };
23987
23988         if (this.groupOnSort) {
23989             this.sort(field, direction);
23990             fireGroupEvent.call(this);
23991             return;
23992         }
23993
23994         if (this.remoteGroup) {
23995             this.on('load', fireGroupEvent, this, {single: true});
23996             this.reload();
23997         } else {
23998             this.sort(sorters);
23999             fireGroupEvent.call(this);
24000         }
24001     },
24002
24003     
24004     
24005     sort : function(fieldName, dir) {
24006         if (this.remoteSort) {
24007             return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
24008         }
24009
24010         var sorters = [];
24011
24012         
24013         if (Ext.isArray(arguments[0])) {
24014             sorters = arguments[0];
24015         } else if (fieldName == undefined) {
24016             
24017             
24018             sorters = this.sortInfo ? [this.sortInfo] : [];
24019         } else {
24020             
24021             
24022             var field = this.fields.get(fieldName);
24023             if (!field) return false;
24024
24025             var name       = field.name,
24026                 sortInfo   = this.sortInfo || null,
24027                 sortToggle = this.sortToggle ? this.sortToggle[name] : null;
24028
24029             if (!dir) {
24030                 if (sortInfo && sortInfo.field == name) { 
24031                     dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
24032                 } else {
24033                     dir = field.sortDir;
24034                 }
24035             }
24036
24037             this.sortToggle[name] = dir;
24038             this.sortInfo = {field: name, direction: dir};
24039
24040             sorters = [this.sortInfo];
24041         }
24042
24043         
24044         if (this.groupField) {
24045             sorters.unshift({direction: this.groupDir, field: this.groupField});
24046         }
24047
24048         return this.multiSort.call(this, sorters, dir);
24049     },
24050
24051     
24052     applyGroupField: function(){
24053         if (this.remoteGroup) {
24054             if(!this.baseParams){
24055                 this.baseParams = {};
24056             }
24057
24058             Ext.apply(this.baseParams, {
24059                 groupBy : this.groupField,
24060                 groupDir: this.groupDir
24061             });
24062
24063             var lo = this.lastOptions;
24064             if (lo && lo.params) {
24065                 lo.params.groupDir = this.groupDir;
24066
24067                 
24068                 delete lo.params.groupBy;
24069             }
24070         }
24071     },
24072
24073     
24074     applyGrouping : function(alwaysFireChange){
24075         if(this.groupField !== false){
24076             this.groupBy(this.groupField, true, this.groupDir);
24077             return true;
24078         }else{
24079             if(alwaysFireChange === true){
24080                 this.fireEvent('datachanged', this);
24081             }
24082             return false;
24083         }
24084     },
24085
24086     
24087     getGroupState : function(){
24088         return this.groupOnSort && this.groupField !== false ?
24089                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
24090     }
24091 });
24092 Ext.reg('groupingstore', Ext.data.GroupingStore);
24093
24094 Ext.data.DirectProxy = function(config){
24095     Ext.apply(this, config);
24096     if(typeof this.paramOrder == 'string'){
24097         this.paramOrder = this.paramOrder.split(/[\s,|]/);
24098     }
24099     Ext.data.DirectProxy.superclass.constructor.call(this, config);
24100 };
24101
24102 Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
24103     
24104     paramOrder: undefined,
24105
24106     
24107     paramsAsHash: true,
24108
24109     
24110     directFn : undefined,
24111
24112     
24113     doRequest : function(action, rs, params, reader, callback, scope, options) {
24114         var args = [],
24115             directFn = this.api[action] || this.directFn;
24116
24117         switch (action) {
24118             case Ext.data.Api.actions.create:
24119                 args.push(params.jsonData);             
24120                 break;
24121             case Ext.data.Api.actions.read:
24122                 
24123                 if(directFn.directCfg.method.len > 0){
24124                     if(this.paramOrder){
24125                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
24126                             args.push(params[this.paramOrder[i]]);
24127                         }
24128                     }else if(this.paramsAsHash){
24129                         args.push(params);
24130                     }
24131                 }
24132                 break;
24133             case Ext.data.Api.actions.update:
24134                 args.push(params.jsonData);        
24135                 break;
24136             case Ext.data.Api.actions.destroy:
24137                 args.push(params.jsonData);        
24138                 break;
24139         }
24140
24141         var trans = {
24142             params : params || {},
24143             request: {
24144                 callback : callback,
24145                 scope : scope,
24146                 arg : options
24147             },
24148             reader: reader
24149         };
24150
24151         args.push(this.createCallback(action, rs, trans), this);
24152         directFn.apply(window, args);
24153     },
24154
24155     
24156     createCallback : function(action, rs, trans) {
24157         var me = this;
24158         return function(result, res) {
24159             if (!res.status) {
24160                 
24161                 if (action === Ext.data.Api.actions.read) {
24162                     me.fireEvent("loadexception", me, trans, res, null);
24163                 }
24164                 me.fireEvent('exception', me, 'remote', action, trans, res, null);
24165                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
24166                 return;
24167             }
24168             if (action === Ext.data.Api.actions.read) {
24169                 me.onRead(action, trans, result, res);
24170             } else {
24171                 me.onWrite(action, trans, result, res, rs);
24172             }
24173         };
24174     },
24175
24176     
24177     onRead : function(action, trans, result, res) {
24178         var records;
24179         try {
24180             records = trans.reader.readRecords(result);
24181         }
24182         catch (ex) {
24183             
24184             this.fireEvent("loadexception", this, trans, res, ex);
24185
24186             this.fireEvent('exception', this, 'response', action, trans, res, ex);
24187             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
24188             return;
24189         }
24190         this.fireEvent("load", this, res, trans.request.arg);
24191         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
24192     },
24193     
24194     onWrite : function(action, trans, result, res, rs) {
24195         var data = trans.reader.extractData(trans.reader.getRoot(result), false);
24196         var success = trans.reader.getSuccess(result);
24197         success = (success !== false);
24198         if (success){
24199             this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
24200         }else{
24201             this.fireEvent('exception', this, 'remote', action, trans, result, rs);
24202         }
24203         trans.request.callback.call(trans.request.scope, data, res, success);
24204     }
24205 });
24206
24207 Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
24208     constructor : function(config){
24209         
24210         var c = Ext.apply({}, {
24211             batchTransactions: false
24212         }, config);
24213         Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
24214             proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
24215             reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
24216         }));
24217     }
24218 });
24219 Ext.reg('directstore', Ext.data.DirectStore);
24220
24221 Ext.Direct = Ext.extend(Ext.util.Observable, {
24222     
24223
24224     
24225     exceptions: {
24226         TRANSPORT: 'xhr',
24227         PARSE: 'parse',
24228         LOGIN: 'login',
24229         SERVER: 'exception'
24230     },
24231
24232     
24233     constructor: function(){
24234         this.addEvents(
24235             
24236             'event',
24237             
24238             'exception'
24239         );
24240         this.transactions = {};
24241         this.providers = {};
24242     },
24243
24244     
24245     addProvider : function(provider){
24246         var a = arguments;
24247         if(a.length > 1){
24248             for(var i = 0, len = a.length; i < len; i++){
24249                 this.addProvider(a[i]);
24250             }
24251             return;
24252         }
24253
24254         
24255         if(!provider.events){
24256             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
24257         }
24258         provider.id = provider.id || Ext.id();
24259         this.providers[provider.id] = provider;
24260
24261         provider.on('data', this.onProviderData, this);
24262         provider.on('exception', this.onProviderException, this);
24263
24264
24265         if(!provider.isConnected()){
24266             provider.connect();
24267         }
24268
24269         return provider;
24270     },
24271
24272     
24273     getProvider : function(id){
24274         return this.providers[id];
24275     },
24276
24277     removeProvider : function(id){
24278         var provider = id.id ? id : this.providers[id];
24279         provider.un('data', this.onProviderData, this);
24280         provider.un('exception', this.onProviderException, this);
24281         delete this.providers[provider.id];
24282         return provider;
24283     },
24284
24285     addTransaction: function(t){
24286         this.transactions[t.tid] = t;
24287         return t;
24288     },
24289
24290     removeTransaction: function(t){
24291         delete this.transactions[t.tid || t];
24292         return t;
24293     },
24294
24295     getTransaction: function(tid){
24296         return this.transactions[tid.tid || tid];
24297     },
24298
24299     onProviderData : function(provider, e){
24300         if(Ext.isArray(e)){
24301             for(var i = 0, len = e.length; i < len; i++){
24302                 this.onProviderData(provider, e[i]);
24303             }
24304             return;
24305         }
24306         if(e.name && e.name != 'event' && e.name != 'exception'){
24307             this.fireEvent(e.name, e);
24308         }else if(e.type == 'exception'){
24309             this.fireEvent('exception', e);
24310         }
24311         this.fireEvent('event', e, provider);
24312     },
24313
24314     createEvent : function(response, extraProps){
24315         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
24316     }
24317 });
24318
24319 Ext.Direct = new Ext.Direct();
24320
24321 Ext.Direct.TID = 1;
24322 Ext.Direct.PROVIDERS = {};
24323 Ext.Direct.Transaction = function(config){
24324     Ext.apply(this, config);
24325     this.tid = ++Ext.Direct.TID;
24326     this.retryCount = 0;
24327 };
24328 Ext.Direct.Transaction.prototype = {
24329     send: function(){
24330         this.provider.queueTransaction(this);
24331     },
24332
24333     retry: function(){
24334         this.retryCount++;
24335         this.send();
24336     },
24337
24338     getProvider: function(){
24339         return this.provider;
24340     }
24341 };Ext.Direct.Event = function(config){
24342     Ext.apply(this, config);
24343 };
24344
24345 Ext.Direct.Event.prototype = {
24346     status: true,
24347     getData: function(){
24348         return this.data;
24349     }
24350 };
24351
24352 Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
24353     type: 'rpc',
24354     getTransaction: function(){
24355         return this.transaction || Ext.Direct.getTransaction(this.tid);
24356     }
24357 });
24358
24359 Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
24360     status: false,
24361     type: 'exception'
24362 });
24363
24364 Ext.Direct.eventTypes = {
24365     'rpc':  Ext.Direct.RemotingEvent,
24366     'event':  Ext.Direct.Event,
24367     'exception':  Ext.Direct.ExceptionEvent
24368 };
24369
24370 Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
24371     
24372         
24373         
24374     priority: 1,
24375
24376         
24377  
24378     
24379     constructor : function(config){
24380         Ext.apply(this, config);
24381         this.addEvents(
24382                         
24383             'connect',
24384                         
24385             'disconnect',
24386                         
24387             'data',
24388                                     
24389             'exception'
24390         );
24391         Ext.direct.Provider.superclass.constructor.call(this, config);
24392     },
24393
24394     
24395     isConnected: function(){
24396         return false;
24397     },
24398
24399     
24400     connect: Ext.emptyFn,
24401     
24402     
24403     disconnect: Ext.emptyFn
24404 });
24405
24406 Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
24407     parseResponse: function(xhr){
24408         if(!Ext.isEmpty(xhr.responseText)){
24409             if(typeof xhr.responseText == 'object'){
24410                 return xhr.responseText;
24411             }
24412             return Ext.decode(xhr.responseText);
24413         }
24414         return null;
24415     },
24416
24417     getEvents: function(xhr){
24418         var data = null;
24419         try{
24420             data = this.parseResponse(xhr);
24421         }catch(e){
24422             var event = new Ext.Direct.ExceptionEvent({
24423                 data: e,
24424                 xhr: xhr,
24425                 code: Ext.Direct.exceptions.PARSE,
24426                 message: 'Error parsing json response: \n\n ' + data
24427             });
24428             return [event];
24429         }
24430         var events = [];
24431         if(Ext.isArray(data)){
24432             for(var i = 0, len = data.length; i < len; i++){
24433                 events.push(Ext.Direct.createEvent(data[i]));
24434             }
24435         }else{
24436             events.push(Ext.Direct.createEvent(data));
24437         }
24438         return events;
24439     }
24440 });
24441 Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
24442     
24443     
24444     priority: 3,
24445     
24446     
24447     interval: 3000,
24448
24449     
24450     
24451     
24452
24453     
24454     constructor : function(config){
24455         Ext.direct.PollingProvider.superclass.constructor.call(this, config);
24456         this.addEvents(
24457             
24458             'beforepoll',            
24459             
24460             'poll'
24461         );
24462     },
24463
24464     
24465     isConnected: function(){
24466         return !!this.pollTask;
24467     },
24468
24469     
24470     connect: function(){
24471         if(this.url && !this.pollTask){
24472             this.pollTask = Ext.TaskMgr.start({
24473                 run: function(){
24474                     if(this.fireEvent('beforepoll', this) !== false){
24475                         if(typeof this.url == 'function'){
24476                             this.url(this.baseParams);
24477                         }else{
24478                             Ext.Ajax.request({
24479                                 url: this.url,
24480                                 callback: this.onData,
24481                                 scope: this,
24482                                 params: this.baseParams
24483                             });
24484                         }
24485                     }
24486                 },
24487                 interval: this.interval,
24488                 scope: this
24489             });
24490             this.fireEvent('connect', this);
24491         }else if(!this.url){
24492             throw 'Error initializing PollingProvider, no url configured.';
24493         }
24494     },
24495
24496     
24497     disconnect: function(){
24498         if(this.pollTask){
24499             Ext.TaskMgr.stop(this.pollTask);
24500             delete this.pollTask;
24501             this.fireEvent('disconnect', this);
24502         }
24503     },
24504
24505     
24506     onData: function(opt, success, xhr){
24507         if(success){
24508             var events = this.getEvents(xhr);
24509             for(var i = 0, len = events.length; i < len; i++){
24510                 var e = events[i];
24511                 this.fireEvent('data', this, e);
24512             }
24513         }else{
24514             var e = new Ext.Direct.ExceptionEvent({
24515                 data: e,
24516                 code: Ext.Direct.exceptions.TRANSPORT,
24517                 message: 'Unable to connect to the server.',
24518                 xhr: xhr
24519             });
24520             this.fireEvent('data', this, e);
24521         }
24522     }
24523 });
24524
24525 Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
24526 Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
24527     
24528     
24529     
24530     
24531     
24532     
24533     
24534     
24535     
24536     enableBuffer: 10,
24537     
24538     
24539     maxRetries: 1,
24540     
24541     
24542     timeout: undefined,
24543
24544     constructor : function(config){
24545         Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
24546         this.addEvents(
24547                         
24548             'beforecall',            
24549                         
24550             'call'
24551         );
24552         this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
24553         this.transactions = {};
24554         this.callBuffer = [];
24555     },
24556
24557     
24558     initAPI : function(){
24559         var o = this.actions;
24560         for(var c in o){
24561             var cls = this.namespace[c] || (this.namespace[c] = {}),
24562                 ms = o[c];
24563             for(var i = 0, len = ms.length; i < len; i++){
24564                 var m = ms[i];
24565                 cls[m.name] = this.createMethod(c, m);
24566             }
24567         }
24568     },
24569
24570     
24571     isConnected: function(){
24572         return !!this.connected;
24573     },
24574
24575     connect: function(){
24576         if(this.url){
24577             this.initAPI();
24578             this.connected = true;
24579             this.fireEvent('connect', this);
24580         }else if(!this.url){
24581             throw 'Error initializing RemotingProvider, no url configured.';
24582         }
24583     },
24584
24585     disconnect: function(){
24586         if(this.connected){
24587             this.connected = false;
24588             this.fireEvent('disconnect', this);
24589         }
24590     },
24591
24592     onData: function(opt, success, xhr){
24593         if(success){
24594             var events = this.getEvents(xhr);
24595             for(var i = 0, len = events.length; i < len; i++){
24596                 var e = events[i],
24597                     t = this.getTransaction(e);
24598                 this.fireEvent('data', this, e);
24599                 if(t){
24600                     this.doCallback(t, e, true);
24601                     Ext.Direct.removeTransaction(t);
24602                 }
24603             }
24604         }else{
24605             var ts = [].concat(opt.ts);
24606             for(var i = 0, len = ts.length; i < len; i++){
24607                 var t = this.getTransaction(ts[i]);
24608                 if(t && t.retryCount < this.maxRetries){
24609                     t.retry();
24610                 }else{
24611                     var e = new Ext.Direct.ExceptionEvent({
24612                         data: e,
24613                         transaction: t,
24614                         code: Ext.Direct.exceptions.TRANSPORT,
24615                         message: 'Unable to connect to the server.',
24616                         xhr: xhr
24617                     });
24618                     this.fireEvent('data', this, e);
24619                     if(t){
24620                         this.doCallback(t, e, false);
24621                         Ext.Direct.removeTransaction(t);
24622                     }
24623                 }
24624             }
24625         }
24626     },
24627
24628     getCallData: function(t){
24629         return {
24630             action: t.action,
24631             method: t.method,
24632             data: t.data,
24633             type: 'rpc',
24634             tid: t.tid
24635         };
24636     },
24637
24638     doSend : function(data){
24639         var o = {
24640             url: this.url,
24641             callback: this.onData,
24642             scope: this,
24643             ts: data,
24644             timeout: this.timeout
24645         }, callData;
24646
24647         if(Ext.isArray(data)){
24648             callData = [];
24649             for(var i = 0, len = data.length; i < len; i++){
24650                 callData.push(this.getCallData(data[i]));
24651             }
24652         }else{
24653             callData = this.getCallData(data);
24654         }
24655
24656         if(this.enableUrlEncode){
24657             var params = {};
24658             params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
24659             o.params = params;
24660         }else{
24661             o.jsonData = callData;
24662         }
24663         Ext.Ajax.request(o);
24664     },
24665
24666     combineAndSend : function(){
24667         var len = this.callBuffer.length;
24668         if(len > 0){
24669             this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
24670             this.callBuffer = [];
24671         }
24672     },
24673
24674     queueTransaction: function(t){
24675         if(t.form){
24676             this.processForm(t);
24677             return;
24678         }
24679         this.callBuffer.push(t);
24680         if(this.enableBuffer){
24681             if(!this.callTask){
24682                 this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
24683             }
24684             this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
24685         }else{
24686             this.combineAndSend();
24687         }
24688     },
24689
24690     doCall : function(c, m, args){
24691         var data = null, hs = args[m.len], scope = args[m.len+1];
24692
24693         if(m.len !== 0){
24694             data = args.slice(0, m.len);
24695         }
24696
24697         var t = new Ext.Direct.Transaction({
24698             provider: this,
24699             args: args,
24700             action: c,
24701             method: m.name,
24702             data: data,
24703             cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
24704         });
24705
24706         if(this.fireEvent('beforecall', this, t, m) !== false){
24707             Ext.Direct.addTransaction(t);
24708             this.queueTransaction(t);
24709             this.fireEvent('call', this, t, m);
24710         }
24711     },
24712
24713     doForm : function(c, m, form, callback, scope){
24714         var t = new Ext.Direct.Transaction({
24715             provider: this,
24716             action: c,
24717             method: m.name,
24718             args:[form, callback, scope],
24719             cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
24720             isForm: true
24721         });
24722
24723         if(this.fireEvent('beforecall', this, t, m) !== false){
24724             Ext.Direct.addTransaction(t);
24725             var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
24726                 params = {
24727                     extTID: t.tid,
24728                     extAction: c,
24729                     extMethod: m.name,
24730                     extType: 'rpc',
24731                     extUpload: String(isUpload)
24732                 };
24733             
24734             
24735             
24736             Ext.apply(t, {
24737                 form: Ext.getDom(form),
24738                 isUpload: isUpload,
24739                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
24740             });
24741             this.fireEvent('call', this, t, m);
24742             this.processForm(t);
24743         }
24744     },
24745     
24746     processForm: function(t){
24747         Ext.Ajax.request({
24748             url: this.url,
24749             params: t.params,
24750             callback: this.onData,
24751             scope: this,
24752             form: t.form,
24753             isUpload: t.isUpload,
24754             ts: t
24755         });
24756     },
24757
24758     createMethod : function(c, m){
24759         var f;
24760         if(!m.formHandler){
24761             f = function(){
24762                 this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
24763             }.createDelegate(this);
24764         }else{
24765             f = function(form, callback, scope){
24766                 this.doForm(c, m, form, callback, scope);
24767             }.createDelegate(this);
24768         }
24769         f.directCfg = {
24770             action: c,
24771             method: m
24772         };
24773         return f;
24774     },
24775
24776     getTransaction: function(opt){
24777         return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
24778     },
24779
24780     doCallback: function(t, e){
24781         var fn = e.status ? 'success' : 'failure';
24782         if(t && t.cb){
24783             var hs = t.cb,
24784                 result = Ext.isDefined(e.result) ? e.result : e.data;
24785             if(Ext.isFunction(hs)){
24786                 hs(result, e);
24787             } else{
24788                 Ext.callback(hs[fn], hs.scope, [result, e]);
24789                 Ext.callback(hs.callback, hs.scope, [result, e]);
24790             }
24791         }
24792     }
24793 });
24794 Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
24795 Ext.Resizable = Ext.extend(Ext.util.Observable, {
24796
24797     constructor: function(el, config){
24798         this.el = Ext.get(el);
24799         if(config && config.wrap){
24800             config.resizeChild = this.el;
24801             this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
24802             this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
24803             this.el.setStyle('overflow', 'hidden');
24804             this.el.setPositioning(config.resizeChild.getPositioning());
24805             config.resizeChild.clearPositioning();
24806             if(!config.width || !config.height){
24807                 var csize = config.resizeChild.getSize();
24808                 this.el.setSize(csize.width, csize.height);
24809             }
24810             if(config.pinned && !config.adjustments){
24811                 config.adjustments = 'auto';
24812             }
24813         }
24814
24815         
24816         this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
24817         this.proxy.unselectable();
24818         this.proxy.enableDisplayMode('block');
24819
24820         Ext.apply(this, config);
24821
24822         if(this.pinned){
24823             this.disableTrackOver = true;
24824             this.el.addClass('x-resizable-pinned');
24825         }
24826         
24827         var position = this.el.getStyle('position');
24828         if(position != 'absolute' && position != 'fixed'){
24829             this.el.setStyle('position', 'relative');
24830         }
24831         if(!this.handles){ 
24832             this.handles = 's,e,se';
24833             if(this.multiDirectional){
24834                 this.handles += ',n,w';
24835             }
24836         }
24837         if(this.handles == 'all'){
24838             this.handles = 'n s e w ne nw se sw';
24839         }
24840         var hs = this.handles.split(/\s*?[,;]\s*?| /);
24841         var ps = Ext.Resizable.positions;
24842         for(var i = 0, len = hs.length; i < len; i++){
24843             if(hs[i] && ps[hs[i]]){
24844                 var pos = ps[hs[i]];
24845                 this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
24846             }
24847         }
24848         
24849         this.corner = this.southeast;
24850
24851         if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
24852             this.updateBox = true;
24853         }
24854
24855         this.activeHandle = null;
24856
24857         if(this.resizeChild){
24858             if(typeof this.resizeChild == 'boolean'){
24859                 this.resizeChild = Ext.get(this.el.dom.firstChild, true);
24860             }else{
24861                 this.resizeChild = Ext.get(this.resizeChild, true);
24862             }
24863         }
24864
24865         if(this.adjustments == 'auto'){
24866             var rc = this.resizeChild;
24867             var hw = this.west, he = this.east, hn = this.north, hs = this.south;
24868             if(rc && (hw || hn)){
24869                 rc.position('relative');
24870                 rc.setLeft(hw ? hw.el.getWidth() : 0);
24871                 rc.setTop(hn ? hn.el.getHeight() : 0);
24872             }
24873             this.adjustments = [
24874                 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
24875                 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
24876             ];
24877         }
24878
24879         if(this.draggable){
24880             this.dd = this.dynamic ?
24881                 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
24882             this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
24883             if(this.constrainTo){
24884                 this.dd.constrainTo(this.constrainTo);
24885             }
24886         }
24887
24888         this.addEvents(
24889             
24890             'beforeresize',
24891             
24892             'resize'
24893         );
24894
24895         if(this.width !== null && this.height !== null){
24896             this.resizeTo(this.width, this.height);
24897         }else{
24898             this.updateChildSize();
24899         }
24900         if(Ext.isIE){
24901             this.el.dom.style.zoom = 1;
24902         }
24903         Ext.Resizable.superclass.constructor.call(this);
24904     },
24905
24906     
24907     adjustments : [0, 0],
24908     
24909     animate : false,
24910     
24911     
24912     disableTrackOver : false,
24913     
24914     draggable: false,
24915     
24916     duration : 0.35,
24917     
24918     dynamic : false,
24919     
24920     easing : 'easeOutStrong',
24921     
24922     enabled : true,
24923     
24924     
24925     handles : false,
24926     
24927     multiDirectional : false,
24928     
24929     height : null,
24930     
24931     width : null,
24932     
24933     heightIncrement : 0,
24934     
24935     widthIncrement : 0,
24936     
24937     minHeight : 5,
24938     
24939     minWidth : 5,
24940     
24941     maxHeight : 10000,
24942     
24943     maxWidth : 10000,
24944     
24945     minX: 0,
24946     
24947     minY: 0,
24948     
24949     pinned : false,
24950     
24951     preserveRatio : false,
24952     
24953     resizeChild : false,
24954     
24955     transparent: false,
24956     
24957     
24958     
24959
24960
24961     
24962     resizeTo : function(width, height){
24963         this.el.setSize(width, height);
24964         this.updateChildSize();
24965         this.fireEvent('resize', this, width, height, null);
24966     },
24967
24968     
24969     startSizing : function(e, handle){
24970         this.fireEvent('beforeresize', this, e);
24971         if(this.enabled){ 
24972
24973             if(!this.overlay){
24974                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
24975                 this.overlay.unselectable();
24976                 this.overlay.enableDisplayMode('block');
24977                 this.overlay.on({
24978                     scope: this,
24979                     mousemove: this.onMouseMove,
24980                     mouseup: this.onMouseUp
24981                 });
24982             }
24983             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
24984
24985             this.resizing = true;
24986             this.startBox = this.el.getBox();
24987             this.startPoint = e.getXY();
24988             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
24989                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
24990
24991             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
24992             this.overlay.show();
24993
24994             if(this.constrainTo) {
24995                 var ct = Ext.get(this.constrainTo);
24996                 this.resizeRegion = ct.getRegion().adjust(
24997                     ct.getFrameWidth('t'),
24998                     ct.getFrameWidth('l'),
24999                     -ct.getFrameWidth('b'),
25000                     -ct.getFrameWidth('r')
25001                 );
25002             }
25003
25004             this.proxy.setStyle('visibility', 'hidden'); 
25005             this.proxy.show();
25006             this.proxy.setBox(this.startBox);
25007             if(!this.dynamic){
25008                 this.proxy.setStyle('visibility', 'visible');
25009             }
25010         }
25011     },
25012
25013     
25014     onMouseDown : function(handle, e){
25015         if(this.enabled){
25016             e.stopEvent();
25017             this.activeHandle = handle;
25018             this.startSizing(e, handle);
25019         }
25020     },
25021
25022     
25023     onMouseUp : function(e){
25024         this.activeHandle = null;
25025         var size = this.resizeElement();
25026         this.resizing = false;
25027         this.handleOut();
25028         this.overlay.hide();
25029         this.proxy.hide();
25030         this.fireEvent('resize', this, size.width, size.height, e);
25031     },
25032
25033     
25034     updateChildSize : function(){
25035         if(this.resizeChild){
25036             var el = this.el;
25037             var child = this.resizeChild;
25038             var adj = this.adjustments;
25039             if(el.dom.offsetWidth){
25040                 var b = el.getSize(true);
25041                 child.setSize(b.width+adj[0], b.height+adj[1]);
25042             }
25043             
25044             
25045             
25046             
25047             if(Ext.isIE){
25048                 setTimeout(function(){
25049                     if(el.dom.offsetWidth){
25050                         var b = el.getSize(true);
25051                         child.setSize(b.width+adj[0], b.height+adj[1]);
25052                     }
25053                 }, 10);
25054             }
25055         }
25056     },
25057
25058     
25059     snap : function(value, inc, min){
25060         if(!inc || !value){
25061             return value;
25062         }
25063         var newValue = value;
25064         var m = value % inc;
25065         if(m > 0){
25066             if(m > (inc/2)){
25067                 newValue = value + (inc-m);
25068             }else{
25069                 newValue = value - m;
25070             }
25071         }
25072         return Math.max(min, newValue);
25073     },
25074
25075     
25076     resizeElement : function(){
25077         var box = this.proxy.getBox();
25078         if(this.updateBox){
25079             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
25080         }else{
25081             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
25082         }
25083         this.updateChildSize();
25084         if(!this.dynamic){
25085             this.proxy.hide();
25086         }
25087         if(this.draggable && this.constrainTo){
25088             this.dd.resetConstraints();
25089             this.dd.constrainTo(this.constrainTo);
25090         }
25091         return box;
25092     },
25093
25094     
25095     constrain : function(v, diff, m, mx){
25096         if(v - diff < m){
25097             diff = v - m;
25098         }else if(v - diff > mx){
25099             diff = v - mx;
25100         }
25101         return diff;
25102     },
25103
25104     
25105     onMouseMove : function(e){
25106         if(this.enabled && this.activeHandle){
25107             try{
25108
25109             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
25110                 return;
25111             }
25112
25113             
25114             var curSize = this.curSize || this.startBox,
25115                 x = this.startBox.x, y = this.startBox.y,
25116                 ox = x,
25117                 oy = y,
25118                 w = curSize.width,
25119                 h = curSize.height,
25120                 ow = w,
25121                 oh = h,
25122                 mw = this.minWidth,
25123                 mh = this.minHeight,
25124                 mxw = this.maxWidth,
25125                 mxh = this.maxHeight,
25126                 wi = this.widthIncrement,
25127                 hi = this.heightIncrement,
25128                 eventXY = e.getXY(),
25129                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
25130                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
25131                 pos = this.activeHandle.position,
25132                 tw,
25133                 th;
25134
25135             switch(pos){
25136                 case 'east':
25137                     w += diffX;
25138                     w = Math.min(Math.max(mw, w), mxw);
25139                     break;
25140                 case 'south':
25141                     h += diffY;
25142                     h = Math.min(Math.max(mh, h), mxh);
25143                     break;
25144                 case 'southeast':
25145                     w += diffX;
25146                     h += diffY;
25147                     w = Math.min(Math.max(mw, w), mxw);
25148                     h = Math.min(Math.max(mh, h), mxh);
25149                     break;
25150                 case 'north':
25151                     diffY = this.constrain(h, diffY, mh, mxh);
25152                     y += diffY;
25153                     h -= diffY;
25154                     break;
25155                 case 'west':
25156                     diffX = this.constrain(w, diffX, mw, mxw);
25157                     x += diffX;
25158                     w -= diffX;
25159                     break;
25160                 case 'northeast':
25161                     w += diffX;
25162                     w = Math.min(Math.max(mw, w), mxw);
25163                     diffY = this.constrain(h, diffY, mh, mxh);
25164                     y += diffY;
25165                     h -= diffY;
25166                     break;
25167                 case 'northwest':
25168                     diffX = this.constrain(w, diffX, mw, mxw);
25169                     diffY = this.constrain(h, diffY, mh, mxh);
25170                     y += diffY;
25171                     h -= diffY;
25172                     x += diffX;
25173                     w -= diffX;
25174                     break;
25175                case 'southwest':
25176                     diffX = this.constrain(w, diffX, mw, mxw);
25177                     h += diffY;
25178                     h = Math.min(Math.max(mh, h), mxh);
25179                     x += diffX;
25180                     w -= diffX;
25181                     break;
25182             }
25183
25184             var sw = this.snap(w, wi, mw);
25185             var sh = this.snap(h, hi, mh);
25186             if(sw != w || sh != h){
25187                 switch(pos){
25188                     case 'northeast':
25189                         y -= sh - h;
25190                     break;
25191                     case 'north':
25192                         y -= sh - h;
25193                         break;
25194                     case 'southwest':
25195                         x -= sw - w;
25196                     break;
25197                     case 'west':
25198                         x -= sw - w;
25199                         break;
25200                     case 'northwest':
25201                         x -= sw - w;
25202                         y -= sh - h;
25203                     break;
25204                 }
25205                 w = sw;
25206                 h = sh;
25207             }
25208
25209             if(this.preserveRatio){
25210                 switch(pos){
25211                     case 'southeast':
25212                     case 'east':
25213                         h = oh * (w/ow);
25214                         h = Math.min(Math.max(mh, h), mxh);
25215                         w = ow * (h/oh);
25216                        break;
25217                     case 'south':
25218                         w = ow * (h/oh);
25219                         w = Math.min(Math.max(mw, w), mxw);
25220                         h = oh * (w/ow);
25221                         break;
25222                     case 'northeast':
25223                         w = ow * (h/oh);
25224                         w = Math.min(Math.max(mw, w), mxw);
25225                         h = oh * (w/ow);
25226                     break;
25227                     case 'north':
25228                         tw = w;
25229                         w = ow * (h/oh);
25230                         w = Math.min(Math.max(mw, w), mxw);
25231                         h = oh * (w/ow);
25232                         x += (tw - w) / 2;
25233                         break;
25234                     case 'southwest':
25235                         h = oh * (w/ow);
25236                         h = Math.min(Math.max(mh, h), mxh);
25237                         tw = w;
25238                         w = ow * (h/oh);
25239                         x += tw - w;
25240                         break;
25241                     case 'west':
25242                         th = h;
25243                         h = oh * (w/ow);
25244                         h = Math.min(Math.max(mh, h), mxh);
25245                         y += (th - h) / 2;
25246                         tw = w;
25247                         w = ow * (h/oh);
25248                         x += tw - w;
25249                        break;
25250                     case 'northwest':
25251                         tw = w;
25252                         th = h;
25253                         h = oh * (w/ow);
25254                         h = Math.min(Math.max(mh, h), mxh);
25255                         w = ow * (h/oh);
25256                         y += th - h;
25257                         x += tw - w;
25258                         break;
25259
25260                 }
25261             }
25262             this.proxy.setBounds(x, y, w, h);
25263             if(this.dynamic){
25264                 this.resizeElement();
25265             }
25266             }catch(ex){}
25267         }
25268     },
25269
25270     
25271     handleOver : function(){
25272         if(this.enabled){
25273             this.el.addClass('x-resizable-over');
25274         }
25275     },
25276
25277     
25278     handleOut : function(){
25279         if(!this.resizing){
25280             this.el.removeClass('x-resizable-over');
25281         }
25282     },
25283
25284     
25285     getEl : function(){
25286         return this.el;
25287     },
25288
25289     
25290     getResizeChild : function(){
25291         return this.resizeChild;
25292     },
25293
25294     
25295     destroy : function(removeEl){
25296         Ext.destroy(this.dd, this.overlay, this.proxy);
25297         this.overlay = null;
25298         this.proxy = null;
25299
25300         var ps = Ext.Resizable.positions;
25301         for(var k in ps){
25302             if(typeof ps[k] != 'function' && this[ps[k]]){
25303                 this[ps[k]].destroy();
25304             }
25305         }
25306         if(removeEl){
25307             this.el.update('');
25308             Ext.destroy(this.el);
25309             this.el = null;
25310         }
25311         this.purgeListeners();
25312     },
25313
25314     syncHandleHeight : function(){
25315         var h = this.el.getHeight(true);
25316         if(this.west){
25317             this.west.el.setHeight(h);
25318         }
25319         if(this.east){
25320             this.east.el.setHeight(h);
25321         }
25322     }
25323 });
25324
25325
25326
25327 Ext.Resizable.positions = {
25328     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
25329 };
25330
25331 Ext.Resizable.Handle = Ext.extend(Object, {
25332     constructor : function(rz, pos, disableTrackOver, transparent, cls){
25333        if(!this.tpl){
25334             
25335             var tpl = Ext.DomHelper.createTemplate(
25336                 {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
25337             );
25338             tpl.compile();
25339             Ext.Resizable.Handle.prototype.tpl = tpl;
25340         }
25341         this.position = pos;
25342         this.rz = rz;
25343         this.el = this.tpl.append(rz.el.dom, [this.position], true);
25344         this.el.unselectable();
25345         if(transparent){
25346             this.el.setOpacity(0);
25347         }
25348         if(!Ext.isEmpty(cls)){
25349             this.el.addClass(cls);
25350         }
25351         this.el.on('mousedown', this.onMouseDown, this);
25352         if(!disableTrackOver){
25353             this.el.on({
25354                 scope: this,
25355                 mouseover: this.onMouseOver,
25356                 mouseout: this.onMouseOut
25357             });
25358         }
25359     },
25360
25361     
25362     afterResize : function(rz){
25363         
25364     },
25365     
25366     onMouseDown : function(e){
25367         this.rz.onMouseDown(this, e);
25368     },
25369     
25370     onMouseOver : function(e){
25371         this.rz.handleOver(this, e);
25372     },
25373     
25374     onMouseOut : function(e){
25375         this.rz.handleOut(this, e);
25376     },
25377     
25378     destroy : function(){
25379         Ext.destroy(this.el);
25380         this.el = null;
25381     }
25382 });
25383
25384 Ext.Window = Ext.extend(Ext.Panel, {
25385     
25386     
25387     
25388     
25389     
25390     
25391     
25392     
25393     
25394     
25395
25396     
25397     baseCls : 'x-window',
25398     
25399     resizable : true,
25400     
25401     draggable : true,
25402     
25403     closable : true,
25404     
25405     closeAction : 'close',
25406     
25407     constrain : false,
25408     
25409     constrainHeader : false,
25410     
25411     plain : false,
25412     
25413     minimizable : false,
25414     
25415     maximizable : false,
25416     
25417     minHeight : 100,
25418     
25419     minWidth : 200,
25420     
25421     expandOnShow : true,
25422
25423     
25424     collapsible : false,
25425
25426     
25427     initHidden : undefined,
25428
25429     
25430     hidden : true,
25431
25432     
25433     
25434     
25435     
25436     
25437     elements : 'header,body',
25438     
25439     frame : true,
25440     
25441     floating : true,
25442
25443     
25444     initComponent : function(){
25445         this.initTools();
25446         Ext.Window.superclass.initComponent.call(this);
25447         this.addEvents(
25448             
25449             
25450             
25451             'resize',
25452             
25453             'maximize',
25454             
25455             'minimize',
25456             
25457             'restore'
25458         );
25459         
25460         if(Ext.isDefined(this.initHidden)){
25461             this.hidden = this.initHidden;
25462         }
25463         if(this.hidden === false){
25464             this.hidden = true;
25465             this.show();
25466         }
25467     },
25468
25469     
25470     getState : function(){
25471         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
25472     },
25473
25474     
25475     onRender : function(ct, position){
25476         Ext.Window.superclass.onRender.call(this, ct, position);
25477
25478         if(this.plain){
25479             this.el.addClass('x-window-plain');
25480         }
25481
25482         
25483         this.focusEl = this.el.createChild({
25484                     tag: 'a', href:'#', cls:'x-dlg-focus',
25485                     tabIndex:'-1', html: '&#160;'});
25486         this.focusEl.swallowEvent('click', true);
25487
25488         this.proxy = this.el.createProxy('x-window-proxy');
25489         this.proxy.enableDisplayMode('block');
25490
25491         if(this.modal){
25492             this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
25493             this.mask.enableDisplayMode('block');
25494             this.mask.hide();
25495             this.mon(this.mask, 'click', this.focus, this);
25496         }
25497         if(this.maximizable){
25498             this.mon(this.header, 'dblclick', this.toggleMaximize, this);
25499         }
25500     },
25501
25502     
25503     initEvents : function(){
25504         Ext.Window.superclass.initEvents.call(this);
25505         if(this.animateTarget){
25506             this.setAnimateTarget(this.animateTarget);
25507         }
25508
25509         if(this.resizable){
25510             this.resizer = new Ext.Resizable(this.el, {
25511                 minWidth: this.minWidth,
25512                 minHeight:this.minHeight,
25513                 handles: this.resizeHandles || 'all',
25514                 pinned: true,
25515                 resizeElement : this.resizerAction,
25516                 handleCls: 'x-window-handle'
25517             });
25518             this.resizer.window = this;
25519             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
25520         }
25521
25522         if(this.draggable){
25523             this.header.addClass('x-window-draggable');
25524         }
25525         this.mon(this.el, 'mousedown', this.toFront, this);
25526         this.manager = this.manager || Ext.WindowMgr;
25527         this.manager.register(this);
25528         if(this.maximized){
25529             this.maximized = false;
25530             this.maximize();
25531         }
25532         if(this.closable){
25533             var km = this.getKeyMap();
25534             km.on(27, this.onEsc, this);
25535             km.disable();
25536         }
25537     },
25538
25539     initDraggable : function(){
25540         
25541         this.dd = new Ext.Window.DD(this);
25542     },
25543
25544    
25545     onEsc : function(k, e){
25546         e.stopEvent();
25547         this[this.closeAction]();
25548     },
25549
25550     
25551     beforeDestroy : function(){
25552         if(this.rendered){
25553             this.hide();
25554             this.clearAnchor();
25555             Ext.destroy(
25556                 this.focusEl,
25557                 this.resizer,
25558                 this.dd,
25559                 this.proxy,
25560                 this.mask
25561             );
25562         }
25563         Ext.Window.superclass.beforeDestroy.call(this);
25564     },
25565
25566     
25567     onDestroy : function(){
25568         if(this.manager){
25569             this.manager.unregister(this);
25570         }
25571         Ext.Window.superclass.onDestroy.call(this);
25572     },
25573
25574     
25575     initTools : function(){
25576         if(this.minimizable){
25577             this.addTool({
25578                 id: 'minimize',
25579                 handler: this.minimize.createDelegate(this, [])
25580             });
25581         }
25582         if(this.maximizable){
25583             this.addTool({
25584                 id: 'maximize',
25585                 handler: this.maximize.createDelegate(this, [])
25586             });
25587             this.addTool({
25588                 id: 'restore',
25589                 handler: this.restore.createDelegate(this, []),
25590                 hidden:true
25591             });
25592         }
25593         if(this.closable){
25594             this.addTool({
25595                 id: 'close',
25596                 handler: this[this.closeAction].createDelegate(this, [])
25597             });
25598         }
25599     },
25600
25601     
25602     resizerAction : function(){
25603         var box = this.proxy.getBox();
25604         this.proxy.hide();
25605         this.window.handleResize(box);
25606         return box;
25607     },
25608
25609     
25610     beforeResize : function(){
25611         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
25612         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
25613         this.resizeBox = this.el.getBox();
25614     },
25615
25616     
25617     updateHandles : function(){
25618         if(Ext.isIE && this.resizer){
25619             this.resizer.syncHandleHeight();
25620             this.el.repaint();
25621         }
25622     },
25623
25624     
25625     handleResize : function(box){
25626         var rz = this.resizeBox;
25627         if(rz.x != box.x || rz.y != box.y){
25628             this.updateBox(box);
25629         }else{
25630             this.setSize(box);
25631             if (Ext.isIE6 && Ext.isStrict) {
25632                 this.doLayout();
25633             }
25634         }
25635         this.focus();
25636         this.updateHandles();
25637         this.saveState();
25638     },
25639
25640     
25641     focus : function(){
25642         var f = this.focusEl,
25643             db = this.defaultButton,
25644             t = typeof db,
25645             el,
25646             ct;
25647         if(Ext.isDefined(db)){
25648             if(Ext.isNumber(db) && this.fbar){
25649                 f = this.fbar.items.get(db);
25650             }else if(Ext.isString(db)){
25651                 f = Ext.getCmp(db);
25652             }else{
25653                 f = db;
25654             }
25655             el = f.getEl();
25656             ct = Ext.getDom(this.container);
25657             if (el && ct) {
25658                 if (!Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
25659                     return;
25660                 }
25661             }
25662         }
25663         f = f || this.focusEl;
25664         f.focus.defer(10, f);
25665     },
25666
25667     
25668     setAnimateTarget : function(el){
25669         el = Ext.get(el);
25670         this.animateTarget = el;
25671     },
25672
25673     
25674     beforeShow : function(){
25675         delete this.el.lastXY;
25676         delete this.el.lastLT;
25677         if(this.x === undefined || this.y === undefined){
25678             var xy = this.el.getAlignToXY(this.container, 'c-c');
25679             var pos = this.el.translatePoints(xy[0], xy[1]);
25680             this.x = this.x === undefined? pos.left : this.x;
25681             this.y = this.y === undefined? pos.top : this.y;
25682         }
25683         this.el.setLeftTop(this.x, this.y);
25684
25685         if(this.expandOnShow){
25686             this.expand(false);
25687         }
25688
25689         if(this.modal){
25690             Ext.getBody().addClass('x-body-masked');
25691             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
25692             this.mask.show();
25693         }
25694     },
25695
25696     
25697     show : function(animateTarget, cb, scope){
25698         if(!this.rendered){
25699             this.render(Ext.getBody());
25700         }
25701         if(this.hidden === false){
25702             this.toFront();
25703             return this;
25704         }
25705         if(this.fireEvent('beforeshow', this) === false){
25706             return this;
25707         }
25708         if(cb){
25709             this.on('show', cb, scope, {single:true});
25710         }
25711         this.hidden = false;
25712         if(Ext.isDefined(animateTarget)){
25713             this.setAnimateTarget(animateTarget);
25714         }
25715         this.beforeShow();
25716         if(this.animateTarget){
25717             this.animShow();
25718         }else{
25719             this.afterShow();
25720         }
25721         return this;
25722     },
25723
25724     
25725     afterShow : function(isAnim){
25726         if (this.isDestroyed){
25727             return false;
25728         }
25729         this.proxy.hide();
25730         this.el.setStyle('display', 'block');
25731         this.el.show();
25732         if(this.maximized){
25733             this.fitContainer();
25734         }
25735         if(Ext.isMac && Ext.isGecko2){ 
25736             this.cascade(this.setAutoScroll);
25737         }
25738
25739         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
25740             Ext.EventManager.onWindowResize(this.onWindowResize, this);
25741         }
25742         this.doConstrain();
25743         this.doLayout();
25744         if(this.keyMap){
25745             this.keyMap.enable();
25746         }
25747         this.toFront();
25748         this.updateHandles();
25749         if(isAnim && (Ext.isIE || Ext.isWebKit)){
25750             var sz = this.getSize();
25751             this.onResize(sz.width, sz.height);
25752         }
25753         this.onShow();
25754         this.fireEvent('show', this);
25755     },
25756
25757     
25758     animShow : function(){
25759         this.proxy.show();
25760         this.proxy.setBox(this.animateTarget.getBox());
25761         this.proxy.setOpacity(0);
25762         var b = this.getBox();
25763         this.el.setStyle('display', 'none');
25764         this.proxy.shift(Ext.apply(b, {
25765             callback: this.afterShow.createDelegate(this, [true], false),
25766             scope: this,
25767             easing: 'easeNone',
25768             duration: 0.25,
25769             opacity: 0.5
25770         }));
25771     },
25772
25773     
25774     hide : function(animateTarget, cb, scope){
25775         if(this.hidden || this.fireEvent('beforehide', this) === false){
25776             return this;
25777         }
25778         if(cb){
25779             this.on('hide', cb, scope, {single:true});
25780         }
25781         this.hidden = true;
25782         if(animateTarget !== undefined){
25783             this.setAnimateTarget(animateTarget);
25784         }
25785         if(this.modal){
25786             this.mask.hide();
25787             Ext.getBody().removeClass('x-body-masked');
25788         }
25789         if(this.animateTarget){
25790             this.animHide();
25791         }else{
25792             this.el.hide();
25793             this.afterHide();
25794         }
25795         return this;
25796     },
25797
25798     
25799     afterHide : function(){
25800         this.proxy.hide();
25801         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
25802             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
25803         }
25804         if(this.keyMap){
25805             this.keyMap.disable();
25806         }
25807         this.onHide();
25808         this.fireEvent('hide', this);
25809     },
25810
25811     
25812     animHide : function(){
25813         this.proxy.setOpacity(0.5);
25814         this.proxy.show();
25815         var tb = this.getBox(false);
25816         this.proxy.setBox(tb);
25817         this.el.hide();
25818         this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
25819             callback: this.afterHide,
25820             scope: this,
25821             duration: 0.25,
25822             easing: 'easeNone',
25823             opacity: 0
25824         }));
25825     },
25826
25827     
25828     onShow : Ext.emptyFn,
25829
25830     
25831     onHide : Ext.emptyFn,
25832
25833     
25834     onWindowResize : function(){
25835         if(this.maximized){
25836             this.fitContainer();
25837         }
25838         if(this.modal){
25839             this.mask.setSize('100%', '100%');
25840             var force = this.mask.dom.offsetHeight;
25841             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
25842         }
25843         this.doConstrain();
25844     },
25845
25846     
25847     doConstrain : function(){
25848         if(this.constrain || this.constrainHeader){
25849             var offsets;
25850             if(this.constrain){
25851                 offsets = {
25852                     right:this.el.shadowOffset,
25853                     left:this.el.shadowOffset,
25854                     bottom:this.el.shadowOffset
25855                 };
25856             }else {
25857                 var s = this.getSize();
25858                 offsets = {
25859                     right:-(s.width - 100),
25860                     bottom:-(s.height - 25)
25861                 };
25862             }
25863
25864             var xy = this.el.getConstrainToXY(this.container, true, offsets);
25865             if(xy){
25866                 this.setPosition(xy[0], xy[1]);
25867             }
25868         }
25869     },
25870
25871     
25872     ghost : function(cls){
25873         var ghost = this.createGhost(cls);
25874         var box = this.getBox(true);
25875         ghost.setLeftTop(box.x, box.y);
25876         ghost.setWidth(box.width);
25877         this.el.hide();
25878         this.activeGhost = ghost;
25879         return ghost;
25880     },
25881
25882     
25883     unghost : function(show, matchPosition){
25884         if(!this.activeGhost) {
25885             return;
25886         }
25887         if(show !== false){
25888             this.el.show();
25889             this.focus.defer(10, this);
25890             if(Ext.isMac && Ext.isGecko2){ 
25891                 this.cascade(this.setAutoScroll);
25892             }
25893         }
25894         if(matchPosition !== false){
25895             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
25896         }
25897         this.activeGhost.hide();
25898         this.activeGhost.remove();
25899         delete this.activeGhost;
25900     },
25901
25902     
25903     minimize : function(){
25904         this.fireEvent('minimize', this);
25905         return this;
25906     },
25907
25908     
25909     close : function(){
25910         if(this.fireEvent('beforeclose', this) !== false){
25911             if(this.hidden){
25912                 this.doClose();
25913             }else{
25914                 this.hide(null, this.doClose, this);
25915             }
25916         }
25917     },
25918
25919     
25920     doClose : function(){
25921         this.fireEvent('close', this);
25922         this.destroy();
25923     },
25924
25925     
25926     maximize : function(){
25927         if(!this.maximized){
25928             this.expand(false);
25929             this.restoreSize = this.getSize();
25930             this.restorePos = this.getPosition(true);
25931             if (this.maximizable){
25932                 this.tools.maximize.hide();
25933                 this.tools.restore.show();
25934             }
25935             this.maximized = true;
25936             this.el.disableShadow();
25937
25938             if(this.dd){
25939                 this.dd.lock();
25940             }
25941             if(this.collapsible){
25942                 this.tools.toggle.hide();
25943             }
25944             this.el.addClass('x-window-maximized');
25945             this.container.addClass('x-window-maximized-ct');
25946
25947             this.setPosition(0, 0);
25948             this.fitContainer();
25949             this.fireEvent('maximize', this);
25950         }
25951         return this;
25952     },
25953
25954     
25955     restore : function(){
25956         if(this.maximized){
25957             var t = this.tools;
25958             this.el.removeClass('x-window-maximized');
25959             if(t.restore){
25960                 t.restore.hide();
25961             }
25962             if(t.maximize){
25963                 t.maximize.show();
25964             }
25965             this.setPosition(this.restorePos[0], this.restorePos[1]);
25966             this.setSize(this.restoreSize.width, this.restoreSize.height);
25967             delete this.restorePos;
25968             delete this.restoreSize;
25969             this.maximized = false;
25970             this.el.enableShadow(true);
25971
25972             if(this.dd){
25973                 this.dd.unlock();
25974             }
25975             if(this.collapsible && t.toggle){
25976                 t.toggle.show();
25977             }
25978             this.container.removeClass('x-window-maximized-ct');
25979
25980             this.doConstrain();
25981             this.fireEvent('restore', this);
25982         }
25983         return this;
25984     },
25985
25986     
25987     toggleMaximize : function(){
25988         return this[this.maximized ? 'restore' : 'maximize']();
25989     },
25990
25991     
25992     fitContainer : function(){
25993         var vs = this.container.getViewSize(false);
25994         this.setSize(vs.width, vs.height);
25995     },
25996
25997     
25998     
25999     setZIndex : function(index){
26000         if(this.modal){
26001             this.mask.setStyle('z-index', index);
26002         }
26003         this.el.setZIndex(++index);
26004         index += 5;
26005
26006         if(this.resizer){
26007             this.resizer.proxy.setStyle('z-index', ++index);
26008         }
26009
26010         this.lastZIndex = index;
26011     },
26012
26013     
26014     alignTo : function(element, position, offsets){
26015         var xy = this.el.getAlignToXY(element, position, offsets);
26016         this.setPagePosition(xy[0], xy[1]);
26017         return this;
26018     },
26019
26020     
26021     anchorTo : function(el, alignment, offsets, monitorScroll){
26022         this.clearAnchor();
26023         this.anchorTarget = {
26024             el: el,
26025             alignment: alignment,
26026             offsets: offsets
26027         };
26028
26029         Ext.EventManager.onWindowResize(this.doAnchor, this);
26030         var tm = typeof monitorScroll;
26031         if(tm != 'undefined'){
26032             Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
26033                 {buffer: tm == 'number' ? monitorScroll : 50});
26034         }
26035         return this.doAnchor();
26036     },
26037
26038     
26039     doAnchor : function(){
26040         var o = this.anchorTarget;
26041         this.alignTo(o.el, o.alignment, o.offsets);
26042         return this;
26043     },
26044
26045     
26046     clearAnchor : function(){
26047         if(this.anchorTarget){
26048             Ext.EventManager.removeResizeListener(this.doAnchor, this);
26049             Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
26050             delete this.anchorTarget;
26051         }
26052         return this;
26053     },
26054
26055     
26056     toFront : function(e){
26057         if(this.manager.bringToFront(this)){
26058             if(!e || !e.getTarget().focus){
26059                 this.focus();
26060             }
26061         }
26062         return this;
26063     },
26064
26065     
26066     setActive : function(active){
26067         if(active){
26068             if(!this.maximized){
26069                 this.el.enableShadow(true);
26070             }
26071             this.fireEvent('activate', this);
26072         }else{
26073             this.el.disableShadow();
26074             this.fireEvent('deactivate', this);
26075         }
26076     },
26077
26078     
26079     toBack : function(){
26080         this.manager.sendToBack(this);
26081         return this;
26082     },
26083
26084     
26085     center : function(){
26086         var xy = this.el.getAlignToXY(this.container, 'c-c');
26087         this.setPagePosition(xy[0], xy[1]);
26088         return this;
26089     }
26090
26091     
26092 });
26093 Ext.reg('window', Ext.Window);
26094
26095
26096 Ext.Window.DD = function(win){
26097     this.win = win;
26098     Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
26099     this.setHandleElId(win.header.id);
26100     this.scroll = false;
26101 };
26102
26103 Ext.extend(Ext.Window.DD, Ext.dd.DD, {
26104     moveOnly:true,
26105     headerOffsets:[100, 25],
26106     startDrag : function(){
26107         var w = this.win;
26108         this.proxy = w.ghost();
26109         if(w.constrain !== false){
26110             var so = w.el.shadowOffset;
26111             this.constrainTo(w.container, {right: so, left: so, bottom: so});
26112         }else if(w.constrainHeader !== false){
26113             var s = this.proxy.getSize();
26114             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
26115         }
26116     },
26117     b4Drag : Ext.emptyFn,
26118
26119     onDrag : function(e){
26120         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
26121     },
26122
26123     endDrag : function(e){
26124         this.win.unghost();
26125         this.win.saveState();
26126     }
26127 });
26128
26129 Ext.WindowGroup = function(){
26130     var list = {};
26131     var accessList = [];
26132     var front = null;
26133
26134     
26135     var sortWindows = function(d1, d2){
26136         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
26137     };
26138
26139     
26140     var orderWindows = function(){
26141         var a = accessList, len = a.length;
26142         if(len > 0){
26143             a.sort(sortWindows);
26144             var seed = a[0].manager.zseed;
26145             for(var i = 0; i < len; i++){
26146                 var win = a[i];
26147                 if(win && !win.hidden){
26148                     win.setZIndex(seed + (i*10));
26149                 }
26150             }
26151         }
26152         activateLast();
26153     };
26154
26155     
26156     var setActiveWin = function(win){
26157         if(win != front){
26158             if(front){
26159                 front.setActive(false);
26160             }
26161             front = win;
26162             if(win){
26163                 win.setActive(true);
26164             }
26165         }
26166     };
26167
26168     
26169     var activateLast = function(){
26170         for(var i = accessList.length-1; i >=0; --i) {
26171             if(!accessList[i].hidden){
26172                 setActiveWin(accessList[i]);
26173                 return;
26174             }
26175         }
26176         
26177         setActiveWin(null);
26178     };
26179
26180     return {
26181         
26182         zseed : 9000,
26183
26184         
26185         register : function(win){
26186             if(win.manager){
26187                 win.manager.unregister(win);
26188             }
26189             win.manager = this;
26190
26191             list[win.id] = win;
26192             accessList.push(win);
26193             win.on('hide', activateLast);
26194         },
26195
26196         
26197         unregister : function(win){
26198             delete win.manager;
26199             delete list[win.id];
26200             win.un('hide', activateLast);
26201             accessList.remove(win);
26202         },
26203
26204         
26205         get : function(id){
26206             return typeof id == "object" ? id : list[id];
26207         },
26208
26209         
26210         bringToFront : function(win){
26211             win = this.get(win);
26212             if(win != front){
26213                 win._lastAccess = new Date().getTime();
26214                 orderWindows();
26215                 return true;
26216             }
26217             return false;
26218         },
26219
26220         
26221         sendToBack : function(win){
26222             win = this.get(win);
26223             win._lastAccess = -(new Date().getTime());
26224             orderWindows();
26225             return win;
26226         },
26227
26228         
26229         hideAll : function(){
26230             for(var id in list){
26231                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
26232                     list[id].hide();
26233                 }
26234             }
26235         },
26236
26237         
26238         getActive : function(){
26239             return front;
26240         },
26241
26242         
26243         getBy : function(fn, scope){
26244             var r = [];
26245             for(var i = accessList.length-1; i >=0; --i) {
26246                 var win = accessList[i];
26247                 if(fn.call(scope||win, win) !== false){
26248                     r.push(win);
26249                 }
26250             }
26251             return r;
26252         },
26253
26254         
26255         each : function(fn, scope){
26256             for(var id in list){
26257                 if(list[id] && typeof list[id] != "function"){
26258                     if(fn.call(scope || list[id], list[id]) === false){
26259                         return;
26260                     }
26261                 }
26262             }
26263         }
26264     };
26265 };
26266
26267
26268
26269 Ext.WindowMgr = new Ext.WindowGroup();
26270 Ext.MessageBox = function(){
26271     var dlg, opt, mask, waitTimer,
26272         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
26273         buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
26274         buttonNames = ['ok', 'yes', 'no', 'cancel'];
26275
26276     
26277     var handleButton = function(button){
26278         buttons[button].blur();
26279         if(dlg.isVisible()){
26280             dlg.hide();
26281             handleHide();
26282             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
26283         }
26284     };
26285
26286     
26287     var handleHide = function(){
26288         if(opt && opt.cls){
26289             dlg.el.removeClass(opt.cls);
26290         }
26291         progressBar.reset();        
26292     };
26293
26294     
26295     var handleEsc = function(d, k, e){
26296         if(opt && opt.closable !== false){
26297             dlg.hide();
26298             handleHide();
26299         }
26300         if(e){
26301             e.stopEvent();
26302         }
26303     };
26304
26305     
26306     var updateButtons = function(b){
26307         var width = 0,
26308             cfg;
26309         if(!b){
26310             Ext.each(buttonNames, function(name){
26311                 buttons[name].hide();
26312             });
26313             return width;
26314         }
26315         dlg.footer.dom.style.display = '';
26316         Ext.iterate(buttons, function(name, btn){
26317             cfg = b[name];
26318             if(cfg){
26319                 btn.show();
26320                 btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
26321                 width += btn.getEl().getWidth() + 15;
26322             }else{
26323                 btn.hide();
26324             }
26325         });
26326         return width;
26327     };
26328
26329     return {
26330         
26331         getDialog : function(titleText){
26332            if(!dlg){
26333                 var btns = [];
26334                 
26335                 buttons = {};
26336                 Ext.each(buttonNames, function(name){
26337                     btns.push(buttons[name] = new Ext.Button({
26338                         text: this.buttonText[name],
26339                         handler: handleButton.createCallback(name),
26340                         hideMode: 'offsets'
26341                     }));
26342                 }, this);
26343                 dlg = new Ext.Window({
26344                     autoCreate : true,
26345                     title:titleText,
26346                     resizable:false,
26347                     constrain:true,
26348                     constrainHeader:true,
26349                     minimizable : false,
26350                     maximizable : false,
26351                     stateful: false,
26352                     modal: true,
26353                     shim:true,
26354                     buttonAlign:"center",
26355                     width:400,
26356                     height:100,
26357                     minHeight: 80,
26358                     plain:true,
26359                     footer:true,
26360                     closable:true,
26361                     close : function(){
26362                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
26363                             handleButton("no");
26364                         }else{
26365                             handleButton("cancel");
26366                         }
26367                     },
26368                     fbar: new Ext.Toolbar({
26369                         items: btns,
26370                         enableOverflow: false
26371                     })
26372                 });
26373                 dlg.render(document.body);
26374                 dlg.getEl().addClass('x-window-dlg');
26375                 mask = dlg.mask;
26376                 bodyEl = dlg.body.createChild({
26377                     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>'
26378                 });
26379                 iconEl = Ext.get(bodyEl.dom.firstChild);
26380                 var contentEl = bodyEl.dom.childNodes[1];
26381                 msgEl = Ext.get(contentEl.firstChild);
26382                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
26383                 textboxEl.enableDisplayMode();
26384                 textboxEl.addKeyListener([10,13], function(){
26385                     if(dlg.isVisible() && opt && opt.buttons){
26386                         if(opt.buttons.ok){
26387                             handleButton("ok");
26388                         }else if(opt.buttons.yes){
26389                             handleButton("yes");
26390                         }
26391                     }
26392                 });
26393                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
26394                 textareaEl.enableDisplayMode();
26395                 progressBar = new Ext.ProgressBar({
26396                     renderTo:bodyEl
26397                 });
26398                bodyEl.createChild({cls:'x-clear'});
26399             }
26400             return dlg;
26401         },
26402
26403         
26404         updateText : function(text){
26405             if(!dlg.isVisible() && !opt.width){
26406                 dlg.setSize(this.maxWidth, 100); 
26407             }
26408             msgEl.update(text || '&#160;');
26409
26410             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
26411                 mw = msgEl.getWidth() + msgEl.getMargins('lr'),
26412                 fw = dlg.getFrameWidth('lr'),
26413                 bw = dlg.body.getFrameWidth('lr'),
26414                 w;
26415                 
26416             if (Ext.isIE && iw > 0){
26417                 
26418                 
26419                 iw += 3;
26420             }
26421             w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
26422                     Math.max(opt.minWidth || this.minWidth, bwidth || 0));
26423
26424             if(opt.prompt === true){
26425                 activeTextEl.setWidth(w-iw-fw-bw);
26426             }
26427             if(opt.progress === true || opt.wait === true){
26428                 progressBar.setSize(w-iw-fw-bw);
26429             }
26430             if(Ext.isIE && w == bwidth){
26431                 w += 4; 
26432             }
26433             dlg.setSize(w, 'auto').center();
26434             return this;
26435         },
26436
26437         
26438         updateProgress : function(value, progressText, msg){
26439             progressBar.updateProgress(value, progressText);
26440             if(msg){
26441                 this.updateText(msg);
26442             }
26443             return this;
26444         },
26445
26446         
26447         isVisible : function(){
26448             return dlg && dlg.isVisible();
26449         },
26450
26451         
26452         hide : function(){
26453             var proxy = dlg ? dlg.activeGhost : null;
26454             if(this.isVisible() || proxy){
26455                 dlg.hide();
26456                 handleHide();
26457                 if (proxy){
26458                     
26459                     
26460                     dlg.unghost(false, false);
26461                 } 
26462             }
26463             return this;
26464         },
26465
26466         
26467         show : function(options){
26468             if(this.isVisible()){
26469                 this.hide();
26470             }
26471             opt = options;
26472             var d = this.getDialog(opt.title || "&#160;");
26473
26474             d.setTitle(opt.title || "&#160;");
26475             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
26476             d.tools.close.setDisplayed(allowClose);
26477             activeTextEl = textboxEl;
26478             opt.prompt = opt.prompt || (opt.multiline ? true : false);
26479             if(opt.prompt){
26480                 if(opt.multiline){
26481                     textboxEl.hide();
26482                     textareaEl.show();
26483                     textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
26484                     activeTextEl = textareaEl;
26485                 }else{
26486                     textboxEl.show();
26487                     textareaEl.hide();
26488                 }
26489             }else{
26490                 textboxEl.hide();
26491                 textareaEl.hide();
26492             }
26493             activeTextEl.dom.value = opt.value || "";
26494             if(opt.prompt){
26495                 d.focusEl = activeTextEl;
26496             }else{
26497                 var bs = opt.buttons;
26498                 var db = null;
26499                 if(bs && bs.ok){
26500                     db = buttons["ok"];
26501                 }else if(bs && bs.yes){
26502                     db = buttons["yes"];
26503                 }
26504                 if (db){
26505                     d.focusEl = db;
26506                 }
26507             }
26508             if(Ext.isDefined(opt.iconCls)){
26509               d.setIconClass(opt.iconCls);
26510             }
26511             this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
26512             bwidth = updateButtons(opt.buttons);
26513             progressBar.setVisible(opt.progress === true || opt.wait === true);
26514             this.updateProgress(0, opt.progressText);
26515             this.updateText(opt.msg);
26516             if(opt.cls){
26517                 d.el.addClass(opt.cls);
26518             }
26519             d.proxyDrag = opt.proxyDrag === true;
26520             d.modal = opt.modal !== false;
26521             d.mask = opt.modal !== false ? mask : false;
26522             if(!d.isVisible()){
26523                 
26524                 document.body.appendChild(dlg.el.dom);
26525                 d.setAnimateTarget(opt.animEl);
26526                 
26527                 d.on('show', function(){
26528                     if(allowClose === true){
26529                         d.keyMap.enable();
26530                     }else{
26531                         d.keyMap.disable();
26532                     }
26533                 }, this, {single:true});
26534                 d.show(opt.animEl);
26535             }
26536             if(opt.wait === true){
26537                 progressBar.wait(opt.waitConfig);
26538             }
26539             return this;
26540         },
26541
26542         
26543         setIcon : function(icon){
26544             if(!dlg){
26545                 bufferIcon = icon;
26546                 return;
26547             }
26548             bufferIcon = undefined;
26549             if(icon && icon != ''){
26550                 iconEl.removeClass('x-hidden');
26551                 iconEl.replaceClass(iconCls, icon);
26552                 bodyEl.addClass('x-dlg-icon');
26553                 iconCls = icon;
26554             }else{
26555                 iconEl.replaceClass(iconCls, 'x-hidden');
26556                 bodyEl.removeClass('x-dlg-icon');
26557                 iconCls = '';
26558             }
26559             return this;
26560         },
26561
26562         
26563         progress : function(title, msg, progressText){
26564             this.show({
26565                 title : title,
26566                 msg : msg,
26567                 buttons: false,
26568                 progress:true,
26569                 closable:false,
26570                 minWidth: this.minProgressWidth,
26571                 progressText: progressText
26572             });
26573             return this;
26574         },
26575
26576         
26577         wait : function(msg, title, config){
26578             this.show({
26579                 title : title,
26580                 msg : msg,
26581                 buttons: false,
26582                 closable:false,
26583                 wait:true,
26584                 modal:true,
26585                 minWidth: this.minProgressWidth,
26586                 waitConfig: config
26587             });
26588             return this;
26589         },
26590
26591         
26592         alert : function(title, msg, fn, scope){
26593             this.show({
26594                 title : title,
26595                 msg : msg,
26596                 buttons: this.OK,
26597                 fn: fn,
26598                 scope : scope,
26599                 minWidth: this.minWidth
26600             });
26601             return this;
26602         },
26603
26604         
26605         confirm : function(title, msg, fn, scope){
26606             this.show({
26607                 title : title,
26608                 msg : msg,
26609                 buttons: this.YESNO,
26610                 fn: fn,
26611                 scope : scope,
26612                 icon: this.QUESTION,
26613                 minWidth: this.minWidth
26614             });
26615             return this;
26616         },
26617
26618         
26619         prompt : function(title, msg, fn, scope, multiline, value){
26620             this.show({
26621                 title : title,
26622                 msg : msg,
26623                 buttons: this.OKCANCEL,
26624                 fn: fn,
26625                 minWidth: this.minPromptWidth,
26626                 scope : scope,
26627                 prompt:true,
26628                 multiline: multiline,
26629                 value: value
26630             });
26631             return this;
26632         },
26633
26634         
26635         OK : {ok:true},
26636         
26637         CANCEL : {cancel:true},
26638         
26639         OKCANCEL : {ok:true, cancel:true},
26640         
26641         YESNO : {yes:true, no:true},
26642         
26643         YESNOCANCEL : {yes:true, no:true, cancel:true},
26644         
26645         INFO : 'ext-mb-info',
26646         
26647         WARNING : 'ext-mb-warning',
26648         
26649         QUESTION : 'ext-mb-question',
26650         
26651         ERROR : 'ext-mb-error',
26652
26653         
26654         defaultTextHeight : 75,
26655         
26656         maxWidth : 600,
26657         
26658         minWidth : 100,
26659         
26660         minProgressWidth : 250,
26661         
26662         minPromptWidth: 250,
26663         
26664         buttonText : {
26665             ok : "OK",
26666             cancel : "Cancel",
26667             yes : "Yes",
26668             no : "No"
26669         }
26670     };
26671 }();
26672
26673
26674 Ext.Msg = Ext.MessageBox;
26675 Ext.dd.PanelProxy = function(panel, config){
26676     this.panel = panel;
26677     this.id = this.panel.id +'-ddproxy';
26678     Ext.apply(this, config);
26679 };
26680
26681 Ext.dd.PanelProxy.prototype = {
26682     
26683     insertProxy : true,
26684
26685     
26686     setStatus : Ext.emptyFn,
26687     reset : Ext.emptyFn,
26688     update : Ext.emptyFn,
26689     stop : Ext.emptyFn,
26690     sync: Ext.emptyFn,
26691
26692     
26693     getEl : function(){
26694         return this.ghost;
26695     },
26696
26697     
26698     getGhost : function(){
26699         return this.ghost;
26700     },
26701
26702     
26703     getProxy : function(){
26704         return this.proxy;
26705     },
26706
26707     
26708     hide : function(){
26709         if(this.ghost){
26710             if(this.proxy){
26711                 this.proxy.remove();
26712                 delete this.proxy;
26713             }
26714             this.panel.el.dom.style.display = '';
26715             this.ghost.remove();
26716             delete this.ghost;
26717         }
26718     },
26719
26720     
26721     show : function(){
26722         if(!this.ghost){
26723             this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
26724             this.ghost.setXY(this.panel.el.getXY());
26725             if(this.insertProxy){
26726                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
26727                 this.proxy.setSize(this.panel.getSize());
26728             }
26729             this.panel.el.dom.style.display = 'none';
26730         }
26731     },
26732
26733     
26734     repair : function(xy, callback, scope){
26735         this.hide();
26736         if(typeof callback == "function"){
26737             callback.call(scope || this);
26738         }
26739     },
26740
26741     
26742     moveProxy : function(parentNode, before){
26743         if(this.proxy){
26744             parentNode.insertBefore(this.proxy.dom, before);
26745         }
26746     }
26747 };
26748
26749
26750 Ext.Panel.DD = function(panel, cfg){
26751     this.panel = panel;
26752     this.dragData = {panel: panel};
26753     this.proxy = new Ext.dd.PanelProxy(panel, cfg);
26754     Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
26755     var h = panel.header;
26756     if(h){
26757         this.setHandleElId(h.id);
26758     }
26759     (h ? h : this.panel.body).setStyle('cursor', 'move');
26760     this.scroll = false;
26761 };
26762
26763 Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
26764     showFrame: Ext.emptyFn,
26765     startDrag: Ext.emptyFn,
26766     b4StartDrag: function(x, y) {
26767         this.proxy.show();
26768     },
26769     b4MouseDown: function(e) {
26770         var x = e.getPageX();
26771         var y = e.getPageY();
26772         this.autoOffset(x, y);
26773     },
26774     onInitDrag : function(x, y){
26775         this.onStartDrag(x, y);
26776         return true;
26777     },
26778     createFrame : Ext.emptyFn,
26779     getDragEl : function(e){
26780         return this.proxy.ghost.dom;
26781     },
26782     endDrag : function(e){
26783         this.proxy.hide();
26784         this.panel.saveState();
26785     },
26786
26787     autoOffset : function(x, y) {
26788         x -= this.startPageX;
26789         y -= this.startPageY;
26790         this.setDelta(x, y);
26791     }
26792 });
26793 Ext.state.Provider = Ext.extend(Ext.util.Observable, {
26794     
26795     constructor : function(){
26796         
26797         this.addEvents("statechange");
26798         this.state = {};
26799         Ext.state.Provider.superclass.constructor.call(this);
26800     },
26801     
26802     
26803     get : function(name, defaultValue){
26804         return typeof this.state[name] == "undefined" ?
26805             defaultValue : this.state[name];
26806     },
26807
26808     
26809     clear : function(name){
26810         delete this.state[name];
26811         this.fireEvent("statechange", this, name, null);
26812     },
26813
26814     
26815     set : function(name, value){
26816         this.state[name] = value;
26817         this.fireEvent("statechange", this, name, value);
26818     },
26819
26820     
26821     decodeValue : function(cookie){
26822         
26823         var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
26824             matches = re.exec(unescape(cookie)),
26825             all,
26826             type,
26827             v,
26828             kv;
26829         if(!matches || !matches[1]){
26830             return; 
26831         }
26832         type = matches[1];
26833         v = matches[2];
26834         switch(type){
26835             case 'e':
26836                 return null;
26837             case 'n':
26838                 return parseFloat(v);
26839             case 'd':
26840                 return new Date(Date.parse(v));
26841             case 'b':
26842                 return (v == '1');
26843             case 'a':
26844                 all = [];
26845                 if(v != ''){
26846                     Ext.each(v.split('^'), function(val){
26847                         all.push(this.decodeValue(val));
26848                     }, this);
26849                 }
26850                 return all;
26851            case 'o':
26852                 all = {};
26853                 if(v != ''){
26854                     Ext.each(v.split('^'), function(val){
26855                         kv = val.split('=');
26856                         all[kv[0]] = this.decodeValue(kv[1]);
26857                     }, this);
26858                 }
26859                 return all;
26860            default:
26861                 return v;
26862         }
26863     },
26864
26865     
26866     encodeValue : function(v){
26867         var enc,
26868             flat = '',
26869             i = 0,
26870             len,
26871             key;
26872         if(v == null){
26873             return 'e:1';    
26874         }else if(typeof v == 'number'){
26875             enc = 'n:' + v;
26876         }else if(typeof v == 'boolean'){
26877             enc = 'b:' + (v ? '1' : '0');
26878         }else if(Ext.isDate(v)){
26879             enc = 'd:' + v.toGMTString();
26880         }else if(Ext.isArray(v)){
26881             for(len = v.length; i < len; i++){
26882                 flat += this.encodeValue(v[i]);
26883                 if(i != len - 1){
26884                     flat += '^';
26885                 }
26886             }
26887             enc = 'a:' + flat;
26888         }else if(typeof v == 'object'){
26889             for(key in v){
26890                 if(typeof v[key] != 'function' && v[key] !== undefined){
26891                     flat += key + '=' + this.encodeValue(v[key]) + '^';
26892                 }
26893             }
26894             enc = 'o:' + flat.substring(0, flat.length-1);
26895         }else{
26896             enc = 's:' + v;
26897         }
26898         return escape(enc);
26899     }
26900 });
26901
26902 Ext.state.Manager = function(){
26903     var provider = new Ext.state.Provider();
26904
26905     return {
26906         
26907         setProvider : function(stateProvider){
26908             provider = stateProvider;
26909         },
26910
26911         
26912         get : function(key, defaultValue){
26913             return provider.get(key, defaultValue);
26914         },
26915
26916         
26917          set : function(key, value){
26918             provider.set(key, value);
26919         },
26920
26921         
26922         clear : function(key){
26923             provider.clear(key);
26924         },
26925
26926         
26927         getProvider : function(){
26928             return provider;
26929         }
26930     };
26931 }();
26932
26933 Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {
26934     
26935     constructor : function(config){
26936         Ext.state.CookieProvider.superclass.constructor.call(this);
26937         this.path = "/";
26938         this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
26939         this.domain = null;
26940         this.secure = false;
26941         Ext.apply(this, config);
26942         this.state = this.readCookies();
26943     },
26944     
26945     
26946     set : function(name, value){
26947         if(typeof value == "undefined" || value === null){
26948             this.clear(name);
26949             return;
26950         }
26951         this.setCookie(name, value);
26952         Ext.state.CookieProvider.superclass.set.call(this, name, value);
26953     },
26954
26955     
26956     clear : function(name){
26957         this.clearCookie(name);
26958         Ext.state.CookieProvider.superclass.clear.call(this, name);
26959     },
26960
26961     
26962     readCookies : function(){
26963         var cookies = {},
26964             c = document.cookie + ";",
26965             re = /\s?(.*?)=(.*?);/g,
26966             matches,
26967             name,
26968             value;
26969         while((matches = re.exec(c)) != null){
26970             name = matches[1];
26971             value = matches[2];
26972             if(name && name.substring(0,3) == "ys-"){
26973                 cookies[name.substr(3)] = this.decodeValue(value);
26974             }
26975         }
26976         return cookies;
26977     },
26978
26979     
26980     setCookie : function(name, value){
26981         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
26982            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
26983            ((this.path == null) ? "" : ("; path=" + this.path)) +
26984            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
26985            ((this.secure == true) ? "; secure" : "");
26986     },
26987
26988     
26989     clearCookie : function(name){
26990         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
26991            ((this.path == null) ? "" : ("; path=" + this.path)) +
26992            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
26993            ((this.secure == true) ? "; secure" : "");
26994     }
26995 });
26996 Ext.DataView = Ext.extend(Ext.BoxComponent, {
26997     
26998     
26999     
27000     
27001     
27002     
27003     
27004     
27005     
27006     selectedClass : "x-view-selected",
27007     
27008     emptyText : "",
27009
27010     
27011     deferEmptyText: true,
27012     
27013     trackOver: false,
27014     
27015     
27016     blockRefresh: false,
27017
27018     
27019     last: false,
27020
27021     
27022     initComponent : function(){
27023         Ext.DataView.superclass.initComponent.call(this);
27024         if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
27025             this.tpl = new Ext.XTemplate(this.tpl);
27026         }
27027
27028         this.addEvents(
27029             
27030             "beforeclick",
27031             
27032             "click",
27033             
27034             "mouseenter",
27035             
27036             "mouseleave",
27037             
27038             "containerclick",
27039             
27040             "dblclick",
27041             
27042             "contextmenu",
27043             
27044             "containercontextmenu",
27045             
27046             "selectionchange",
27047
27048             
27049             "beforeselect"
27050         );
27051
27052         this.store = Ext.StoreMgr.lookup(this.store);
27053         this.all = new Ext.CompositeElementLite();
27054         this.selected = new Ext.CompositeElementLite();
27055     },
27056
27057     
27058     afterRender : function(){
27059         Ext.DataView.superclass.afterRender.call(this);
27060
27061                 this.mon(this.getTemplateTarget(), {
27062             "click": this.onClick,
27063             "dblclick": this.onDblClick,
27064             "contextmenu": this.onContextMenu,
27065             scope:this
27066         });
27067
27068         if(this.overClass || this.trackOver){
27069             this.mon(this.getTemplateTarget(), {
27070                 "mouseover": this.onMouseOver,
27071                 "mouseout": this.onMouseOut,
27072                 scope:this
27073             });
27074         }
27075
27076         if(this.store){
27077             this.bindStore(this.store, true);
27078         }
27079     },
27080
27081     
27082     refresh : function() {
27083         this.clearSelections(false, true);
27084         var el = this.getTemplateTarget();
27085         el.update("");
27086         var records = this.store.getRange();
27087         if(records.length < 1){
27088             if(!this.deferEmptyText || this.hasSkippedEmptyText){
27089                 el.update(this.emptyText);
27090             }
27091             this.all.clear();
27092         }else{
27093             this.tpl.overwrite(el, this.collectData(records, 0));
27094             this.all.fill(Ext.query(this.itemSelector, el.dom));
27095             this.updateIndexes(0);
27096         }
27097         this.hasSkippedEmptyText = true;
27098     },
27099
27100     getTemplateTarget: function(){
27101         return this.el;
27102     },
27103
27104     
27105     prepareData : function(data){
27106         return data;
27107     },
27108
27109     
27110     collectData : function(records, startIndex){
27111         var r = [];
27112         for(var i = 0, len = records.length; i < len; i++){
27113             r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
27114         }
27115         return r;
27116     },
27117
27118     
27119     bufferRender : function(records){
27120         var div = document.createElement('div');
27121         this.tpl.overwrite(div, this.collectData(records));
27122         return Ext.query(this.itemSelector, div);
27123     },
27124
27125     
27126     onUpdate : function(ds, record){
27127         var index = this.store.indexOf(record);
27128         if(index > -1){
27129             var sel = this.isSelected(index);
27130             var original = this.all.elements[index];
27131             var node = this.bufferRender([record], index)[0];
27132
27133             this.all.replaceElement(index, node, true);
27134             if(sel){
27135                 this.selected.replaceElement(original, node);
27136                 this.all.item(index).addClass(this.selectedClass);
27137             }
27138             this.updateIndexes(index, index);
27139         }
27140     },
27141
27142     
27143     onAdd : function(ds, records, index){
27144         if(this.all.getCount() === 0){
27145             this.refresh();
27146             return;
27147         }
27148         var nodes = this.bufferRender(records, index), n, a = this.all.elements;
27149         if(index < this.all.getCount()){
27150             n = this.all.item(index).insertSibling(nodes, 'before', true);
27151             a.splice.apply(a, [index, 0].concat(nodes));
27152         }else{
27153             n = this.all.last().insertSibling(nodes, 'after', true);
27154             a.push.apply(a, nodes);
27155         }
27156         this.updateIndexes(index);
27157     },
27158
27159     
27160     onRemove : function(ds, record, index){
27161         this.deselect(index);
27162         this.all.removeElement(index, true);
27163         this.updateIndexes(index);
27164         if (this.store.getCount() === 0){
27165             this.refresh();
27166         }
27167     },
27168
27169     
27170     refreshNode : function(index){
27171         this.onUpdate(this.store, this.store.getAt(index));
27172     },
27173
27174     
27175     updateIndexes : function(startIndex, endIndex){
27176         var ns = this.all.elements;
27177         startIndex = startIndex || 0;
27178         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
27179         for(var i = startIndex; i <= endIndex; i++){
27180             ns[i].viewIndex = i;
27181         }
27182     },
27183     
27184     
27185     getStore : function(){
27186         return this.store;
27187     },
27188
27189     
27190     bindStore : function(store, initial){
27191         if(!initial && this.store){
27192             if(store !== this.store && this.store.autoDestroy){
27193                 this.store.destroy();
27194             }else{
27195                 this.store.un("beforeload", this.onBeforeLoad, this);
27196                 this.store.un("datachanged", this.onDataChanged, this);
27197                 this.store.un("add", this.onAdd, this);
27198                 this.store.un("remove", this.onRemove, this);
27199                 this.store.un("update", this.onUpdate, this);
27200                 this.store.un("clear", this.refresh, this);
27201             }
27202             if(!store){
27203                 this.store = null;
27204             }
27205         }
27206         if(store){
27207             store = Ext.StoreMgr.lookup(store);
27208             store.on({
27209                 scope: this,
27210                 beforeload: this.onBeforeLoad,
27211                 datachanged: this.onDataChanged,
27212                 add: this.onAdd,
27213                 remove: this.onRemove,
27214                 update: this.onUpdate,
27215                 clear: this.refresh
27216             });
27217         }
27218         this.store = store;
27219         if(store){
27220             this.refresh();
27221         }
27222     },
27223     
27224     
27225     onDataChanged: function() {
27226         if (this.blockRefresh !== true) {
27227             this.refresh.apply(this, arguments);
27228         }
27229     },
27230
27231     
27232     findItemFromChild : function(node){
27233         return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
27234     },
27235
27236     
27237     onClick : function(e){
27238         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27239         if(item){
27240             var index = this.indexOf(item);
27241             if(this.onItemClick(item, index, e) !== false){
27242                 this.fireEvent("click", this, index, item, e);
27243             }
27244         }else{
27245             if(this.fireEvent("containerclick", this, e) !== false){
27246                 this.onContainerClick(e);
27247             }
27248         }
27249     },
27250
27251     onContainerClick : function(e){
27252         this.clearSelections();
27253     },
27254
27255     
27256     onContextMenu : function(e){
27257         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27258         if(item){
27259             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
27260         }else{
27261             this.fireEvent("containercontextmenu", this, e);
27262         }
27263     },
27264
27265     
27266     onDblClick : function(e){
27267         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27268         if(item){
27269             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
27270         }
27271     },
27272
27273     
27274     onMouseOver : function(e){
27275         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
27276         if(item && item !== this.lastItem){
27277             this.lastItem = item;
27278             Ext.fly(item).addClass(this.overClass);
27279             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
27280         }
27281     },
27282
27283     
27284     onMouseOut : function(e){
27285         if(this.lastItem){
27286             if(!e.within(this.lastItem, true, true)){
27287                 Ext.fly(this.lastItem).removeClass(this.overClass);
27288                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
27289                 delete this.lastItem;
27290             }
27291         }
27292     },
27293
27294     
27295     onItemClick : function(item, index, e){
27296         if(this.fireEvent("beforeclick", this, index, item, e) === false){
27297             return false;
27298         }
27299         if(this.multiSelect){
27300             this.doMultiSelection(item, index, e);
27301             e.preventDefault();
27302         }else if(this.singleSelect){
27303             this.doSingleSelection(item, index, e);
27304             e.preventDefault();
27305         }
27306         return true;
27307     },
27308
27309     
27310     doSingleSelection : function(item, index, e){
27311         if(e.ctrlKey && this.isSelected(index)){
27312             this.deselect(index);
27313         }else{
27314             this.select(index, false);
27315         }
27316     },
27317
27318     
27319     doMultiSelection : function(item, index, e){
27320         if(e.shiftKey && this.last !== false){
27321             var last = this.last;
27322             this.selectRange(last, index, e.ctrlKey);
27323             this.last = last; 
27324         }else{
27325             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
27326                 this.deselect(index);
27327             }else{
27328                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
27329             }
27330         }
27331     },
27332
27333     
27334     getSelectionCount : function(){
27335         return this.selected.getCount();
27336     },
27337
27338     
27339     getSelectedNodes : function(){
27340         return this.selected.elements;
27341     },
27342
27343     
27344     getSelectedIndexes : function(){
27345         var indexes = [], s = this.selected.elements;
27346         for(var i = 0, len = s.length; i < len; i++){
27347             indexes.push(s[i].viewIndex);
27348         }
27349         return indexes;
27350     },
27351
27352     
27353     getSelectedRecords : function(){
27354         var r = [], s = this.selected.elements;
27355         for(var i = 0, len = s.length; i < len; i++){
27356             r[r.length] = this.store.getAt(s[i].viewIndex);
27357         }
27358         return r;
27359     },
27360
27361     
27362     getRecords : function(nodes){
27363         var r = [], s = nodes;
27364         for(var i = 0, len = s.length; i < len; i++){
27365             r[r.length] = this.store.getAt(s[i].viewIndex);
27366         }
27367         return r;
27368     },
27369
27370     
27371     getRecord : function(node){
27372         return this.store.getAt(node.viewIndex);
27373     },
27374
27375     
27376     clearSelections : function(suppressEvent, skipUpdate){
27377         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
27378             if(!skipUpdate){
27379                 this.selected.removeClass(this.selectedClass);
27380             }
27381             this.selected.clear();
27382             this.last = false;
27383             if(!suppressEvent){
27384                 this.fireEvent("selectionchange", this, this.selected.elements);
27385             }
27386         }
27387     },
27388
27389     
27390     isSelected : function(node){
27391         return this.selected.contains(this.getNode(node));
27392     },
27393
27394     
27395     deselect : function(node){
27396         if(this.isSelected(node)){
27397             node = this.getNode(node);
27398             this.selected.removeElement(node);
27399             if(this.last == node.viewIndex){
27400                 this.last = false;
27401             }
27402             Ext.fly(node).removeClass(this.selectedClass);
27403             this.fireEvent("selectionchange", this, this.selected.elements);
27404         }
27405     },
27406
27407     
27408     select : function(nodeInfo, keepExisting, suppressEvent){
27409         if(Ext.isArray(nodeInfo)){
27410             if(!keepExisting){
27411                 this.clearSelections(true);
27412             }
27413             for(var i = 0, len = nodeInfo.length; i < len; i++){
27414                 this.select(nodeInfo[i], true, true);
27415             }
27416             if(!suppressEvent){
27417                 this.fireEvent("selectionchange", this, this.selected.elements);
27418             }
27419         } else{
27420             var node = this.getNode(nodeInfo);
27421             if(!keepExisting){
27422                 this.clearSelections(true);
27423             }
27424             if(node && !this.isSelected(node)){
27425                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
27426                     Ext.fly(node).addClass(this.selectedClass);
27427                     this.selected.add(node);
27428                     this.last = node.viewIndex;
27429                     if(!suppressEvent){
27430                         this.fireEvent("selectionchange", this, this.selected.elements);
27431                     }
27432                 }
27433             }
27434         }
27435     },
27436
27437     
27438     selectRange : function(start, end, keepExisting){
27439         if(!keepExisting){
27440             this.clearSelections(true);
27441         }
27442         this.select(this.getNodes(start, end), true);
27443     },
27444
27445     
27446     getNode : function(nodeInfo){
27447         if(Ext.isString(nodeInfo)){
27448             return document.getElementById(nodeInfo);
27449         }else if(Ext.isNumber(nodeInfo)){
27450             return this.all.elements[nodeInfo];
27451         }else if(nodeInfo instanceof Ext.data.Record){
27452             var idx = this.store.indexOf(nodeInfo);
27453             return this.all.elements[idx];
27454         }
27455         return nodeInfo;
27456     },
27457
27458     
27459     getNodes : function(start, end){
27460         var ns = this.all.elements;
27461         start = start || 0;
27462         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
27463         var nodes = [], i;
27464         if(start <= end){
27465             for(i = start; i <= end && ns[i]; i++){
27466                 nodes.push(ns[i]);
27467             }
27468         } else{
27469             for(i = start; i >= end && ns[i]; i--){
27470                 nodes.push(ns[i]);
27471             }
27472         }
27473         return nodes;
27474     },
27475
27476     
27477     indexOf : function(node){
27478         node = this.getNode(node);
27479         if(Ext.isNumber(node.viewIndex)){
27480             return node.viewIndex;
27481         }
27482         return this.all.indexOf(node);
27483     },
27484
27485     
27486     onBeforeLoad : function(){
27487         if(this.loadingText){
27488             this.clearSelections(false, true);
27489             this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
27490             this.all.clear();
27491         }
27492     },
27493
27494     onDestroy : function(){
27495         this.all.clear();
27496         this.selected.clear();
27497         Ext.DataView.superclass.onDestroy.call(this);
27498         this.bindStore(null);
27499     }
27500 });
27501
27502
27503 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
27504
27505 Ext.reg('dataview', Ext.DataView);
27506
27507 Ext.list.ListView = Ext.extend(Ext.DataView, {
27508     
27509     
27510     
27511     itemSelector: 'dl',
27512     
27513     selectedClass:'x-list-selected',
27514     
27515     overClass:'x-list-over',
27516     
27517     
27518     scrollOffset : undefined,
27519     
27520     columnResize: true,
27521     
27522     
27523     columnSort: true,
27524     
27525
27526     
27527     maxColumnWidth: Ext.isIE ? 99 : 100,
27528
27529     initComponent : function(){
27530         if(this.columnResize){
27531             this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
27532             this.colResizer.init(this);
27533         }
27534         if(this.columnSort){
27535             this.colSorter = new Ext.list.Sorter(this.columnSort);
27536             this.colSorter.init(this);
27537         }
27538         if(!this.internalTpl){
27539             this.internalTpl = new Ext.XTemplate(
27540                 '<div class="x-list-header"><div class="x-list-header-inner">',
27541                     '<tpl for="columns">',
27542                     '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
27543                         '{header}',
27544                     '</em></div>',
27545                     '</tpl>',
27546                     '<div class="x-clear"></div>',
27547                 '</div></div>',
27548                 '<div class="x-list-body"><div class="x-list-body-inner">',
27549                 '</div></div>'
27550             );
27551         }
27552         if(!this.tpl){
27553             this.tpl = new Ext.XTemplate(
27554                 '<tpl for="rows">',
27555                     '<dl>',
27556                         '<tpl for="parent.columns">',
27557                         '<dt style="width:{[values.width*100]}%;text-align:{align};">',
27558                         '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
27559                             '{[values.tpl.apply(parent)]}',
27560                         '</em></dt>',
27561                         '</tpl>',
27562                         '<div class="x-clear"></div>',
27563                     '</dl>',
27564                 '</tpl>'
27565             );
27566         };
27567
27568         var cs = this.columns,
27569             allocatedWidth = 0,
27570             colsWithWidth = 0,
27571             len = cs.length,
27572             columns = [];
27573
27574         for(var i = 0; i < len; i++){
27575             var c = cs[i];
27576             if(!c.isColumn) {
27577                 c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
27578                 c = Ext.create(c);
27579             }
27580             if(c.width) {
27581                 allocatedWidth += c.width*100;
27582                 colsWithWidth++;
27583             }
27584             columns.push(c);
27585         }
27586
27587         cs = this.columns = columns;
27588
27589         
27590         if(colsWithWidth < len){
27591             var remaining = len - colsWithWidth;
27592             if(allocatedWidth < this.maxColumnWidth){
27593                 var perCol = ((this.maxColumnWidth-allocatedWidth) / remaining)/100;
27594                 for(var j = 0; j < len; j++){
27595                     var c = cs[j];
27596                     if(!c.width){
27597                         c.width = perCol;
27598                     }
27599                 }
27600             }
27601         }
27602         Ext.list.ListView.superclass.initComponent.call(this);
27603     },
27604
27605     onRender : function(){
27606         this.autoEl = {
27607             cls: 'x-list-wrap'
27608         };
27609         Ext.list.ListView.superclass.onRender.apply(this, arguments);
27610
27611         this.internalTpl.overwrite(this.el, {columns: this.columns});
27612
27613         this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
27614         this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
27615
27616         if(this.hideHeaders){
27617             this.el.dom.firstChild.style.display = 'none';
27618         }
27619     },
27620
27621     getTemplateTarget : function(){
27622         return this.innerBody;
27623     },
27624
27625     
27626     collectData : function(){
27627         var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
27628         return {
27629             columns: this.columns,
27630             rows: rs
27631         }
27632     },
27633
27634     verifyInternalSize : function(){
27635         if(this.lastSize){
27636             this.onResize(this.lastSize.width, this.lastSize.height);
27637         }
27638     },
27639
27640     
27641     onResize : function(w, h){
27642         var bd = this.innerBody.dom;
27643         var hd = this.innerHd.dom;
27644         if(!bd){
27645             return;
27646         }
27647         var bdp = bd.parentNode;
27648         if(Ext.isNumber(w)){
27649             var sw = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
27650             if(this.reserveScrollOffset || ((bdp.offsetWidth - bdp.clientWidth) > 10)){
27651                 bd.style.width = sw + 'px';
27652                 hd.style.width = sw + 'px';
27653             }else{
27654                 bd.style.width = w + 'px';
27655                 hd.style.width = w + 'px';
27656                 setTimeout(function(){
27657                     if((bdp.offsetWidth - bdp.clientWidth) > 10){
27658                         bd.style.width = sw + 'px';
27659                         hd.style.width = sw + 'px';
27660                     }
27661                 }, 10);
27662             }
27663         }
27664         if(Ext.isNumber(h)){
27665             bdp.style.height = (h - hd.parentNode.offsetHeight) + 'px';
27666         }
27667     },
27668
27669     updateIndexes : function(){
27670         Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
27671         this.verifyInternalSize();
27672     },
27673
27674     findHeaderIndex : function(hd){
27675         hd = hd.dom || hd;
27676         var pn = hd.parentNode, cs = pn.parentNode.childNodes;
27677         for(var i = 0, c; c = cs[i]; i++){
27678             if(c == pn){
27679                 return i;
27680             }
27681         }
27682         return -1;
27683     },
27684
27685     setHdWidths : function(){
27686         var els = this.innerHd.dom.getElementsByTagName('div');
27687         for(var i = 0, cs = this.columns, len = cs.length; i < len; i++){
27688             els[i].style.width = (cs[i].width*100) + '%';
27689         }
27690     }
27691 });
27692
27693 Ext.reg('listview', Ext.list.ListView);
27694
27695
27696 Ext.ListView = Ext.list.ListView;
27697 Ext.list.Column = Ext.extend(Object, {
27698     
27699     isColumn: true,
27700     
27701             
27702     align: 'left',
27703         
27704     header: '',
27705     
27706         
27707     width: null,
27708
27709     
27710     cls: '',
27711     
27712     
27713
27714     
27715     
27716     constructor : function(c){
27717         if(!c.tpl){
27718             c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
27719         }
27720         else if(Ext.isString(c.tpl)){
27721             c.tpl = new Ext.XTemplate(c.tpl);
27722         }
27723         
27724         Ext.apply(this, c);
27725     }
27726 });
27727
27728 Ext.reg('lvcolumn', Ext.list.Column);
27729
27730
27731 Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
27732         
27733     format: '0,000.00',
27734     
27735     constructor : function(c) {
27736         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
27737         Ext.list.NumberColumn.superclass.constructor.call(this, c);
27738     }
27739 });
27740
27741 Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
27742
27743
27744 Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
27745     format: 'm/d/Y',
27746     constructor : function(c) {
27747         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
27748         Ext.list.DateColumn.superclass.constructor.call(this, c);
27749     }
27750 });
27751 Ext.reg('lvdatecolumn', Ext.list.DateColumn);
27752
27753
27754 Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
27755     
27756     trueText: 'true',
27757     
27758     falseText: 'false',
27759     
27760     undefinedText: '&#160;',
27761     
27762     constructor : function(c) {
27763         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
27764         
27765         var t = this.trueText, f = this.falseText, u = this.undefinedText;
27766         c.tpl.format = function(v){
27767             if(v === undefined){
27768                 return u;
27769             }
27770             if(!v || v === 'false'){
27771                 return f;
27772             }
27773             return t;
27774         };
27775         
27776         Ext.list.DateColumn.superclass.constructor.call(this, c);
27777     }
27778 });
27779
27780 Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
27781 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
27782     
27783     minPct: .05,
27784
27785     constructor: function(config){
27786         Ext.apply(this, config);
27787         Ext.list.ColumnResizer.superclass.constructor.call(this);
27788     },
27789     init : function(listView){
27790         this.view = listView;
27791         listView.on('render', this.initEvents, this);
27792     },
27793
27794     initEvents : function(view){
27795         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
27796         this.tracker = new Ext.dd.DragTracker({
27797             onBeforeStart: this.onBeforeStart.createDelegate(this),
27798             onStart: this.onStart.createDelegate(this),
27799             onDrag: this.onDrag.createDelegate(this),
27800             onEnd: this.onEnd.createDelegate(this),
27801             tolerance: 3,
27802             autoStart: 300
27803         });
27804         this.tracker.initEl(view.innerHd);
27805         view.on('beforedestroy', this.tracker.destroy, this.tracker);
27806     },
27807
27808     handleHdMove : function(e, t){
27809         var hw = 5,
27810             x = e.getPageX(),
27811             hd = e.getTarget('em', 3, true);
27812         if(hd){
27813             var r = hd.getRegion(),
27814                 ss = hd.dom.style,
27815                 pn = hd.dom.parentNode;
27816
27817             if(x - r.left <= hw && pn != pn.parentNode.firstChild){
27818                 this.activeHd = Ext.get(pn.previousSibling.firstChild);
27819                 ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
27820             } else if(r.right - x <= hw && pn != pn.parentNode.lastChild.previousSibling){
27821                 this.activeHd = hd;
27822                 ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
27823             } else{
27824                 delete this.activeHd;
27825                 ss.cursor = '';
27826             }
27827         }
27828     },
27829
27830     onBeforeStart : function(e){
27831         this.dragHd = this.activeHd;
27832         return !!this.dragHd;
27833     },
27834
27835     onStart: function(e){
27836         this.view.disableHeaders = true;
27837         this.proxy = this.view.el.createChild({cls:'x-list-resizer'});
27838         this.proxy.setHeight(this.view.el.getHeight());
27839
27840         var x = this.tracker.getXY()[0],
27841             w = this.view.innerHd.getWidth();
27842
27843         this.hdX = this.dragHd.getX();
27844         this.hdIndex = this.view.findHeaderIndex(this.dragHd);
27845
27846         this.proxy.setX(this.hdX);
27847         this.proxy.setWidth(x-this.hdX);
27848
27849         this.minWidth = w*this.minPct;
27850         this.maxWidth = w - (this.minWidth*(this.view.columns.length-1-this.hdIndex));
27851     },
27852
27853     onDrag: function(e){
27854         var cursorX = this.tracker.getXY()[0];
27855         this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
27856     },
27857
27858     onEnd: function(e){
27859         
27860         var nw = this.proxy.getWidth();
27861         this.proxy.remove();
27862
27863         var index = this.hdIndex,
27864             vw = this.view,
27865             cs = vw.columns,
27866             len = cs.length,
27867             w = this.view.innerHd.getWidth(),
27868             minPct = this.minPct * 100,
27869             pct = Math.ceil((nw * vw.maxColumnWidth) / w),
27870             diff = (cs[index].width * 100) - pct,
27871             eachItem = Math.floor(diff / (len-1-index)),
27872             mod = diff - (eachItem * (len-1-index));
27873
27874         for(var i = index+1; i < len; i++){
27875             var cw = (cs[i].width * 100) + eachItem,
27876                 ncw = Math.max(minPct, cw);
27877             if(cw != ncw){
27878                 mod += cw - ncw;
27879             }
27880             cs[i].width = ncw / 100;
27881         }
27882         cs[index].width = pct / 100;
27883         cs[index+1].width += (mod / 100);
27884         delete this.dragHd;
27885         vw.setHdWidths();
27886         vw.refresh();
27887         setTimeout(function(){
27888             vw.disableHeaders = false;
27889         }, 100);
27890     }
27891 });
27892
27893
27894 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
27895 Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
27896     
27897     sortClasses : ["sort-asc", "sort-desc"],
27898
27899     constructor: function(config){
27900         Ext.apply(this, config);
27901         Ext.list.Sorter.superclass.constructor.call(this);
27902     },
27903
27904     init : function(listView){
27905         this.view = listView;
27906         listView.on('render', this.initEvents, this);
27907     },
27908
27909     initEvents : function(view){
27910         view.mon(view.innerHd, 'click', this.onHdClick, this);
27911         view.innerHd.setStyle('cursor', 'pointer');
27912         view.mon(view.store, 'datachanged', this.updateSortState, this);
27913         this.updateSortState.defer(10, this, [view.store]);
27914     },
27915
27916     updateSortState : function(store){
27917         var state = store.getSortState();
27918         if(!state){
27919             return;
27920         }
27921         this.sortState = state;
27922         var cs = this.view.columns, sortColumn = -1;
27923         for(var i = 0, len = cs.length; i < len; i++){
27924             if(cs[i].dataIndex == state.field){
27925                 sortColumn = i;
27926                 break;
27927             }
27928         }
27929         if(sortColumn != -1){
27930             var sortDir = state.direction;
27931             this.updateSortIcon(sortColumn, sortDir);
27932         }
27933     },
27934
27935     updateSortIcon : function(col, dir){
27936         var sc = this.sortClasses;
27937         var hds = this.view.innerHd.select('em').removeClass(sc);
27938         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
27939     },
27940
27941     onHdClick : function(e){
27942         var hd = e.getTarget('em', 3);
27943         if(hd && !this.view.disableHeaders){
27944             var index = this.view.findHeaderIndex(hd);
27945             this.view.store.sort(this.view.columns[index].dataIndex);
27946         }
27947     }
27948 });
27949
27950
27951 Ext.ListView.Sorter = Ext.list.Sorter;
27952 Ext.TabPanel = Ext.extend(Ext.Panel,  {
27953     
27954     
27955     
27956     deferredRender : true,
27957     
27958     tabWidth : 120,
27959     
27960     minTabWidth : 30,
27961     
27962     resizeTabs : false,
27963     
27964     enableTabScroll : false,
27965     
27966     scrollIncrement : 0,
27967     
27968     scrollRepeatInterval : 400,
27969     
27970     scrollDuration : 0.35,
27971     
27972     animScroll : true,
27973     
27974     tabPosition : 'top',
27975     
27976     baseCls : 'x-tab-panel',
27977     
27978     autoTabs : false,
27979     
27980     autoTabSelector : 'div.x-tab',
27981     
27982     activeTab : undefined,
27983     
27984     tabMargin : 2,
27985     
27986     plain : false,
27987     
27988     wheelIncrement : 20,
27989
27990     
27991     idDelimiter : '__',
27992
27993     
27994     itemCls : 'x-tab-item',
27995
27996     
27997     elements : 'body',
27998     headerAsText : false,
27999     frame : false,
28000     hideBorders :true,
28001
28002     
28003     initComponent : function(){
28004         this.frame = false;
28005         Ext.TabPanel.superclass.initComponent.call(this);
28006         this.addEvents(
28007             
28008             'beforetabchange',
28009             
28010             'tabchange',
28011             
28012             'contextmenu'
28013         );
28014         
28015         this.setLayout(new Ext.layout.CardLayout(Ext.apply({
28016             layoutOnCardChange: this.layoutOnTabChange,
28017             deferredRender: this.deferredRender
28018         }, this.layoutConfig)));
28019
28020         if(this.tabPosition == 'top'){
28021             this.elements += ',header';
28022             this.stripTarget = 'header';
28023         }else {
28024             this.elements += ',footer';
28025             this.stripTarget = 'footer';
28026         }
28027         if(!this.stack){
28028             this.stack = Ext.TabPanel.AccessStack();
28029         }
28030         this.initItems();
28031     },
28032
28033     
28034     onRender : function(ct, position){
28035         Ext.TabPanel.superclass.onRender.call(this, ct, position);
28036
28037         if(this.plain){
28038             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
28039             this[pos].addClass('x-tab-panel-'+pos+'-plain');
28040         }
28041
28042         var st = this[this.stripTarget];
28043
28044         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
28045             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
28046
28047         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
28048         st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
28049         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
28050
28051         
28052         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
28053         this.strip.createChild({cls:'x-clear'});
28054
28055         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
28056
28057         
28058         if(!this.itemTpl){
28059             var tt = new Ext.Template(
28060                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
28061                  '<a class="x-tab-right" href="#"><em class="x-tab-left">',
28062                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
28063                  '</em></a></li>'
28064             );
28065             tt.disableFormats = true;
28066             tt.compile();
28067             Ext.TabPanel.prototype.itemTpl = tt;
28068         }
28069
28070         this.items.each(this.initTab, this);
28071     },
28072
28073     
28074     afterRender : function(){
28075         Ext.TabPanel.superclass.afterRender.call(this);
28076         if(this.autoTabs){
28077             this.readTabs(false);
28078         }
28079         if(this.activeTab !== undefined){
28080             var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
28081             delete this.activeTab;
28082             this.setActiveTab(item);
28083         }
28084     },
28085
28086     
28087     initEvents : function(){
28088         Ext.TabPanel.superclass.initEvents.call(this);
28089         this.mon(this.strip, {
28090             scope: this,
28091             mousedown: this.onStripMouseDown,
28092             contextmenu: this.onStripContextMenu
28093         });
28094         if(this.enableTabScroll){
28095             this.mon(this.strip, 'mousewheel', this.onWheel, this);
28096         }
28097     },
28098
28099     
28100     findTargets : function(e){
28101         var item = null,
28102             itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
28103
28104         if(itemEl){
28105             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
28106             if(item.disabled){
28107                 return {
28108                     close : null,
28109                     item : null,
28110                     el : null
28111                 };
28112             }
28113         }
28114         return {
28115             close : e.getTarget('.x-tab-strip-close', this.strip),
28116             item : item,
28117             el : itemEl
28118         };
28119     },
28120
28121     
28122     onStripMouseDown : function(e){
28123         if(e.button !== 0){
28124             return;
28125         }
28126         e.preventDefault();
28127         var t = this.findTargets(e);
28128         if(t.close){
28129             if (t.item.fireEvent('beforeclose', t.item) !== false) {
28130                 t.item.fireEvent('close', t.item);
28131                 this.remove(t.item);
28132             }
28133             return;
28134         }
28135         if(t.item && t.item != this.activeTab){
28136             this.setActiveTab(t.item);
28137         }
28138     },
28139
28140     
28141     onStripContextMenu : function(e){
28142         e.preventDefault();
28143         var t = this.findTargets(e);
28144         if(t.item){
28145             this.fireEvent('contextmenu', this, t.item, e);
28146         }
28147     },
28148
28149     
28150     readTabs : function(removeExisting){
28151         if(removeExisting === true){
28152             this.items.each(function(item){
28153                 this.remove(item);
28154             }, this);
28155         }
28156         var tabs = this.el.query(this.autoTabSelector);
28157         for(var i = 0, len = tabs.length; i < len; i++){
28158             var tab = tabs[i],
28159                 title = tab.getAttribute('title');
28160             tab.removeAttribute('title');
28161             this.add({
28162                 title: title,
28163                 contentEl: tab
28164             });
28165         }
28166     },
28167
28168     
28169     initTab : function(item, index){
28170         var before = this.strip.dom.childNodes[index],
28171             p = this.getTemplateArgs(item),
28172             el = before ?
28173                  this.itemTpl.insertBefore(before, p) :
28174                  this.itemTpl.append(this.strip, p),
28175             cls = 'x-tab-strip-over',
28176             tabEl = Ext.get(el);
28177
28178         tabEl.hover(function(){
28179             if(!item.disabled){
28180                 tabEl.addClass(cls);
28181             }
28182         }, function(){
28183             tabEl.removeClass(cls);
28184         });
28185
28186         if(item.tabTip){
28187             tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
28188         }
28189         item.tabEl = el;
28190
28191         
28192         tabEl.select('a').on('click', function(e){
28193             if(!e.getPageX()){
28194                 this.onStripMouseDown(e);
28195             }
28196         }, this, {preventDefault: true});
28197
28198         item.on({
28199             scope: this,
28200             disable: this.onItemDisabled,
28201             enable: this.onItemEnabled,
28202             titlechange: this.onItemTitleChanged,
28203             iconchange: this.onItemIconChanged,
28204             beforeshow: this.onBeforeShowItem
28205         });
28206     },
28207
28208
28209
28210     
28211     getTemplateArgs : function(item) {
28212         var cls = item.closable ? 'x-tab-strip-closable' : '';
28213         if(item.disabled){
28214             cls += ' x-item-disabled';
28215         }
28216         if(item.iconCls){
28217             cls += ' x-tab-with-icon';
28218         }
28219         if(item.tabCls){
28220             cls += ' ' + item.tabCls;
28221         }
28222
28223         return {
28224             id: this.id + this.idDelimiter + item.getItemId(),
28225             text: item.title,
28226             cls: cls,
28227             iconCls: item.iconCls || ''
28228         };
28229     },
28230
28231     
28232     onAdd : function(c){
28233         Ext.TabPanel.superclass.onAdd.call(this, c);
28234         if(this.rendered){
28235             var items = this.items;
28236             this.initTab(c, items.indexOf(c));
28237             this.delegateUpdates();
28238         }
28239     },
28240
28241     
28242     onBeforeAdd : function(item){
28243         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
28244         if(existing){
28245             this.setActiveTab(item);
28246             return false;
28247         }
28248         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
28249         var es = item.elements;
28250         item.elements = es ? es.replace(',header', '') : es;
28251         item.border = (item.border === true);
28252     },
28253
28254     
28255     onRemove : function(c){
28256         var te = Ext.get(c.tabEl);
28257         
28258         if(te){
28259             te.select('a').removeAllListeners();
28260             Ext.destroy(te);
28261         }
28262         Ext.TabPanel.superclass.onRemove.call(this, c);
28263         this.stack.remove(c);
28264         delete c.tabEl;
28265         c.un('disable', this.onItemDisabled, this);
28266         c.un('enable', this.onItemEnabled, this);
28267         c.un('titlechange', this.onItemTitleChanged, this);
28268         c.un('iconchange', this.onItemIconChanged, this);
28269         c.un('beforeshow', this.onBeforeShowItem, this);
28270         if(c == this.activeTab){
28271             var next = this.stack.next();
28272             if(next){
28273                 this.setActiveTab(next);
28274             }else if(this.items.getCount() > 0){
28275                 this.setActiveTab(0);
28276             }else{
28277                 this.setActiveTab(null);
28278             }
28279         }
28280         if(!this.destroying){
28281             this.delegateUpdates();
28282         }
28283     },
28284
28285     
28286     onBeforeShowItem : function(item){
28287         if(item != this.activeTab){
28288             this.setActiveTab(item);
28289             return false;
28290         }
28291     },
28292
28293     
28294     onItemDisabled : function(item){
28295         var el = this.getTabEl(item);
28296         if(el){
28297             Ext.fly(el).addClass('x-item-disabled');
28298         }
28299         this.stack.remove(item);
28300     },
28301
28302     
28303     onItemEnabled : function(item){
28304         var el = this.getTabEl(item);
28305         if(el){
28306             Ext.fly(el).removeClass('x-item-disabled');
28307         }
28308     },
28309
28310     
28311     onItemTitleChanged : function(item){
28312         var el = this.getTabEl(item);
28313         if(el){
28314             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
28315         }
28316     },
28317
28318     
28319     onItemIconChanged : function(item, iconCls, oldCls){
28320         var el = this.getTabEl(item);
28321         if(el){
28322             el = Ext.get(el);
28323             el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
28324             el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
28325         }
28326     },
28327
28328     
28329     getTabEl : function(item){
28330         var c = this.getComponent(item);
28331         return c ? c.tabEl : null;
28332     },
28333
28334     
28335     onResize : function(){
28336         Ext.TabPanel.superclass.onResize.apply(this, arguments);
28337         this.delegateUpdates();
28338     },
28339
28340     
28341     beginUpdate : function(){
28342         this.suspendUpdates = true;
28343     },
28344
28345     
28346     endUpdate : function(){
28347         this.suspendUpdates = false;
28348         this.delegateUpdates();
28349     },
28350
28351     
28352     hideTabStripItem : function(item){
28353         item = this.getComponent(item);
28354         var el = this.getTabEl(item);
28355         if(el){
28356             el.style.display = 'none';
28357             this.delegateUpdates();
28358         }
28359         this.stack.remove(item);
28360     },
28361
28362     
28363     unhideTabStripItem : function(item){
28364         item = this.getComponent(item);
28365         var el = this.getTabEl(item);
28366         if(el){
28367             el.style.display = '';
28368             this.delegateUpdates();
28369         }
28370     },
28371
28372     
28373     delegateUpdates : function(){
28374         if(this.suspendUpdates){
28375             return;
28376         }
28377         if(this.resizeTabs && this.rendered){
28378             this.autoSizeTabs();
28379         }
28380         if(this.enableTabScroll && this.rendered){
28381             this.autoScrollTabs();
28382         }
28383     },
28384
28385     
28386     autoSizeTabs : function(){
28387         var count = this.items.length,
28388             ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
28389             ow = this[ce].dom.offsetWidth,
28390             aw = this[ce].dom.clientWidth;
28391
28392         if(!this.resizeTabs || count < 1 || !aw){ 
28393             return;
28394         }
28395
28396         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
28397         this.lastTabWidth = each;
28398         var lis = this.strip.query('li:not(.x-tab-edge)');
28399         for(var i = 0, len = lis.length; i < len; i++) {
28400             var li = lis[i],
28401                 inner = Ext.fly(li).child('.x-tab-strip-inner', true),
28402                 tw = li.offsetWidth,
28403                 iw = inner.offsetWidth;
28404             inner.style.width = (each - (tw-iw)) + 'px';
28405         }
28406     },
28407
28408     
28409     adjustBodyWidth : function(w){
28410         if(this.header){
28411             this.header.setWidth(w);
28412         }
28413         if(this.footer){
28414             this.footer.setWidth(w);
28415         }
28416         return w;
28417     },
28418
28419     
28420     setActiveTab : function(item){
28421         item = this.getComponent(item);
28422         if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
28423             return;
28424         }
28425         if(!this.rendered){
28426             this.activeTab = item;
28427             return;
28428         }
28429         if(this.activeTab != item){
28430             if(this.activeTab){
28431                 var oldEl = this.getTabEl(this.activeTab);
28432                 if(oldEl){
28433                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
28434                 }
28435             }
28436             this.activeTab = item;
28437             if(item){
28438                 var el = this.getTabEl(item);
28439                 Ext.fly(el).addClass('x-tab-strip-active');
28440                 this.stack.add(item);
28441
28442                 this.layout.setActiveItem(item);
28443                 if(this.scrolling){
28444                     this.scrollToTab(item, this.animScroll);
28445                 }
28446             }
28447             this.fireEvent('tabchange', this, item);
28448         }
28449     },
28450
28451     
28452     getActiveTab : function(){
28453         return this.activeTab || null;
28454     },
28455
28456     
28457     getItem : function(item){
28458         return this.getComponent(item);
28459     },
28460
28461     
28462     autoScrollTabs : function(){
28463         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
28464         var count = this.items.length,
28465             ow = this.pos.dom.offsetWidth,
28466             tw = this.pos.dom.clientWidth,
28467             wrap = this.stripWrap,
28468             wd = wrap.dom,
28469             cw = wd.offsetWidth,
28470             pos = this.getScrollPos(),
28471             l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
28472
28473         if(!this.enableTabScroll || cw < 20){ 
28474             return;
28475         }
28476         if(count == 0 || l <= tw){
28477             
28478             wd.scrollLeft = 0;
28479             wrap.setWidth(tw);
28480             if(this.scrolling){
28481                 this.scrolling = false;
28482                 this.pos.removeClass('x-tab-scrolling');
28483                 this.scrollLeft.hide();
28484                 this.scrollRight.hide();
28485                 
28486                 if(Ext.isAir || Ext.isWebKit){
28487                     wd.style.marginLeft = '';
28488                     wd.style.marginRight = '';
28489                 }
28490             }
28491         }else{
28492             if(!this.scrolling){
28493                 this.pos.addClass('x-tab-scrolling');
28494                 
28495                 if(Ext.isAir || Ext.isWebKit){
28496                     wd.style.marginLeft = '18px';
28497                     wd.style.marginRight = '18px';
28498                 }
28499             }
28500             tw -= wrap.getMargins('lr');
28501             wrap.setWidth(tw > 20 ? tw : 20);
28502             if(!this.scrolling){
28503                 if(!this.scrollLeft){
28504                     this.createScrollers();
28505                 }else{
28506                     this.scrollLeft.show();
28507                     this.scrollRight.show();
28508                 }
28509             }
28510             this.scrolling = true;
28511             if(pos > (l-tw)){ 
28512                 wd.scrollLeft = l-tw;
28513             }else{ 
28514                 this.scrollToTab(this.activeTab, false);
28515             }
28516             this.updateScrollButtons();
28517         }
28518     },
28519
28520     
28521     createScrollers : function(){
28522         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
28523         var h = this.stripWrap.dom.offsetHeight;
28524
28525         
28526         var sl = this.pos.insertFirst({
28527             cls:'x-tab-scroller-left'
28528         });
28529         sl.setHeight(h);
28530         sl.addClassOnOver('x-tab-scroller-left-over');
28531         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
28532             interval : this.scrollRepeatInterval,
28533             handler: this.onScrollLeft,
28534             scope: this
28535         });
28536         this.scrollLeft = sl;
28537
28538         
28539         var sr = this.pos.insertFirst({
28540             cls:'x-tab-scroller-right'
28541         });
28542         sr.setHeight(h);
28543         sr.addClassOnOver('x-tab-scroller-right-over');
28544         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
28545             interval : this.scrollRepeatInterval,
28546             handler: this.onScrollRight,
28547             scope: this
28548         });
28549         this.scrollRight = sr;
28550     },
28551
28552     
28553     getScrollWidth : function(){
28554         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
28555     },
28556
28557     
28558     getScrollPos : function(){
28559         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
28560     },
28561
28562     
28563     getScrollArea : function(){
28564         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
28565     },
28566
28567     
28568     getScrollAnim : function(){
28569         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
28570     },
28571
28572     
28573     getScrollIncrement : function(){
28574         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
28575     },
28576
28577     
28578
28579     scrollToTab : function(item, animate){
28580         if(!item){
28581             return;
28582         }
28583         var el = this.getTabEl(item),
28584             pos = this.getScrollPos(),
28585             area = this.getScrollArea(),
28586             left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
28587             right = left + el.offsetWidth;
28588         if(left < pos){
28589             this.scrollTo(left, animate);
28590         }else if(right > (pos + area)){
28591             this.scrollTo(right - area, animate);
28592         }
28593     },
28594
28595     
28596     scrollTo : function(pos, animate){
28597         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
28598         if(!animate){
28599             this.updateScrollButtons();
28600         }
28601     },
28602
28603     onWheel : function(e){
28604         var d = e.getWheelDelta()*this.wheelIncrement*-1;
28605         e.stopEvent();
28606
28607         var pos = this.getScrollPos(),
28608             newpos = pos + d,
28609             sw = this.getScrollWidth()-this.getScrollArea();
28610
28611         var s = Math.max(0, Math.min(sw, newpos));
28612         if(s != pos){
28613             this.scrollTo(s, false);
28614         }
28615     },
28616
28617     
28618     onScrollRight : function(){
28619         var sw = this.getScrollWidth()-this.getScrollArea(),
28620             pos = this.getScrollPos(),
28621             s = Math.min(sw, pos + this.getScrollIncrement());
28622         if(s != pos){
28623             this.scrollTo(s, this.animScroll);
28624         }
28625     },
28626
28627     
28628     onScrollLeft : function(){
28629         var pos = this.getScrollPos(),
28630             s = Math.max(0, pos - this.getScrollIncrement());
28631         if(s != pos){
28632             this.scrollTo(s, this.animScroll);
28633         }
28634     },
28635
28636     
28637     updateScrollButtons : function(){
28638         var pos = this.getScrollPos();
28639         this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
28640         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
28641     },
28642
28643     
28644     beforeDestroy : function() {
28645         Ext.destroy(this.leftRepeater, this.rightRepeater);
28646         this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
28647         this.activeTab = null;
28648         Ext.TabPanel.superclass.beforeDestroy.apply(this);
28649     }
28650
28651     
28652     
28653     
28654     
28655     
28656     
28657     
28658     
28659     
28660     
28661     
28662     
28663 });
28664 Ext.reg('tabpanel', Ext.TabPanel);
28665
28666
28667 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
28668
28669
28670 Ext.TabPanel.AccessStack = function(){
28671     var items = [];
28672     return {
28673         add : function(item){
28674             items.push(item);
28675             if(items.length > 10){
28676                 items.shift();
28677             }
28678         },
28679
28680         remove : function(item){
28681             var s = [];
28682             for(var i = 0, len = items.length; i < len; i++) {
28683                 if(items[i] != item){
28684                     s.push(items[i]);
28685                 }
28686             }
28687             items = s;
28688         },
28689
28690         next : function(){
28691             return items.pop();
28692         }
28693     };
28694 };
28695
28696 Ext.Button = Ext.extend(Ext.BoxComponent, {
28697     
28698     hidden : false,
28699     
28700     disabled : false,
28701     
28702     pressed : false,
28703
28704     
28705
28706     
28707
28708     
28709     enableToggle : false,
28710     
28711     
28712     
28713     menuAlign : 'tl-bl?',
28714
28715     
28716     
28717     
28718     type : 'button',
28719
28720     
28721     menuClassTarget : 'tr:nth(2)',
28722
28723     
28724     clickEvent : 'click',
28725
28726     
28727     handleMouseEvents : true,
28728
28729     
28730     tooltipType : 'qtip',
28731
28732     
28733     buttonSelector : 'button:first-child',
28734
28735     
28736     scale : 'small',
28737
28738     
28739
28740     
28741     iconAlign : 'left',
28742
28743     
28744     arrowAlign : 'right',
28745
28746     
28747     
28748     
28749     
28750
28751     initComponent : function(){
28752         Ext.Button.superclass.initComponent.call(this);
28753
28754         this.addEvents(
28755             
28756             'click',
28757             
28758             'toggle',
28759             
28760             'mouseover',
28761             
28762             'mouseout',
28763             
28764             'menushow',
28765             
28766             'menuhide',
28767             
28768             'menutriggerover',
28769             
28770             'menutriggerout'
28771         );
28772         if(this.menu){
28773             this.menu = Ext.menu.MenuMgr.get(this.menu);
28774         }
28775         if(Ext.isString(this.toggleGroup)){
28776             this.enableToggle = true;
28777         }
28778     },
28779
28780
28781     getTemplateArgs : function(){
28782         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
28783     },
28784
28785     
28786     setButtonClass : function(){
28787         if(this.useSetClass){
28788             if(!Ext.isEmpty(this.oldCls)){
28789                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
28790             }
28791             this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
28792             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
28793         }
28794     },
28795
28796     
28797     getMenuClass : function(){
28798         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
28799     },
28800
28801     
28802     onRender : function(ct, position){
28803         if(!this.template){
28804             if(!Ext.Button.buttonTemplate){
28805                 
28806                 Ext.Button.buttonTemplate = new Ext.Template(
28807                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
28808                     '<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>',
28809                     '<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>',
28810                     '<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>',
28811                     '</tbody></table>');
28812                 Ext.Button.buttonTemplate.compile();
28813             }
28814             this.template = Ext.Button.buttonTemplate;
28815         }
28816
28817         var btn, targs = this.getTemplateArgs();
28818
28819         if(position){
28820             btn = this.template.insertBefore(position, targs, true);
28821         }else{
28822             btn = this.template.append(ct, targs, true);
28823         }
28824         
28825         this.btnEl = btn.child(this.buttonSelector);
28826         this.mon(this.btnEl, {
28827             scope: this,
28828             focus: this.onFocus,
28829             blur: this.onBlur
28830         });
28831
28832         this.initButtonEl(btn, this.btnEl);
28833
28834         Ext.ButtonToggleMgr.register(this);
28835     },
28836
28837     
28838     initButtonEl : function(btn, btnEl){
28839         this.el = btn;
28840         this.setIcon(this.icon);
28841         this.setText(this.text);
28842         this.setIconClass(this.iconCls);
28843         if(Ext.isDefined(this.tabIndex)){
28844             btnEl.dom.tabIndex = this.tabIndex;
28845         }
28846         if(this.tooltip){
28847             this.setTooltip(this.tooltip, true);
28848         }
28849
28850         if(this.handleMouseEvents){
28851             this.mon(btn, {
28852                 scope: this,
28853                 mouseover: this.onMouseOver,
28854                 mousedown: this.onMouseDown
28855             });
28856
28857             
28858             
28859         }
28860
28861         if(this.menu){
28862             this.mon(this.menu, {
28863                 scope: this,
28864                 show: this.onMenuShow,
28865                 hide: this.onMenuHide
28866             });
28867         }
28868
28869         if(this.repeat){
28870             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
28871             this.mon(repeater, 'click', this.onRepeatClick, this);
28872         }else{
28873             this.mon(btn, this.clickEvent, this.onClick, this);
28874         }
28875     },
28876
28877     
28878     afterRender : function(){
28879         Ext.Button.superclass.afterRender.call(this);
28880         this.useSetClass = true;
28881         this.setButtonClass();
28882         this.doc = Ext.getDoc();
28883         this.doAutoWidth();
28884     },
28885
28886     
28887     setIconClass : function(cls){
28888         this.iconCls = cls;
28889         if(this.el){
28890             this.btnEl.dom.className = '';
28891             this.btnEl.addClass(['x-btn-text', cls || '']);
28892             this.setButtonClass();
28893         }
28894         return this;
28895     },
28896
28897     
28898     setTooltip : function(tooltip,  initial){
28899         if(this.rendered){
28900             if(!initial){
28901                 this.clearTip();
28902             }
28903             if(Ext.isObject(tooltip)){
28904                 Ext.QuickTips.register(Ext.apply({
28905                       target: this.btnEl.id
28906                 }, tooltip));
28907                 this.tooltip = tooltip;
28908             }else{
28909                 this.btnEl.dom[this.tooltipType] = tooltip;
28910             }
28911         }else{
28912             this.tooltip = tooltip;
28913         }
28914         return this;
28915     },
28916
28917     
28918     clearTip : function(){
28919         if(Ext.isObject(this.tooltip)){
28920             Ext.QuickTips.unregister(this.btnEl);
28921         }
28922     },
28923
28924     
28925     beforeDestroy : function(){
28926         if(this.rendered){
28927             this.clearTip();
28928         }
28929         if(this.menu && this.destroyMenu !== false) {
28930             Ext.destroy(this.btnEl, this.menu);
28931         }
28932         Ext.destroy(this.repeater);
28933     },
28934
28935     
28936     onDestroy : function(){
28937         if(this.rendered){
28938             this.doc.un('mouseover', this.monitorMouseOver, this);
28939             this.doc.un('mouseup', this.onMouseUp, this);
28940             delete this.doc;
28941             delete this.btnEl;
28942             Ext.ButtonToggleMgr.unregister(this);
28943         }
28944         Ext.Button.superclass.onDestroy.call(this);
28945     },
28946
28947     
28948     doAutoWidth : function(){
28949         if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
28950             this.el.setWidth('auto');
28951             if(Ext.isIE7 && Ext.isStrict){
28952                 var ib = this.btnEl;
28953                 if(ib && ib.getWidth() > 20){
28954                     ib.clip();
28955                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
28956                 }
28957             }
28958             if(this.minWidth){
28959                 if(this.el.getWidth() < this.minWidth){
28960                     this.el.setWidth(this.minWidth);
28961                 }
28962             }
28963         }
28964     },
28965
28966     
28967     setHandler : function(handler, scope){
28968         this.handler = handler;
28969         this.scope = scope;
28970         return this;
28971     },
28972
28973     
28974     setText : function(text){
28975         this.text = text;
28976         if(this.el){
28977             this.btnEl.update(text || '&#160;');
28978             this.setButtonClass();
28979         }
28980         this.doAutoWidth();
28981         return this;
28982     },
28983
28984     
28985     setIcon : function(icon){
28986         this.icon = icon;
28987         if(this.el){
28988             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
28989             this.setButtonClass();
28990         }
28991         return this;
28992     },
28993
28994     
28995     getText : function(){
28996         return this.text;
28997     },
28998
28999     
29000     toggle : function(state, suppressEvent){
29001         state = state === undefined ? !this.pressed : !!state;
29002         if(state != this.pressed){
29003             if(this.rendered){
29004                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
29005             }
29006             this.pressed = state;
29007             if(!suppressEvent){
29008                 this.fireEvent('toggle', this, state);
29009                 if(this.toggleHandler){
29010                     this.toggleHandler.call(this.scope || this, this, state);
29011                 }
29012             }
29013         }
29014         return this;
29015     },
29016
29017     
29018     onDisable : function(){
29019         this.onDisableChange(true);
29020     },
29021
29022     
29023     onEnable : function(){
29024         this.onDisableChange(false);
29025     },
29026
29027     onDisableChange : function(disabled){
29028         if(this.el){
29029             if(!Ext.isIE6 || !this.text){
29030                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
29031             }
29032             this.el.dom.disabled = disabled;
29033         }
29034         this.disabled = disabled;
29035     },
29036
29037     
29038     showMenu : function(){
29039         if(this.rendered && this.menu){
29040             if(this.tooltip){
29041                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
29042             }
29043             if(this.menu.isVisible()){
29044                 this.menu.hide();
29045             }
29046             this.menu.ownerCt = this;
29047             this.menu.show(this.el, this.menuAlign);
29048         }
29049         return this;
29050     },
29051
29052     
29053     hideMenu : function(){
29054         if(this.hasVisibleMenu()){
29055             this.menu.hide();
29056         }
29057         return this;
29058     },
29059
29060     
29061     hasVisibleMenu : function(){
29062         return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
29063     },
29064     
29065     
29066     onRepeatClick : function(repeat, e){
29067         this.onClick(e);
29068     },
29069
29070     
29071     onClick : function(e){
29072         if(e){
29073             e.preventDefault();
29074         }
29075         if(e.button !== 0){
29076             return;
29077         }
29078         if(!this.disabled){
29079             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
29080                 this.toggle();
29081             }
29082             if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
29083                 this.showMenu();
29084             }
29085             this.fireEvent('click', this, e);
29086             if(this.handler){
29087                 
29088                 this.handler.call(this.scope || this, this, e);
29089             }
29090         }
29091     },
29092
29093     
29094     isMenuTriggerOver : function(e, internal){
29095         return this.menu && !internal;
29096     },
29097
29098     
29099     isMenuTriggerOut : function(e, internal){
29100         return this.menu && !internal;
29101     },
29102
29103     
29104     onMouseOver : function(e){
29105         if(!this.disabled){
29106             var internal = e.within(this.el,  true);
29107             if(!internal){
29108                 this.el.addClass('x-btn-over');
29109                 if(!this.monitoringMouseOver){
29110                     this.doc.on('mouseover', this.monitorMouseOver, this);
29111                     this.monitoringMouseOver = true;
29112                 }
29113                 this.fireEvent('mouseover', this, e);
29114             }
29115             if(this.isMenuTriggerOver(e, internal)){
29116                 this.fireEvent('menutriggerover', this, this.menu, e);
29117             }
29118         }
29119     },
29120
29121     
29122     monitorMouseOver : function(e){
29123         if(e.target != this.el.dom && !e.within(this.el)){
29124             if(this.monitoringMouseOver){
29125                 this.doc.un('mouseover', this.monitorMouseOver, this);
29126                 this.monitoringMouseOver = false;
29127             }
29128             this.onMouseOut(e);
29129         }
29130     },
29131
29132     
29133     onMouseOut : function(e){
29134         var internal = e.within(this.el) && e.target != this.el.dom;
29135         this.el.removeClass('x-btn-over');
29136         this.fireEvent('mouseout', this, e);
29137         if(this.isMenuTriggerOut(e, internal)){
29138             this.fireEvent('menutriggerout', this, this.menu, e);
29139         }
29140     },
29141
29142     focus : function() {
29143         this.btnEl.focus();
29144     },
29145
29146     blur : function() {
29147         this.btnEl.blur();
29148     },
29149
29150     
29151     onFocus : function(e){
29152         if(!this.disabled){
29153             this.el.addClass('x-btn-focus');
29154         }
29155     },
29156     
29157     onBlur : function(e){
29158         this.el.removeClass('x-btn-focus');
29159     },
29160
29161     
29162     getClickEl : function(e, isUp){
29163        return this.el;
29164     },
29165
29166     
29167     onMouseDown : function(e){
29168         if(!this.disabled && e.button === 0){
29169             this.getClickEl(e).addClass('x-btn-click');
29170             this.doc.on('mouseup', this.onMouseUp, this);
29171         }
29172     },
29173     
29174     onMouseUp : function(e){
29175         if(e.button === 0){
29176             this.getClickEl(e, true).removeClass('x-btn-click');
29177             this.doc.un('mouseup', this.onMouseUp, this);
29178         }
29179     },
29180     
29181     onMenuShow : function(e){
29182         if(this.menu.ownerCt == this){
29183             this.menu.ownerCt = this;
29184             this.ignoreNextClick = 0;
29185             this.el.addClass('x-btn-menu-active');
29186             this.fireEvent('menushow', this, this.menu);
29187         }
29188     },
29189     
29190     onMenuHide : function(e){
29191         if(this.menu.ownerCt == this){
29192             this.el.removeClass('x-btn-menu-active');
29193             this.ignoreNextClick = this.restoreClick.defer(250, this);
29194             this.fireEvent('menuhide', this, this.menu);
29195             delete this.menu.ownerCt;
29196         }
29197     },
29198
29199     
29200     restoreClick : function(){
29201         this.ignoreNextClick = 0;
29202     }
29203
29204     
29205     
29206     
29207     
29208     
29209     
29210 });
29211 Ext.reg('button', Ext.Button);
29212
29213
29214 Ext.ButtonToggleMgr = function(){
29215    var groups = {};
29216
29217    function toggleGroup(btn, state){
29218        if(state){
29219            var g = groups[btn.toggleGroup];
29220            for(var i = 0, l = g.length; i < l; i++){
29221                if(g[i] != btn){
29222                    g[i].toggle(false);
29223                }
29224            }
29225        }
29226    }
29227
29228    return {
29229        register : function(btn){
29230            if(!btn.toggleGroup){
29231                return;
29232            }
29233            var g = groups[btn.toggleGroup];
29234            if(!g){
29235                g = groups[btn.toggleGroup] = [];
29236            }
29237            g.push(btn);
29238            btn.on('toggle', toggleGroup);
29239        },
29240
29241        unregister : function(btn){
29242            if(!btn.toggleGroup){
29243                return;
29244            }
29245            var g = groups[btn.toggleGroup];
29246            if(g){
29247                g.remove(btn);
29248                btn.un('toggle', toggleGroup);
29249            }
29250        },
29251
29252        
29253        getPressed : function(group){
29254            var g = groups[group];
29255            if(g){
29256                for(var i = 0, len = g.length; i < len; i++){
29257                    if(g[i].pressed === true){
29258                        return g[i];
29259                    }
29260                }
29261            }
29262            return null;
29263        }
29264    };
29265 }();
29266
29267 Ext.SplitButton = Ext.extend(Ext.Button, {
29268         
29269     arrowSelector : 'em',
29270     split: true,
29271
29272     
29273     initComponent : function(){
29274         Ext.SplitButton.superclass.initComponent.call(this);
29275         
29276         this.addEvents("arrowclick");
29277     },
29278
29279     
29280     onRender : function(){
29281         Ext.SplitButton.superclass.onRender.apply(this, arguments);
29282         if(this.arrowTooltip){
29283             this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
29284         }
29285     },
29286
29287     
29288     setArrowHandler : function(handler, scope){
29289         this.arrowHandler = handler;
29290         this.scope = scope;
29291     },
29292
29293     getMenuClass : function(){
29294         return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
29295     },
29296
29297     isClickOnArrow : function(e){
29298         if (this.arrowAlign != 'bottom') {
29299             var visBtn = this.el.child('em.x-btn-split');
29300             var right = visBtn.getRegion().right - visBtn.getPadding('r');
29301             return e.getPageX() > right;
29302         } else {
29303             return e.getPageY() > this.btnEl.getRegion().bottom;
29304         }
29305     },
29306
29307     
29308     onClick : function(e, t){
29309         e.preventDefault();
29310         if(!this.disabled){
29311             if(this.isClickOnArrow(e)){
29312                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
29313                     this.showMenu();
29314                 }
29315                 this.fireEvent("arrowclick", this, e);
29316                 if(this.arrowHandler){
29317                     this.arrowHandler.call(this.scope || this, this, e);
29318                 }
29319             }else{
29320                 if(this.enableToggle){
29321                     this.toggle();
29322                 }
29323                 this.fireEvent("click", this, e);
29324                 if(this.handler){
29325                     this.handler.call(this.scope || this, this, e);
29326                 }
29327             }
29328         }
29329     },
29330
29331     
29332     isMenuTriggerOver : function(e){
29333         return this.menu && e.target.tagName == this.arrowSelector;
29334     },
29335
29336     
29337     isMenuTriggerOut : function(e, internal){
29338         return this.menu && e.target.tagName != this.arrowSelector;
29339     }
29340 });
29341
29342 Ext.reg('splitbutton', Ext.SplitButton);
29343 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
29344     
29345     
29346     
29347     
29348     
29349     
29350
29351     
29352     getItemText : function(item){
29353         if(item && this.showText === true){
29354             var text = '';
29355             if(this.prependText){
29356                 text += this.prependText;
29357             }
29358             text += item.text;
29359             return text;
29360         }
29361         return undefined;
29362     },
29363
29364     
29365     setActiveItem : function(item, suppressEvent){
29366         if(!Ext.isObject(item)){
29367             item = this.menu.getComponent(item);
29368         }
29369         if(item){
29370             if(!this.rendered){
29371                 this.text = this.getItemText(item);
29372                 this.iconCls = item.iconCls;
29373             }else{
29374                 var t = this.getItemText(item);
29375                 if(t){
29376                     this.setText(t);
29377                 }
29378                 this.setIconClass(item.iconCls);
29379             }
29380             this.activeItem = item;
29381             if(!item.checked){
29382                 item.setChecked(true, false);
29383             }
29384             if(this.forceIcon){
29385                 this.setIconClass(this.forceIcon);
29386             }
29387             if(!suppressEvent){
29388                 this.fireEvent('change', this, item);
29389             }
29390         }
29391     },
29392
29393     
29394     getActiveItem : function(){
29395         return this.activeItem;
29396     },
29397
29398     
29399     initComponent : function(){
29400         this.addEvents(
29401             
29402             "change"
29403         );
29404
29405         if(this.changeHandler){
29406             this.on('change', this.changeHandler, this.scope||this);
29407             delete this.changeHandler;
29408         }
29409
29410         this.itemCount = this.items.length;
29411
29412         this.menu = {cls:'x-cycle-menu', items:[]};
29413         var checked = 0;
29414         Ext.each(this.items, function(item, i){
29415             Ext.apply(item, {
29416                 group: item.group || this.id,
29417                 itemIndex: i,
29418                 checkHandler: this.checkHandler,
29419                 scope: this,
29420                 checked: item.checked || false
29421             });
29422             this.menu.items.push(item);
29423             if(item.checked){
29424                 checked = i;
29425             }
29426         }, this);
29427         Ext.CycleButton.superclass.initComponent.call(this);
29428         this.on('click', this.toggleSelected, this);
29429         this.setActiveItem(checked, true);
29430     },
29431
29432     
29433     checkHandler : function(item, pressed){
29434         if(pressed){
29435             this.setActiveItem(item);
29436         }
29437     },
29438
29439     
29440     toggleSelected : function(){
29441         var m = this.menu;
29442         m.render();
29443         
29444         if(!m.hasLayout){
29445             m.doLayout();
29446         }
29447         
29448         var nextIdx, checkItem;
29449         for (var i = 1; i < this.itemCount; i++) {
29450             nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
29451             
29452             checkItem = m.items.itemAt(nextIdx);
29453             
29454             if (!checkItem.disabled) {
29455                 checkItem.setChecked(true);
29456                 break;
29457             }
29458         }
29459     }
29460 });
29461 Ext.reg('cycle', Ext.CycleButton);
29462 Ext.Toolbar = function(config){
29463     if(Ext.isArray(config)){
29464         config = {items: config, layout: 'toolbar'};
29465     } else {
29466         config = Ext.apply({
29467             layout: 'toolbar'
29468         }, config);
29469         if(config.buttons) {
29470             config.items = config.buttons;
29471         }
29472     }
29473     Ext.Toolbar.superclass.constructor.call(this, config);
29474 };
29475
29476 (function(){
29477
29478 var T = Ext.Toolbar;
29479
29480 Ext.extend(T, Ext.Container, {
29481
29482     defaultType: 'button',
29483
29484     
29485
29486     enableOverflow : false,
29487
29488     
29489     
29490
29491     trackMenus : true,
29492     internalDefaults: {removeMode: 'container', hideParent: true},
29493     toolbarCls: 'x-toolbar',
29494
29495     initComponent : function(){
29496         T.superclass.initComponent.call(this);
29497
29498         
29499         this.addEvents('overflowchange');
29500     },
29501
29502     
29503     onRender : function(ct, position){
29504         if(!this.el){
29505             if(!this.autoCreate){
29506                 this.autoCreate = {
29507                     cls: this.toolbarCls + ' x-small-editor'
29508                 };
29509             }
29510             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
29511             Ext.Toolbar.superclass.onRender.apply(this, arguments);
29512         }
29513     },
29514
29515     
29516
29517     
29518     lookupComponent : function(c){
29519         if(Ext.isString(c)){
29520             if(c == '-'){
29521                 c = new T.Separator();
29522             }else if(c == ' '){
29523                 c = new T.Spacer();
29524             }else if(c == '->'){
29525                 c = new T.Fill();
29526             }else{
29527                 c = new T.TextItem(c);
29528             }
29529             this.applyDefaults(c);
29530         }else{
29531             if(c.isFormField || c.render){ 
29532                 c = this.createComponent(c);
29533             }else if(c.tag){ 
29534                 c = new T.Item({autoEl: c});
29535             }else if(c.tagName){ 
29536                 c = new T.Item({el:c});
29537             }else if(Ext.isObject(c)){ 
29538                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
29539             }
29540         }
29541         return c;
29542     },
29543
29544     
29545     applyDefaults : function(c){
29546         if(!Ext.isString(c)){
29547             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
29548             var d = this.internalDefaults;
29549             if(c.events){
29550                 Ext.applyIf(c.initialConfig, d);
29551                 Ext.apply(c, d);
29552             }else{
29553                 Ext.applyIf(c, d);
29554             }
29555         }
29556         return c;
29557     },
29558
29559     
29560     addSeparator : function(){
29561         return this.add(new T.Separator());
29562     },
29563
29564     
29565     addSpacer : function(){
29566         return this.add(new T.Spacer());
29567     },
29568
29569     
29570     addFill : function(){
29571         this.add(new T.Fill());
29572     },
29573
29574     
29575     addElement : function(el){
29576         return this.addItem(new T.Item({el:el}));
29577     },
29578
29579     
29580     addItem : function(item){
29581         return this.add.apply(this, arguments);
29582     },
29583
29584     
29585     addButton : function(config){
29586         if(Ext.isArray(config)){
29587             var buttons = [];
29588             for(var i = 0, len = config.length; i < len; i++) {
29589                 buttons.push(this.addButton(config[i]));
29590             }
29591             return buttons;
29592         }
29593         return this.add(this.constructButton(config));
29594     },
29595
29596     
29597     addText : function(text){
29598         return this.addItem(new T.TextItem(text));
29599     },
29600
29601     
29602     addDom : function(config){
29603         return this.add(new T.Item({autoEl: config}));
29604     },
29605
29606     
29607     addField : function(field){
29608         return this.add(field);
29609     },
29610
29611     
29612     insertButton : function(index, item){
29613         if(Ext.isArray(item)){
29614             var buttons = [];
29615             for(var i = 0, len = item.length; i < len; i++) {
29616                buttons.push(this.insertButton(index + i, item[i]));
29617             }
29618             return buttons;
29619         }
29620         return Ext.Toolbar.superclass.insert.call(this, index, item);
29621     },
29622
29623     
29624     trackMenu : function(item, remove){
29625         if(this.trackMenus && item.menu){
29626             var method = remove ? 'mun' : 'mon';
29627             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
29628             this[method](item, 'menushow', this.onButtonMenuShow, this);
29629             this[method](item, 'menuhide', this.onButtonMenuHide, this);
29630         }
29631     },
29632
29633     
29634     constructButton : function(item){
29635         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
29636         return b;
29637     },
29638
29639     
29640     onAdd : function(c){
29641         Ext.Toolbar.superclass.onAdd.call(this);
29642         this.trackMenu(c);
29643         if(this.disabled){
29644             c.disable();
29645         }
29646     },
29647
29648     
29649     onRemove : function(c){
29650         Ext.Toolbar.superclass.onRemove.call(this);
29651         this.trackMenu(c, true);
29652     },
29653
29654     
29655     onDisable : function(){
29656         this.items.each(function(item){
29657              if(item.disable){
29658                  item.disable();
29659              }
29660         });
29661     },
29662
29663     
29664     onEnable : function(){
29665         this.items.each(function(item){
29666              if(item.enable){
29667                  item.enable();
29668              }
29669         });
29670     },
29671
29672     
29673     onButtonTriggerOver : function(btn){
29674         if(this.activeMenuBtn && this.activeMenuBtn != btn){
29675             this.activeMenuBtn.hideMenu();
29676             btn.showMenu();
29677             this.activeMenuBtn = btn;
29678         }
29679     },
29680
29681     
29682     onButtonMenuShow : function(btn){
29683         this.activeMenuBtn = btn;
29684     },
29685
29686     
29687     onButtonMenuHide : function(btn){
29688         delete this.activeMenuBtn;
29689     }
29690 });
29691 Ext.reg('toolbar', Ext.Toolbar);
29692
29693
29694 T.Item = Ext.extend(Ext.BoxComponent, {
29695     hideParent: true, 
29696     enable:Ext.emptyFn,
29697     disable:Ext.emptyFn,
29698     focus:Ext.emptyFn
29699     
29700 });
29701 Ext.reg('tbitem', T.Item);
29702
29703
29704 T.Separator = Ext.extend(T.Item, {
29705     onRender : function(ct, position){
29706         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
29707     }
29708 });
29709 Ext.reg('tbseparator', T.Separator);
29710
29711
29712 T.Spacer = Ext.extend(T.Item, {
29713     
29714
29715     onRender : function(ct, position){
29716         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
29717     }
29718 });
29719 Ext.reg('tbspacer', T.Spacer);
29720
29721
29722 T.Fill = Ext.extend(T.Item, {
29723     
29724     render : Ext.emptyFn,
29725     isFill : true
29726 });
29727 Ext.reg('tbfill', T.Fill);
29728
29729
29730 T.TextItem = Ext.extend(T.Item, {
29731     
29732
29733     constructor: function(config){
29734         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
29735     },
29736
29737     
29738     onRender : function(ct, position) {
29739         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
29740         T.TextItem.superclass.onRender.call(this, ct, position);
29741     },
29742
29743     
29744     setText : function(t) {
29745         if(this.rendered){
29746             this.el.update(t);
29747         }else{
29748             this.text = t;
29749         }
29750     }
29751 });
29752 Ext.reg('tbtext', T.TextItem);
29753
29754
29755 T.Button = Ext.extend(Ext.Button, {});
29756 T.SplitButton = Ext.extend(Ext.SplitButton, {});
29757 Ext.reg('tbbutton', T.Button);
29758 Ext.reg('tbsplit', T.SplitButton);
29759
29760 })();
29761
29762 Ext.ButtonGroup = Ext.extend(Ext.Panel, {
29763     
29764     
29765     baseCls: 'x-btn-group',
29766     
29767     layout:'table',
29768     defaultType: 'button',
29769     
29770     frame: true,
29771     internalDefaults: {removeMode: 'container', hideParent: true},
29772
29773     initComponent : function(){
29774         this.layoutConfig = this.layoutConfig || {};
29775         Ext.applyIf(this.layoutConfig, {
29776             columns : this.columns
29777         });
29778         if(!this.title){
29779             this.addClass('x-btn-group-notitle');
29780         }
29781         this.on('afterlayout', this.onAfterLayout, this);
29782         Ext.ButtonGroup.superclass.initComponent.call(this);
29783     },
29784
29785     applyDefaults : function(c){
29786         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
29787         var d = this.internalDefaults;
29788         if(c.events){
29789             Ext.applyIf(c.initialConfig, d);
29790             Ext.apply(c, d);
29791         }else{
29792             Ext.applyIf(c, d);
29793         }
29794         return c;
29795     },
29796
29797     onAfterLayout : function(){
29798         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
29799         this.body.setWidth(bodyWidth);
29800         this.el.setWidth(bodyWidth + this.getFrameWidth());
29801     }
29802     
29803 });
29804
29805 Ext.reg('buttongroup', Ext.ButtonGroup);
29806
29807 (function() {
29808
29809 var T = Ext.Toolbar;
29810
29811 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
29812     
29813     
29814     
29815     pageSize : 20,
29816     
29817     
29818     displayMsg : 'Displaying {0} - {1} of {2}',
29819     
29820     emptyMsg : 'No data to display',
29821     
29822     beforePageText : 'Page',
29823     
29824     afterPageText : 'of {0}',
29825     
29826     firstText : 'First Page',
29827     
29828     prevText : 'Previous Page',
29829     
29830     nextText : 'Next Page',
29831     
29832     lastText : 'Last Page',
29833     
29834     refreshText : 'Refresh',
29835
29836     
29837
29838     
29839
29840     
29841
29842     initComponent : function(){
29843         var pagingItems = [this.first = new T.Button({
29844             tooltip: this.firstText,
29845             overflowText: this.firstText,
29846             iconCls: 'x-tbar-page-first',
29847             disabled: true,
29848             handler: this.moveFirst,
29849             scope: this
29850         }), this.prev = new T.Button({
29851             tooltip: this.prevText,
29852             overflowText: this.prevText,
29853             iconCls: 'x-tbar-page-prev',
29854             disabled: true,
29855             handler: this.movePrevious,
29856             scope: this
29857         }), '-', this.beforePageText,
29858         this.inputItem = new Ext.form.NumberField({
29859             cls: 'x-tbar-page-number',
29860             allowDecimals: false,
29861             allowNegative: false,
29862             enableKeyEvents: true,
29863             selectOnFocus: true,
29864             submitValue: false,
29865             listeners: {
29866                 scope: this,
29867                 keydown: this.onPagingKeyDown,
29868                 blur: this.onPagingBlur
29869             }
29870         }), this.afterTextItem = new T.TextItem({
29871             text: String.format(this.afterPageText, 1)
29872         }), '-', this.next = new T.Button({
29873             tooltip: this.nextText,
29874             overflowText: this.nextText,
29875             iconCls: 'x-tbar-page-next',
29876             disabled: true,
29877             handler: this.moveNext,
29878             scope: this
29879         }), this.last = new T.Button({
29880             tooltip: this.lastText,
29881             overflowText: this.lastText,
29882             iconCls: 'x-tbar-page-last',
29883             disabled: true,
29884             handler: this.moveLast,
29885             scope: this
29886         }), '-', this.refresh = new T.Button({
29887             tooltip: this.refreshText,
29888             overflowText: this.refreshText,
29889             iconCls: 'x-tbar-loading',
29890             handler: this.doRefresh,
29891             scope: this
29892         })];
29893
29894
29895         var userItems = this.items || this.buttons || [];
29896         if (this.prependButtons) {
29897             this.items = userItems.concat(pagingItems);
29898         }else{
29899             this.items = pagingItems.concat(userItems);
29900         }
29901         delete this.buttons;
29902         if(this.displayInfo){
29903             this.items.push('->');
29904             this.items.push(this.displayItem = new T.TextItem({}));
29905         }
29906         Ext.PagingToolbar.superclass.initComponent.call(this);
29907         this.addEvents(
29908             
29909             'change',
29910             
29911             'beforechange'
29912         );
29913         this.on('afterlayout', this.onFirstLayout, this, {single: true});
29914         this.cursor = 0;
29915         this.bindStore(this.store, true);
29916     },
29917
29918     
29919     onFirstLayout : function(){
29920         if(this.dsLoaded){
29921             this.onLoad.apply(this, this.dsLoaded);
29922         }
29923     },
29924
29925     
29926     updateInfo : function(){
29927         if(this.displayItem){
29928             var count = this.store.getCount();
29929             var msg = count == 0 ?
29930                 this.emptyMsg :
29931                 String.format(
29932                     this.displayMsg,
29933                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
29934                 );
29935             this.displayItem.setText(msg);
29936         }
29937     },
29938
29939     
29940     onLoad : function(store, r, o){
29941         if(!this.rendered){
29942             this.dsLoaded = [store, r, o];
29943             return;
29944         }
29945         var p = this.getParams();
29946         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
29947         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
29948
29949         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
29950         this.inputItem.setValue(ap);
29951         this.first.setDisabled(ap == 1);
29952         this.prev.setDisabled(ap == 1);
29953         this.next.setDisabled(ap == ps);
29954         this.last.setDisabled(ap == ps);
29955         this.refresh.enable();
29956         this.updateInfo();
29957         this.fireEvent('change', this, d);
29958     },
29959
29960     
29961     getPageData : function(){
29962         var total = this.store.getTotalCount();
29963         return {
29964             total : total,
29965             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
29966             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
29967         };
29968     },
29969
29970     
29971     changePage : function(page){
29972         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
29973     },
29974
29975     
29976     onLoadError : function(){
29977         if(!this.rendered){
29978             return;
29979         }
29980         this.refresh.enable();
29981     },
29982
29983     
29984     readPage : function(d){
29985         var v = this.inputItem.getValue(), pageNum;
29986         if (!v || isNaN(pageNum = parseInt(v, 10))) {
29987             this.inputItem.setValue(d.activePage);
29988             return false;
29989         }
29990         return pageNum;
29991     },
29992
29993     onPagingFocus : function(){
29994         this.inputItem.select();
29995     },
29996
29997     
29998     onPagingBlur : function(e){
29999         this.inputItem.setValue(this.getPageData().activePage);
30000     },
30001
30002     
30003     onPagingKeyDown : function(field, e){
30004         var k = e.getKey(), d = this.getPageData(), pageNum;
30005         if (k == e.RETURN) {
30006             e.stopEvent();
30007             pageNum = this.readPage(d);
30008             if(pageNum !== false){
30009                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
30010                 this.doLoad(pageNum * this.pageSize);
30011             }
30012         }else if (k == e.HOME || k == e.END){
30013             e.stopEvent();
30014             pageNum = k == e.HOME ? 1 : d.pages;
30015             field.setValue(pageNum);
30016         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
30017             e.stopEvent();
30018             if((pageNum = this.readPage(d))){
30019                 var increment = e.shiftKey ? 10 : 1;
30020                 if(k == e.DOWN || k == e.PAGEDOWN){
30021                     increment *= -1;
30022                 }
30023                 pageNum += increment;
30024                 if(pageNum >= 1 & pageNum <= d.pages){
30025                     field.setValue(pageNum);
30026                 }
30027             }
30028         }
30029     },
30030
30031     
30032     getParams : function(){
30033         
30034         return this.paramNames || this.store.paramNames;
30035     },
30036
30037     
30038     beforeLoad : function(){
30039         if(this.rendered && this.refresh){
30040             this.refresh.disable();
30041         }
30042     },
30043
30044     
30045     doLoad : function(start){
30046         var o = {}, pn = this.getParams();
30047         o[pn.start] = start;
30048         o[pn.limit] = this.pageSize;
30049         if(this.fireEvent('beforechange', this, o) !== false){
30050             this.store.load({params:o});
30051         }
30052     },
30053
30054     
30055     moveFirst : function(){
30056         this.doLoad(0);
30057     },
30058
30059     
30060     movePrevious : function(){
30061         this.doLoad(Math.max(0, this.cursor-this.pageSize));
30062     },
30063
30064     
30065     moveNext : function(){
30066         this.doLoad(this.cursor+this.pageSize);
30067     },
30068
30069     
30070     moveLast : function(){
30071         var total = this.store.getTotalCount(),
30072             extra = total % this.pageSize;
30073
30074         this.doLoad(extra ? (total - extra) : total - this.pageSize);
30075     },
30076
30077     
30078     doRefresh : function(){
30079         this.doLoad(this.cursor);
30080     },
30081
30082     
30083     bindStore : function(store, initial){
30084         var doLoad;
30085         if(!initial && this.store){
30086             if(store !== this.store && this.store.autoDestroy){
30087                 this.store.destroy();
30088             }else{
30089                 this.store.un('beforeload', this.beforeLoad, this);
30090                 this.store.un('load', this.onLoad, this);
30091                 this.store.un('exception', this.onLoadError, this);
30092             }
30093             if(!store){
30094                 this.store = null;
30095             }
30096         }
30097         if(store){
30098             store = Ext.StoreMgr.lookup(store);
30099             store.on({
30100                 scope: this,
30101                 beforeload: this.beforeLoad,
30102                 load: this.onLoad,
30103                 exception: this.onLoadError
30104             });
30105             doLoad = true;
30106         }
30107         this.store = store;
30108         if(doLoad){
30109             this.onLoad(store, null, {});
30110         }
30111     },
30112
30113     
30114     unbind : function(store){
30115         this.bindStore(null);
30116     },
30117
30118     
30119     bind : function(store){
30120         this.bindStore(store);
30121     },
30122
30123     
30124     onDestroy : function(){
30125         this.bindStore(null);
30126         Ext.PagingToolbar.superclass.onDestroy.call(this);
30127     }
30128 });
30129
30130 })();
30131 Ext.reg('paging', Ext.PagingToolbar);
30132 Ext.History = (function () {
30133     var iframe, hiddenField;
30134     var ready = false;
30135     var currentToken;
30136
30137     function getHash() {
30138         var href = top.location.href, i = href.indexOf("#");
30139         return i >= 0 ? href.substr(i + 1) : null;
30140     }
30141
30142     function doSave() {
30143         hiddenField.value = currentToken;
30144     }
30145
30146     function handleStateChange(token) {
30147         currentToken = token;
30148         Ext.History.fireEvent('change', token);
30149     }
30150
30151     function updateIFrame (token) {
30152         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
30153         try {
30154             var doc = iframe.contentWindow.document;
30155             doc.open();
30156             doc.write(html);
30157             doc.close();
30158             return true;
30159         } catch (e) {
30160             return false;
30161         }
30162     }
30163
30164     function checkIFrame() {
30165         if (!iframe.contentWindow || !iframe.contentWindow.document) {
30166             setTimeout(checkIFrame, 10);
30167             return;
30168         }
30169
30170         var doc = iframe.contentWindow.document;
30171         var elem = doc.getElementById("state");
30172         var token = elem ? elem.innerText : null;
30173
30174         var hash = getHash();
30175
30176         setInterval(function () {
30177
30178             doc = iframe.contentWindow.document;
30179             elem = doc.getElementById("state");
30180
30181             var newtoken = elem ? elem.innerText : null;
30182
30183             var newHash = getHash();
30184
30185             if (newtoken !== token) {
30186                 token = newtoken;
30187                 handleStateChange(token);
30188                 top.location.hash = token;
30189                 hash = token;
30190                 doSave();
30191             } else if (newHash !== hash) {
30192                 hash = newHash;
30193                 updateIFrame(newHash);
30194             }
30195
30196         }, 50);
30197
30198         ready = true;
30199
30200         Ext.History.fireEvent('ready', Ext.History);
30201     }
30202
30203     function startUp() {
30204         currentToken = hiddenField.value ? hiddenField.value : getHash();
30205
30206         if (Ext.isIE) {
30207             checkIFrame();
30208         } else {
30209             var hash = getHash();
30210             setInterval(function () {
30211                 var newHash = getHash();
30212                 if (newHash !== hash) {
30213                     hash = newHash;
30214                     handleStateChange(hash);
30215                     doSave();
30216                 }
30217             }, 50);
30218             ready = true;
30219             Ext.History.fireEvent('ready', Ext.History);
30220         }
30221     }
30222
30223     return {
30224         
30225         fieldId: 'x-history-field',
30226         
30227         iframeId: 'x-history-frame',
30228
30229         events:{},
30230
30231         
30232         init: function (onReady, scope) {
30233             if(ready) {
30234                 Ext.callback(onReady, scope, [this]);
30235                 return;
30236             }
30237             if(!Ext.isReady){
30238                 Ext.onReady(function(){
30239                     Ext.History.init(onReady, scope);
30240                 });
30241                 return;
30242             }
30243             hiddenField = Ext.getDom(Ext.History.fieldId);
30244             if (Ext.isIE) {
30245                 iframe = Ext.getDom(Ext.History.iframeId);
30246             }
30247             this.addEvents(
30248                 
30249                 'ready',
30250                 
30251                 'change'
30252             );
30253             if(onReady){
30254                 this.on('ready', onReady, scope, {single:true});
30255             }
30256             startUp();
30257         },
30258
30259         
30260         add: function (token, preventDup) {
30261             if(preventDup !== false){
30262                 if(this.getToken() == token){
30263                     return true;
30264                 }
30265             }
30266             if (Ext.isIE) {
30267                 return updateIFrame(token);
30268             } else {
30269                 top.location.hash = token;
30270                 return true;
30271             }
30272         },
30273
30274         
30275         back: function(){
30276             history.go(-1);
30277         },
30278
30279         
30280         forward: function(){
30281             history.go(1);
30282         },
30283
30284         
30285         getToken: function() {
30286             return ready ? currentToken : getHash();
30287         }
30288     };
30289 })();
30290 Ext.apply(Ext.History, new Ext.util.Observable());
30291 Ext.Tip = Ext.extend(Ext.Panel, {
30292     
30293     
30294     
30295     minWidth : 40,
30296     
30297     maxWidth : 300,
30298     
30299     shadow : "sides",
30300     
30301     defaultAlign : "tl-bl?",
30302     autoRender: true,
30303     quickShowInterval : 250,
30304
30305     
30306     frame:true,
30307     hidden:true,
30308     baseCls: 'x-tip',
30309     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
30310     autoHeight:true,
30311
30312     closeAction: 'hide',
30313
30314     
30315     initComponent : function(){
30316         Ext.Tip.superclass.initComponent.call(this);
30317         if(this.closable && !this.title){
30318             this.elements += ',header';
30319         }
30320     },
30321
30322     
30323     afterRender : function(){
30324         Ext.Tip.superclass.afterRender.call(this);
30325         if(this.closable){
30326             this.addTool({
30327                 id: 'close',
30328                 handler: this[this.closeAction],
30329                 scope: this
30330             });
30331         }
30332     },
30333
30334     
30335     showAt : function(xy){
30336         Ext.Tip.superclass.show.call(this);
30337         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
30338             this.doAutoWidth();
30339         }
30340         if(this.constrainPosition){
30341             xy = this.el.adjustForConstraints(xy);
30342         }
30343         this.setPagePosition(xy[0], xy[1]);
30344     },
30345
30346     
30347     doAutoWidth : function(adjust){
30348         adjust = adjust || 0;
30349         var bw = this.body.getTextWidth();
30350         if(this.title){
30351             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
30352         }
30353         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
30354         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
30355         
30356         
30357         if(Ext.isIE7 && !this.repainted){
30358             this.el.repaint();
30359             this.repainted = true;
30360         }
30361     },
30362
30363     
30364     showBy : function(el, pos){
30365         if(!this.rendered){
30366             this.render(Ext.getBody());
30367         }
30368         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
30369     },
30370
30371     initDraggable : function(){
30372         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
30373         this.header.addClass('x-tip-draggable');
30374     }
30375 });
30376
30377 Ext.reg('tip', Ext.Tip);
30378
30379
30380 Ext.Tip.DD = function(tip, config){
30381     Ext.apply(this, config);
30382     this.tip = tip;
30383     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
30384     this.setHandleElId(tip.header.id);
30385     this.scroll = false;
30386 };
30387
30388 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
30389     moveOnly:true,
30390     scroll:false,
30391     headerOffsets:[100, 25],
30392     startDrag : function(){
30393         this.tip.el.disableShadow();
30394     },
30395     endDrag : function(e){
30396         this.tip.el.enableShadow(true);
30397     }
30398 });
30399 Ext.ToolTip = Ext.extend(Ext.Tip, {
30400     
30401     
30402     
30403     
30404     showDelay : 500,
30405     
30406     hideDelay : 200,
30407     
30408     dismissDelay : 5000,
30409     
30410     
30411     trackMouse : false,
30412     
30413     anchorToTarget : true,
30414     
30415     anchorOffset : 0,
30416     
30417
30418     
30419     targetCounter : 0,
30420
30421     constrainPosition : false,
30422
30423     
30424     initComponent : function(){
30425         Ext.ToolTip.superclass.initComponent.call(this);
30426         this.lastActive = new Date();
30427         this.initTarget(this.target);
30428         this.origAnchor = this.anchor;
30429     },
30430
30431     
30432     onRender : function(ct, position){
30433         Ext.ToolTip.superclass.onRender.call(this, ct, position);
30434         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
30435         this.anchorEl = this.el.createChild({
30436             cls: 'x-tip-anchor ' + this.anchorCls
30437         });
30438     },
30439
30440     
30441     afterRender : function(){
30442         Ext.ToolTip.superclass.afterRender.call(this);
30443         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
30444     },
30445
30446     
30447     initTarget : function(target){
30448         var t;
30449         if((t = Ext.get(target))){
30450             if(this.target){
30451                 var tg = Ext.get(this.target);
30452                 this.mun(tg, 'mouseover', this.onTargetOver, this);
30453                 this.mun(tg, 'mouseout', this.onTargetOut, this);
30454                 this.mun(tg, 'mousemove', this.onMouseMove, this);
30455             }
30456             this.mon(t, {
30457                 mouseover: this.onTargetOver,
30458                 mouseout: this.onTargetOut,
30459                 mousemove: this.onMouseMove,
30460                 scope: this
30461             });
30462             this.target = t;
30463         }
30464         if(this.anchor){
30465             this.anchorTarget = this.target;
30466         }
30467     },
30468
30469     
30470     onMouseMove : function(e){
30471         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
30472         if (t) {
30473             this.targetXY = e.getXY();
30474             if (t === this.triggerElement) {
30475                 if(!this.hidden && this.trackMouse){
30476                     this.setPagePosition(this.getTargetXY());
30477                 }
30478             } else {
30479                 this.hide();
30480                 this.lastActive = new Date(0);
30481                 this.onTargetOver(e);
30482             }
30483         } else if (!this.closable && this.isVisible()) {
30484             this.hide();
30485         }
30486     },
30487
30488     
30489     getTargetXY : function(){
30490         if(this.delegate){
30491             this.anchorTarget = this.triggerElement;
30492         }
30493         if(this.anchor){
30494             this.targetCounter++;
30495             var offsets = this.getOffsets(),
30496                 xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
30497                 dw = Ext.lib.Dom.getViewWidth() - 5,
30498                 dh = Ext.lib.Dom.getViewHeight() - 5,
30499                 de = document.documentElement,
30500                 bd = document.body,
30501                 scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
30502                 scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
30503                 axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
30504                 sz = this.getSize();
30505                 
30506             this.anchorEl.removeClass(this.anchorCls);
30507
30508             if(this.targetCounter < 2){
30509                 if(axy[0] < scrollX){
30510                     if(this.anchorToTarget){
30511                         this.defaultAlign = 'l-r';
30512                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
30513                     }
30514                     this.anchor = 'left';
30515                     return this.getTargetXY();
30516                 }
30517                 if(axy[0]+sz.width > dw){
30518                     if(this.anchorToTarget){
30519                         this.defaultAlign = 'r-l';
30520                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
30521                     }
30522                     this.anchor = 'right';
30523                     return this.getTargetXY();
30524                 }
30525                 if(axy[1] < scrollY){
30526                     if(this.anchorToTarget){
30527                         this.defaultAlign = 't-b';
30528                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
30529                     }
30530                     this.anchor = 'top';
30531                     return this.getTargetXY();
30532                 }
30533                 if(axy[1]+sz.height > dh){
30534                     if(this.anchorToTarget){
30535                         this.defaultAlign = 'b-t';
30536                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
30537                     }
30538                     this.anchor = 'bottom';
30539                     return this.getTargetXY();
30540                 }
30541             }
30542
30543             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
30544             this.anchorEl.addClass(this.anchorCls);
30545             this.targetCounter = 0;
30546             return axy;
30547         }else{
30548             var mouseOffset = this.getMouseOffset();
30549             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
30550         }
30551     },
30552
30553     getMouseOffset : function(){
30554         var offset = this.anchor ? [0,0] : [15,18];
30555         if(this.mouseOffset){
30556             offset[0] += this.mouseOffset[0];
30557             offset[1] += this.mouseOffset[1];
30558         }
30559         return offset;
30560     },
30561
30562     
30563     getAnchorPosition : function(){
30564         if(this.anchor){
30565             this.tipAnchor = this.anchor.charAt(0);
30566         }else{
30567             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
30568             if(!m){
30569                throw 'AnchorTip.defaultAlign is invalid';
30570             }
30571             this.tipAnchor = m[1].charAt(0);
30572         }
30573
30574         switch(this.tipAnchor){
30575             case 't': return 'top';
30576             case 'b': return 'bottom';
30577             case 'r': return 'right';
30578         }
30579         return 'left';
30580     },
30581
30582     
30583     getAnchorAlign : function(){
30584         switch(this.anchor){
30585             case 'top'  : return 'tl-bl';
30586             case 'left' : return 'tl-tr';
30587             case 'right': return 'tr-tl';
30588             default     : return 'bl-tl';
30589         }
30590     },
30591
30592     
30593     getOffsets : function(){
30594         var offsets, 
30595             ap = this.getAnchorPosition().charAt(0);
30596         if(this.anchorToTarget && !this.trackMouse){
30597             switch(ap){
30598                 case 't':
30599                     offsets = [0, 9];
30600                     break;
30601                 case 'b':
30602                     offsets = [0, -13];
30603                     break;
30604                 case 'r':
30605                     offsets = [-13, 0];
30606                     break;
30607                 default:
30608                     offsets = [9, 0];
30609                     break;
30610             }
30611         }else{
30612             switch(ap){
30613                 case 't':
30614                     offsets = [-15-this.anchorOffset, 30];
30615                     break;
30616                 case 'b':
30617                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
30618                     break;
30619                 case 'r':
30620                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
30621                     break;
30622                 default:
30623                     offsets = [25, -13-this.anchorOffset];
30624                     break;
30625             }
30626         }
30627         var mouseOffset = this.getMouseOffset();
30628         offsets[0] += mouseOffset[0];
30629         offsets[1] += mouseOffset[1];
30630
30631         return offsets;
30632     },
30633
30634     
30635     onTargetOver : function(e){
30636         if(this.disabled || e.within(this.target.dom, true)){
30637             return;
30638         }
30639         var t = e.getTarget(this.delegate);
30640         if (t) {
30641             this.triggerElement = t;
30642             this.clearTimer('hide');
30643             this.targetXY = e.getXY();
30644             this.delayShow();
30645         }
30646     },
30647
30648     
30649     delayShow : function(){
30650         if(this.hidden && !this.showTimer){
30651             if(this.lastActive.getElapsed() < this.quickShowInterval){
30652                 this.show();
30653             }else{
30654                 this.showTimer = this.show.defer(this.showDelay, this);
30655             }
30656         }else if(!this.hidden && this.autoHide !== false){
30657             this.show();
30658         }
30659     },
30660
30661     
30662     onTargetOut : function(e){
30663         if(this.disabled || e.within(this.target.dom, true)){
30664             return;
30665         }
30666         this.clearTimer('show');
30667         if(this.autoHide !== false){
30668             this.delayHide();
30669         }
30670     },
30671
30672     
30673     delayHide : function(){
30674         if(!this.hidden && !this.hideTimer){
30675             this.hideTimer = this.hide.defer(this.hideDelay, this);
30676         }
30677     },
30678
30679     
30680     hide: function(){
30681         this.clearTimer('dismiss');
30682         this.lastActive = new Date();
30683         if(this.anchorEl){
30684             this.anchorEl.hide();
30685         }
30686         Ext.ToolTip.superclass.hide.call(this);
30687         delete this.triggerElement;
30688     },
30689
30690     
30691     show : function(){
30692         if(this.anchor){
30693             
30694             
30695             this.showAt([-1000,-1000]);
30696             this.origConstrainPosition = this.constrainPosition;
30697             this.constrainPosition = false;
30698             this.anchor = this.origAnchor;
30699         }
30700         this.showAt(this.getTargetXY());
30701
30702         if(this.anchor){
30703             this.syncAnchor();
30704             this.anchorEl.show();
30705             this.constrainPosition = this.origConstrainPosition;
30706         }else{
30707             this.anchorEl.hide();
30708         }
30709     },
30710
30711     
30712     showAt : function(xy){
30713         this.lastActive = new Date();
30714         this.clearTimers();
30715         Ext.ToolTip.superclass.showAt.call(this, xy);
30716         if(this.dismissDelay && this.autoHide !== false){
30717             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
30718         }
30719         if(this.anchor && !this.anchorEl.isVisible()){
30720             this.syncAnchor();
30721             this.anchorEl.show();
30722         }else{
30723             this.anchorEl.hide();
30724         }
30725     },
30726
30727     
30728     syncAnchor : function(){
30729         var anchorPos, targetPos, offset;
30730         switch(this.tipAnchor.charAt(0)){
30731             case 't':
30732                 anchorPos = 'b';
30733                 targetPos = 'tl';
30734                 offset = [20+this.anchorOffset, 2];
30735                 break;
30736             case 'r':
30737                 anchorPos = 'l';
30738                 targetPos = 'tr';
30739                 offset = [-2, 11+this.anchorOffset];
30740                 break;
30741             case 'b':
30742                 anchorPos = 't';
30743                 targetPos = 'bl';
30744                 offset = [20+this.anchorOffset, -2];
30745                 break;
30746             default:
30747                 anchorPos = 'r';
30748                 targetPos = 'tl';
30749                 offset = [2, 11+this.anchorOffset];
30750                 break;
30751         }
30752         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
30753     },
30754
30755     
30756     setPagePosition : function(x, y){
30757         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
30758         if(this.anchor){
30759             this.syncAnchor();
30760         }
30761     },
30762
30763     
30764     clearTimer : function(name){
30765         name = name + 'Timer';
30766         clearTimeout(this[name]);
30767         delete this[name];
30768     },
30769
30770     
30771     clearTimers : function(){
30772         this.clearTimer('show');
30773         this.clearTimer('dismiss');
30774         this.clearTimer('hide');
30775     },
30776
30777     
30778     onShow : function(){
30779         Ext.ToolTip.superclass.onShow.call(this);
30780         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
30781     },
30782
30783     
30784     onHide : function(){
30785         Ext.ToolTip.superclass.onHide.call(this);
30786         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
30787     },
30788
30789     
30790     onDocMouseDown : function(e){
30791         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
30792             this.disable();
30793             this.doEnable.defer(100, this);
30794         }
30795     },
30796     
30797     
30798     doEnable : function(){
30799         if(!this.isDestroyed){
30800             this.enable();
30801         }
30802     },
30803
30804     
30805     onDisable : function(){
30806         this.clearTimers();
30807         this.hide();
30808     },
30809
30810     
30811     adjustPosition : function(x, y){
30812         if(this.contstrainPosition){
30813             var ay = this.targetXY[1], h = this.getSize().height;
30814             if(y <= ay && (y+h) >= ay){
30815                 y = ay-h-5;
30816             }
30817         }
30818         return {x : x, y: y};
30819     },
30820     
30821     beforeDestroy : function(){
30822         this.clearTimers();
30823         Ext.destroy(this.anchorEl);
30824         delete this.anchorEl;
30825         delete this.target;
30826         delete this.anchorTarget;
30827         delete this.triggerElement;
30828         Ext.ToolTip.superclass.beforeDestroy.call(this);    
30829     },
30830
30831     
30832     onDestroy : function(){
30833         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
30834         Ext.ToolTip.superclass.onDestroy.call(this);
30835     }
30836 });
30837
30838 Ext.reg('tooltip', Ext.ToolTip);
30839 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
30840     
30841     
30842     interceptTitles : false,
30843
30844     
30845     tagConfig : {
30846         namespace : "ext",
30847         attribute : "qtip",
30848         width : "qwidth",
30849         target : "target",
30850         title : "qtitle",
30851         hide : "hide",
30852         cls : "qclass",
30853         align : "qalign",
30854         anchor : "anchor"
30855     },
30856
30857     
30858     initComponent : function(){
30859         this.target = this.target || Ext.getDoc();
30860         this.targets = this.targets || {};
30861         Ext.QuickTip.superclass.initComponent.call(this);
30862     },
30863
30864     
30865     register : function(config){
30866         var cs = Ext.isArray(config) ? config : arguments;
30867         for(var i = 0, len = cs.length; i < len; i++){
30868             var c = cs[i];
30869             var target = c.target;
30870             if(target){
30871                 if(Ext.isArray(target)){
30872                     for(var j = 0, jlen = target.length; j < jlen; j++){
30873                         this.targets[Ext.id(target[j])] = c;
30874                     }
30875                 } else{
30876                     this.targets[Ext.id(target)] = c;
30877                 }
30878             }
30879         }
30880     },
30881
30882     
30883     unregister : function(el){
30884         delete this.targets[Ext.id(el)];
30885     },
30886     
30887     
30888     cancelShow: function(el){
30889         var at = this.activeTarget;
30890         el = Ext.get(el).dom;
30891         if(this.isVisible()){
30892             if(at && at.el == el){
30893                 this.hide();
30894             }
30895         }else if(at && at.el == el){
30896             this.clearTimer('show');
30897         }
30898     },
30899     
30900     getTipCfg: function(e) {
30901         var t = e.getTarget(), 
30902             ttp, 
30903             cfg;
30904         if(this.interceptTitles && t.title && Ext.isString(t.title)){
30905             ttp = t.title;
30906             t.qtip = ttp;
30907             t.removeAttribute("title");
30908             e.preventDefault();
30909         }else{
30910             cfg = this.tagConfig;
30911             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
30912         }
30913         return ttp;
30914     },
30915
30916     
30917     onTargetOver : function(e){
30918         if(this.disabled){
30919             return;
30920         }
30921         this.targetXY = e.getXY();
30922         var t = e.getTarget();
30923         if(!t || t.nodeType !== 1 || t == document || t == document.body){
30924             return;
30925         }
30926         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
30927             this.clearTimer('hide');
30928             this.show();
30929             return;
30930         }
30931         if(t && this.targets[t.id]){
30932             this.activeTarget = this.targets[t.id];
30933             this.activeTarget.el = t;
30934             this.anchor = this.activeTarget.anchor;
30935             if(this.anchor){
30936                 this.anchorTarget = t;
30937             }
30938             this.delayShow();
30939             return;
30940         }
30941         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
30942         if(ttp = this.getTipCfg(e)){
30943             var autoHide = et.getAttribute(cfg.hide, ns);
30944             this.activeTarget = {
30945                 el: t,
30946                 text: ttp,
30947                 width: et.getAttribute(cfg.width, ns),
30948                 autoHide: autoHide != "user" && autoHide !== 'false',
30949                 title: et.getAttribute(cfg.title, ns),
30950                 cls: et.getAttribute(cfg.cls, ns),
30951                 align: et.getAttribute(cfg.align, ns)
30952                 
30953             };
30954             this.anchor = et.getAttribute(cfg.anchor, ns);
30955             if(this.anchor){
30956                 this.anchorTarget = t;
30957             }
30958             this.delayShow();
30959         }
30960     },
30961
30962     
30963     onTargetOut : function(e){
30964
30965         
30966         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
30967             return;
30968         }
30969
30970         this.clearTimer('show');
30971         if(this.autoHide !== false){
30972             this.delayHide();
30973         }
30974     },
30975
30976     
30977     showAt : function(xy){
30978         var t = this.activeTarget;
30979         if(t){
30980             if(!this.rendered){
30981                 this.render(Ext.getBody());
30982                 this.activeTarget = t;
30983             }
30984             if(t.width){
30985                 this.setWidth(t.width);
30986                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
30987                 this.measureWidth = false;
30988             } else{
30989                 this.measureWidth = true;
30990             }
30991             this.setTitle(t.title || '');
30992             this.body.update(t.text);
30993             this.autoHide = t.autoHide;
30994             this.dismissDelay = t.dismissDelay || this.dismissDelay;
30995             if(this.lastCls){
30996                 this.el.removeClass(this.lastCls);
30997                 delete this.lastCls;
30998             }
30999             if(t.cls){
31000                 this.el.addClass(t.cls);
31001                 this.lastCls = t.cls;
31002             }
31003             if(this.anchor){
31004                 this.constrainPosition = false;
31005             }else if(t.align){ 
31006                 xy = this.el.getAlignToXY(t.el, t.align);
31007                 this.constrainPosition = false;
31008             }else{
31009                 this.constrainPosition = true;
31010             }
31011         }
31012         Ext.QuickTip.superclass.showAt.call(this, xy);
31013     },
31014
31015     
31016     hide: function(){
31017         delete this.activeTarget;
31018         Ext.QuickTip.superclass.hide.call(this);
31019     }
31020 });
31021 Ext.reg('quicktip', Ext.QuickTip);
31022 Ext.QuickTips = function(){
31023     var tip, locks = [];
31024     return {
31025         
31026         init : function(autoRender){
31027             if(!tip){
31028                 if(!Ext.isReady){
31029                     Ext.onReady(function(){
31030                         Ext.QuickTips.init(autoRender);
31031                     });
31032                     return;
31033                 }
31034                 tip = new Ext.QuickTip({elements:'header,body'});
31035                 if(autoRender !== false){
31036                     tip.render(Ext.getBody());
31037                 }
31038             }
31039         },
31040
31041         
31042         enable : function(){
31043             if(tip){
31044                 locks.pop();
31045                 if(locks.length < 1){
31046                     tip.enable();
31047                 }
31048             }
31049         },
31050
31051         
31052         disable : function(){
31053             if(tip){
31054                 tip.disable();
31055             }
31056             locks.push(1);
31057         },
31058
31059         
31060         isEnabled : function(){
31061             return tip !== undefined && !tip.disabled;
31062         },
31063
31064         
31065         getQuickTip : function(){
31066             return tip;
31067         },
31068
31069         
31070         register : function(){
31071             tip.register.apply(tip, arguments);
31072         },
31073
31074         
31075         unregister : function(){
31076             tip.unregister.apply(tip, arguments);
31077         },
31078
31079         
31080         tips :function(){
31081             tip.register.apply(tip, arguments);
31082         }
31083     }
31084 }();
31085 Ext.slider.Tip = Ext.extend(Ext.Tip, {
31086     minWidth: 10,
31087     offsets : [0, -10],
31088     
31089     init: function(slider) {
31090         slider.on({
31091             scope    : this,
31092             dragstart: this.onSlide,
31093             drag     : this.onSlide,
31094             dragend  : this.hide,
31095             destroy  : this.destroy
31096         });
31097     },
31098     
31099     
31100     onSlide : function(slider, e, thumb) {
31101         this.show();
31102         this.body.update(this.getText(thumb));
31103         this.doAutoWidth();
31104         this.el.alignTo(thumb.el, 'b-t?', this.offsets);
31105     },
31106
31107     
31108     getText : function(thumb) {
31109         return String(thumb.value);
31110     }
31111 });
31112
31113
31114 Ext.ux.SliderTip = Ext.slider.Tip;
31115 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
31116     rootVisible : true,
31117     animate : Ext.enableFx,
31118     lines : true,
31119     enableDD : false,
31120     hlDrop : Ext.enableFx,
31121     pathSeparator : '/',
31122
31123     
31124     bubbleEvents : [],
31125
31126     initComponent : function(){
31127         Ext.tree.TreePanel.superclass.initComponent.call(this);
31128
31129         if(!this.eventModel){
31130             this.eventModel = new Ext.tree.TreeEventModel(this);
31131         }
31132
31133         
31134         var l = this.loader;
31135         if(!l){
31136             l = new Ext.tree.TreeLoader({
31137                 dataUrl: this.dataUrl,
31138                 requestMethod: this.requestMethod
31139             });
31140         }else if(Ext.isObject(l) && !l.load){
31141             l = new Ext.tree.TreeLoader(l);
31142         }
31143         this.loader = l;
31144
31145         this.nodeHash = {};
31146
31147         
31148         if(this.root){
31149             var r = this.root;
31150             delete this.root;
31151             this.setRootNode(r);
31152         }
31153
31154
31155         this.addEvents(
31156
31157             
31158            'append',
31159            
31160            'remove',
31161            
31162            'movenode',
31163            
31164            'insert',
31165            
31166            'beforeappend',
31167            
31168            'beforeremove',
31169            
31170            'beforemovenode',
31171            
31172             'beforeinsert',
31173
31174             
31175             'beforeload',
31176             
31177             'load',
31178             
31179             'textchange',
31180             
31181             'beforeexpandnode',
31182             
31183             'beforecollapsenode',
31184             
31185             'expandnode',
31186             
31187             'disabledchange',
31188             
31189             'collapsenode',
31190             
31191             'beforeclick',
31192             
31193             'click',
31194             
31195             'containerclick',
31196             
31197             'checkchange',
31198             
31199             'beforedblclick',
31200             
31201             'dblclick',
31202             
31203             'containerdblclick',
31204             
31205             'contextmenu',
31206             
31207             'containercontextmenu',
31208             
31209             'beforechildrenrendered',
31210            
31211             'startdrag',
31212             
31213             'enddrag',
31214             
31215             'dragdrop',
31216             
31217             'beforenodedrop',
31218             
31219             'nodedrop',
31220              
31221             'nodedragover'
31222         );
31223         if(this.singleExpand){
31224             this.on('beforeexpandnode', this.restrictExpand, this);
31225         }
31226     },
31227
31228     
31229     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
31230         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
31231             ename = ename+'node';
31232         }
31233         
31234         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
31235     },
31236
31237
31238     
31239     getRootNode : function(){
31240         return this.root;
31241     },
31242
31243     
31244     setRootNode : function(node){
31245         this.destroyRoot();
31246         if(!node.render){ 
31247             node = this.loader.createNode(node);
31248         }
31249         this.root = node;
31250         node.ownerTree = this;
31251         node.isRoot = true;
31252         this.registerNode(node);
31253         if(!this.rootVisible){
31254             var uiP = node.attributes.uiProvider;
31255             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
31256         }
31257         if(this.innerCt){
31258             this.clearInnerCt();
31259             this.renderRoot();
31260         }
31261         return node;
31262     },
31263     
31264     clearInnerCt : function(){
31265         this.innerCt.update('');    
31266     },
31267     
31268     
31269     renderRoot : function(){
31270         this.root.render();
31271         if(!this.rootVisible){
31272             this.root.renderChildren();
31273         }
31274     },
31275
31276     
31277     getNodeById : function(id){
31278         return this.nodeHash[id];
31279     },
31280
31281     
31282     registerNode : function(node){
31283         this.nodeHash[node.id] = node;
31284     },
31285
31286     
31287     unregisterNode : function(node){
31288         delete this.nodeHash[node.id];
31289     },
31290
31291     
31292     toString : function(){
31293         return '[Tree'+(this.id?' '+this.id:'')+']';
31294     },
31295
31296     
31297     restrictExpand : function(node){
31298         var p = node.parentNode;
31299         if(p){
31300             if(p.expandedChild && p.expandedChild.parentNode == p){
31301                 p.expandedChild.collapse();
31302             }
31303             p.expandedChild = node;
31304         }
31305     },
31306
31307     
31308     getChecked : function(a, startNode){
31309         startNode = startNode || this.root;
31310         var r = [];
31311         var f = function(){
31312             if(this.attributes.checked){
31313                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
31314             }
31315         };
31316         startNode.cascade(f);
31317         return r;
31318     },
31319
31320     
31321     getLoader : function(){
31322         return this.loader;
31323     },
31324
31325     
31326     expandAll : function(){
31327         this.root.expand(true);
31328     },
31329
31330     
31331     collapseAll : function(){
31332         this.root.collapse(true);
31333     },
31334
31335     
31336     getSelectionModel : function(){
31337         if(!this.selModel){
31338             this.selModel = new Ext.tree.DefaultSelectionModel();
31339         }
31340         return this.selModel;
31341     },
31342
31343     
31344     expandPath : function(path, attr, callback){
31345         if(Ext.isEmpty(path)){
31346             if(callback){
31347                 callback(false, undefined);
31348             }
31349             return;
31350         }
31351         attr = attr || 'id';
31352         var keys = path.split(this.pathSeparator);
31353         var curNode = this.root;
31354         if(curNode.attributes[attr] != keys[1]){ 
31355             if(callback){
31356                 callback(false, null);
31357             }
31358             return;
31359         }
31360         var index = 1;
31361         var f = function(){
31362             if(++index == keys.length){
31363                 if(callback){
31364                     callback(true, curNode);
31365                 }
31366                 return;
31367             }
31368             var c = curNode.findChild(attr, keys[index]);
31369             if(!c){
31370                 if(callback){
31371                     callback(false, curNode);
31372                 }
31373                 return;
31374             }
31375             curNode = c;
31376             c.expand(false, false, f);
31377         };
31378         curNode.expand(false, false, f);
31379     },
31380
31381     
31382     selectPath : function(path, attr, callback){
31383         if(Ext.isEmpty(path)){
31384             if(callback){
31385                 callback(false, undefined);
31386             }
31387             return;
31388         }
31389         attr = attr || 'id';
31390         var keys = path.split(this.pathSeparator),
31391             v = keys.pop();
31392         if(keys.length > 1){
31393             var f = function(success, node){
31394                 if(success && node){
31395                     var n = node.findChild(attr, v);
31396                     if(n){
31397                         n.select();
31398                         if(callback){
31399                             callback(true, n);
31400                         }
31401                     }else if(callback){
31402                         callback(false, n);
31403                     }
31404                 }else{
31405                     if(callback){
31406                         callback(false, n);
31407                     }
31408                 }
31409             };
31410             this.expandPath(keys.join(this.pathSeparator), attr, f);
31411         }else{
31412             this.root.select();
31413             if(callback){
31414                 callback(true, this.root);
31415             }
31416         }
31417     },
31418
31419     
31420     getTreeEl : function(){
31421         return this.body;
31422     },
31423
31424     
31425     onRender : function(ct, position){
31426         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
31427         this.el.addClass('x-tree');
31428         this.innerCt = this.body.createChild({tag:'ul',
31429                cls:'x-tree-root-ct ' +
31430                (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
31431     },
31432
31433     
31434     initEvents : function(){
31435         Ext.tree.TreePanel.superclass.initEvents.call(this);
31436
31437         if(this.containerScroll){
31438             Ext.dd.ScrollManager.register(this.body);
31439         }
31440         if((this.enableDD || this.enableDrop) && !this.dropZone){
31441            
31442              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
31443                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
31444            });
31445         }
31446         if((this.enableDD || this.enableDrag) && !this.dragZone){
31447            
31448             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
31449                ddGroup: this.ddGroup || 'TreeDD',
31450                scroll: this.ddScroll
31451            });
31452         }
31453         this.getSelectionModel().init(this);
31454     },
31455
31456     
31457     afterRender : function(){
31458         Ext.tree.TreePanel.superclass.afterRender.call(this);
31459         this.renderRoot();
31460     },
31461
31462     beforeDestroy : function(){
31463         if(this.rendered){
31464             Ext.dd.ScrollManager.unregister(this.body);
31465             Ext.destroy(this.dropZone, this.dragZone);
31466         }
31467         this.destroyRoot();
31468         Ext.destroy(this.loader);
31469         this.nodeHash = this.root = this.loader = null;
31470         Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
31471     },
31472     
31473     
31474     destroyRoot : function(){
31475         if(this.root && this.root.destroy){
31476             this.root.destroy(true);
31477         }
31478     }
31479
31480     
31481     
31482     
31483     
31484     
31485     
31486     
31487     
31488     
31489     
31490     
31491     
31492     
31493     
31494     
31495     
31496     
31497     
31498     
31499     
31500     
31501     
31502     
31503     
31504     
31505     
31506     
31507     
31508     
31509     
31510     
31511
31512
31513
31514     
31515     
31516     
31517     
31518     
31519     
31520     
31521     
31522     
31523     
31524     
31525     
31526     
31527     
31528     
31529     
31530 });
31531
31532 Ext.tree.TreePanel.nodeTypes = {};
31533
31534 Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
31535     this.tree = tree;
31536     this.tree.on('render', this.initEvents, this);
31537 };
31538
31539 Ext.tree.TreeEventModel.prototype = {
31540     initEvents : function(){
31541         var t = this.tree;
31542
31543         if(t.trackMouseOver !== false){
31544             t.mon(t.innerCt, {
31545                 scope: this,
31546                 mouseover: this.delegateOver,
31547                 mouseout: this.delegateOut
31548             });
31549         }
31550         t.mon(t.getTreeEl(), {
31551             scope: this,
31552             click: this.delegateClick,
31553             dblclick: this.delegateDblClick,
31554             contextmenu: this.delegateContextMenu
31555         });
31556     },
31557
31558     getNode : function(e){
31559         var t;
31560         if(t = e.getTarget('.x-tree-node-el', 10)){
31561             var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
31562             if(id){
31563                 return this.tree.getNodeById(id);
31564             }
31565         }
31566         return null;
31567     },
31568
31569     getNodeTarget : function(e){
31570         var t = e.getTarget('.x-tree-node-icon', 1);
31571         if(!t){
31572             t = e.getTarget('.x-tree-node-el', 6);
31573         }
31574         return t;
31575     },
31576
31577     delegateOut : function(e, t){
31578         if(!this.beforeEvent(e)){
31579             return;
31580         }
31581         if(e.getTarget('.x-tree-ec-icon', 1)){
31582             var n = this.getNode(e);
31583             this.onIconOut(e, n);
31584             if(n == this.lastEcOver){
31585                 delete this.lastEcOver;
31586             }
31587         }
31588         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
31589             this.onNodeOut(e, this.getNode(e));
31590         }
31591     },
31592
31593     delegateOver : function(e, t){
31594         if(!this.beforeEvent(e)){
31595             return;
31596         }
31597         if(Ext.isGecko && !this.trackingDoc){ 
31598             Ext.getBody().on('mouseover', this.trackExit, this);
31599             this.trackingDoc = true;
31600         }
31601         if(this.lastEcOver){ 
31602             this.onIconOut(e, this.lastEcOver);
31603             delete this.lastEcOver;
31604         }
31605         if(e.getTarget('.x-tree-ec-icon', 1)){
31606             this.lastEcOver = this.getNode(e);
31607             this.onIconOver(e, this.lastEcOver);
31608         }
31609         if(t = this.getNodeTarget(e)){
31610             this.onNodeOver(e, this.getNode(e));
31611         }
31612     },
31613
31614     trackExit : function(e){
31615         if(this.lastOverNode){
31616             if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
31617                 this.onNodeOut(e, this.lastOverNode);
31618             }
31619             delete this.lastOverNode;
31620             Ext.getBody().un('mouseover', this.trackExit, this);
31621             this.trackingDoc = false;
31622         }
31623
31624     },
31625
31626     delegateClick : function(e, t){
31627         if(this.beforeEvent(e)){
31628             if(e.getTarget('input[type=checkbox]', 1)){
31629                 this.onCheckboxClick(e, this.getNode(e));
31630             }else if(e.getTarget('.x-tree-ec-icon', 1)){
31631                 this.onIconClick(e, this.getNode(e));
31632             }else if(this.getNodeTarget(e)){
31633                 this.onNodeClick(e, this.getNode(e));
31634             }
31635         }else{
31636             this.checkContainerEvent(e, 'click');
31637         }
31638     },
31639
31640     delegateDblClick : function(e, t){
31641         if(this.beforeEvent(e)){
31642             if(this.getNodeTarget(e)){
31643                 this.onNodeDblClick(e, this.getNode(e));
31644             }
31645         }else{
31646             this.checkContainerEvent(e, 'dblclick');
31647         }
31648     },
31649
31650     delegateContextMenu : function(e, t){
31651         if(this.beforeEvent(e)){
31652             if(this.getNodeTarget(e)){
31653                 this.onNodeContextMenu(e, this.getNode(e));
31654             }
31655         }else{
31656             this.checkContainerEvent(e, 'contextmenu');
31657         }
31658     },
31659     
31660     checkContainerEvent: function(e, type){
31661         if(this.disabled){
31662             e.stopEvent();
31663             return false;
31664         }
31665         this.onContainerEvent(e, type);    
31666     },
31667
31668     onContainerEvent: function(e, type){
31669         this.tree.fireEvent('container' + type, this.tree, e);
31670     },
31671
31672     onNodeClick : function(e, node){
31673         node.ui.onClick(e);
31674     },
31675
31676     onNodeOver : function(e, node){
31677         this.lastOverNode = node;
31678         node.ui.onOver(e);
31679     },
31680
31681     onNodeOut : function(e, node){
31682         node.ui.onOut(e);
31683     },
31684
31685     onIconOver : function(e, node){
31686         node.ui.addClass('x-tree-ec-over');
31687     },
31688
31689     onIconOut : function(e, node){
31690         node.ui.removeClass('x-tree-ec-over');
31691     },
31692
31693     onIconClick : function(e, node){
31694         node.ui.ecClick(e);
31695     },
31696
31697     onCheckboxClick : function(e, node){
31698         node.ui.onCheckChange(e);
31699     },
31700
31701     onNodeDblClick : function(e, node){
31702         node.ui.onDblClick(e);
31703     },
31704
31705     onNodeContextMenu : function(e, node){
31706         node.ui.onContextMenu(e);
31707     },
31708
31709     beforeEvent : function(e){
31710         var node = this.getNode(e);
31711         if(this.disabled || !node || !node.ui){
31712             e.stopEvent();
31713             return false;
31714         }
31715         return true;
31716     },
31717
31718     disable: function(){
31719         this.disabled = true;
31720     },
31721
31722     enable: function(){
31723         this.disabled = false;
31724     }
31725 };
31726 Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
31727     
31728     constructor : function(config){
31729         this.selNode = null;
31730    
31731         this.addEvents(
31732             
31733             'selectionchange',
31734
31735             
31736             'beforeselect'
31737         );
31738
31739         Ext.apply(this, config);
31740         Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
31741     },
31742     
31743     init : function(tree){
31744         this.tree = tree;
31745         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
31746         tree.on('click', this.onNodeClick, this);
31747     },
31748     
31749     onNodeClick : function(node, e){
31750         this.select(node);
31751     },
31752     
31753     
31754     select : function(node,  selectNextNode){
31755         
31756         if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
31757             return selectNextNode.call(this, node);
31758         }
31759         var last = this.selNode;
31760         if(node == last){
31761             node.ui.onSelectedChange(true);
31762         }else if(this.fireEvent('beforeselect', this, node, last) !== false){
31763             if(last && last.ui){
31764                 last.ui.onSelectedChange(false);
31765             }
31766             this.selNode = node;
31767             node.ui.onSelectedChange(true);
31768             this.fireEvent('selectionchange', this, node, last);
31769         }
31770         return node;
31771     },
31772     
31773     
31774     unselect : function(node, silent){
31775         if(this.selNode == node){
31776             this.clearSelections(silent);
31777         }    
31778     },
31779     
31780     
31781     clearSelections : function(silent){
31782         var n = this.selNode;
31783         if(n){
31784             n.ui.onSelectedChange(false);
31785             this.selNode = null;
31786             if(silent !== true){
31787                 this.fireEvent('selectionchange', this, null);
31788             }
31789         }
31790         return n;
31791     },
31792     
31793     
31794     getSelectedNode : function(){
31795         return this.selNode;    
31796     },
31797     
31798     
31799     isSelected : function(node){
31800         return this.selNode == node;  
31801     },
31802
31803     
31804     selectPrevious : function( s){
31805         if(!(s = s || this.selNode || this.lastSelNode)){
31806             return null;
31807         }
31808         
31809         var ps = s.previousSibling;
31810         if(ps){
31811             if(!ps.isExpanded() || ps.childNodes.length < 1){
31812                 return this.select(ps, this.selectPrevious);
31813             } else{
31814                 var lc = ps.lastChild;
31815                 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
31816                     lc = lc.lastChild;
31817                 }
31818                 return this.select(lc, this.selectPrevious);
31819             }
31820         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
31821             return this.select(s.parentNode, this.selectPrevious);
31822         }
31823         return null;
31824     },
31825
31826     
31827     selectNext : function( s){
31828         if(!(s = s || this.selNode || this.lastSelNode)){
31829             return null;
31830         }
31831         
31832         if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
31833              return this.select(s.firstChild, this.selectNext);
31834          }else if(s.nextSibling){
31835              return this.select(s.nextSibling, this.selectNext);
31836          }else if(s.parentNode){
31837             var newS = null;
31838             s.parentNode.bubble(function(){
31839                 if(this.nextSibling){
31840                     newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
31841                     return false;
31842                 }
31843             });
31844             return newS;
31845          }
31846         return null;
31847     },
31848
31849     onKeyDown : function(e){
31850         var s = this.selNode || this.lastSelNode;
31851         
31852         var sm = this;
31853         if(!s){
31854             return;
31855         }
31856         var k = e.getKey();
31857         switch(k){
31858              case e.DOWN:
31859                  e.stopEvent();
31860                  this.selectNext();
31861              break;
31862              case e.UP:
31863                  e.stopEvent();
31864                  this.selectPrevious();
31865              break;
31866              case e.RIGHT:
31867                  e.preventDefault();
31868                  if(s.hasChildNodes()){
31869                      if(!s.isExpanded()){
31870                          s.expand();
31871                      }else if(s.firstChild){
31872                          this.select(s.firstChild, e);
31873                      }
31874                  }
31875              break;
31876              case e.LEFT:
31877                  e.preventDefault();
31878                  if(s.hasChildNodes() && s.isExpanded()){
31879                      s.collapse();
31880                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
31881                      this.select(s.parentNode, e);
31882                  }
31883              break;
31884         };
31885     }
31886 });
31887
31888
31889 Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
31890     
31891     constructor : function(config){
31892         this.selNodes = [];
31893         this.selMap = {};
31894         this.addEvents(
31895             
31896             'selectionchange'
31897         );
31898         Ext.apply(this, config);
31899         Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
31900     },
31901     
31902     init : function(tree){
31903         this.tree = tree;
31904         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
31905         tree.on('click', this.onNodeClick, this);
31906     },
31907     
31908     onNodeClick : function(node, e){
31909         if(e.ctrlKey && this.isSelected(node)){
31910             this.unselect(node);
31911         }else{
31912             this.select(node, e, e.ctrlKey);
31913         }
31914     },
31915     
31916     
31917     select : function(node, e, keepExisting){
31918         if(keepExisting !== true){
31919             this.clearSelections(true);
31920         }
31921         if(this.isSelected(node)){
31922             this.lastSelNode = node;
31923             return node;
31924         }
31925         this.selNodes.push(node);
31926         this.selMap[node.id] = node;
31927         this.lastSelNode = node;
31928         node.ui.onSelectedChange(true);
31929         this.fireEvent('selectionchange', this, this.selNodes);
31930         return node;
31931     },
31932     
31933     
31934     unselect : function(node){
31935         if(this.selMap[node.id]){
31936             node.ui.onSelectedChange(false);
31937             var sn = this.selNodes;
31938             var index = sn.indexOf(node);
31939             if(index != -1){
31940                 this.selNodes.splice(index, 1);
31941             }
31942             delete this.selMap[node.id];
31943             this.fireEvent('selectionchange', this, this.selNodes);
31944         }
31945     },
31946     
31947     
31948     clearSelections : function(suppressEvent){
31949         var sn = this.selNodes;
31950         if(sn.length > 0){
31951             for(var i = 0, len = sn.length; i < len; i++){
31952                 sn[i].ui.onSelectedChange(false);
31953             }
31954             this.selNodes = [];
31955             this.selMap = {};
31956             if(suppressEvent !== true){
31957                 this.fireEvent('selectionchange', this, this.selNodes);
31958             }
31959         }
31960     },
31961     
31962     
31963     isSelected : function(node){
31964         return this.selMap[node.id] ? true : false;  
31965     },
31966     
31967     
31968     getSelectedNodes : function(){
31969         return this.selNodes.concat([]);
31970     },
31971
31972     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
31973
31974     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
31975
31976     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
31977 });
31978 Ext.data.Tree = function(root){
31979    this.nodeHash = {};
31980    
31981    this.root = null;
31982    if(root){
31983        this.setRootNode(root);
31984    }
31985    this.addEvents(
31986        
31987        "append",
31988        
31989        "remove",
31990        
31991        "move",
31992        
31993        "insert",
31994        
31995        "beforeappend",
31996        
31997        "beforeremove",
31998        
31999        "beforemove",
32000        
32001        "beforeinsert"
32002    );
32003
32004     Ext.data.Tree.superclass.constructor.call(this);
32005 };
32006
32007 Ext.extend(Ext.data.Tree, Ext.util.Observable, {
32008     
32009     pathSeparator: "/",
32010
32011     
32012     proxyNodeEvent : function(){
32013         return this.fireEvent.apply(this, arguments);
32014     },
32015
32016     
32017     getRootNode : function(){
32018         return this.root;
32019     },
32020
32021     
32022     setRootNode : function(node){
32023         this.root = node;
32024         node.ownerTree = this;
32025         node.isRoot = true;
32026         this.registerNode(node);
32027         return node;
32028     },
32029
32030     
32031     getNodeById : function(id){
32032         return this.nodeHash[id];
32033     },
32034
32035     
32036     registerNode : function(node){
32037         this.nodeHash[node.id] = node;
32038     },
32039
32040     
32041     unregisterNode : function(node){
32042         delete this.nodeHash[node.id];
32043     },
32044
32045     toString : function(){
32046         return "[Tree"+(this.id?" "+this.id:"")+"]";
32047     }
32048 });
32049
32050
32051 Ext.data.Node = function(attributes){
32052     
32053     this.attributes = attributes || {};
32054     this.leaf = this.attributes.leaf;
32055     
32056     this.id = this.attributes.id;
32057     if(!this.id){
32058         this.id = Ext.id(null, "xnode-");
32059         this.attributes.id = this.id;
32060     }
32061     
32062     this.childNodes = [];
32063     if(!this.childNodes.indexOf){ 
32064         this.childNodes.indexOf = function(o){
32065             for(var i = 0, len = this.length; i < len; i++){
32066                 if(this[i] == o){
32067                     return i;
32068                 }
32069             }
32070             return -1;
32071         };
32072     }
32073     
32074     this.parentNode = null;
32075     
32076     this.firstChild = null;
32077     
32078     this.lastChild = null;
32079     
32080     this.previousSibling = null;
32081     
32082     this.nextSibling = null;
32083
32084     this.addEvents({
32085        
32086        "append" : true,
32087        
32088        "remove" : true,
32089        
32090        "move" : true,
32091        
32092        "insert" : true,
32093        
32094        "beforeappend" : true,
32095        
32096        "beforeremove" : true,
32097        
32098        "beforemove" : true,
32099        
32100        "beforeinsert" : true
32101    });
32102     this.listeners = this.attributes.listeners;
32103     Ext.data.Node.superclass.constructor.call(this);
32104 };
32105
32106 Ext.extend(Ext.data.Node, Ext.util.Observable, {
32107     
32108     fireEvent : function(evtName){
32109         
32110         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
32111             return false;
32112         }
32113         
32114         var ot = this.getOwnerTree();
32115         if(ot){
32116             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
32117                 return false;
32118             }
32119         }
32120         return true;
32121     },
32122
32123     
32124     isLeaf : function(){
32125         return this.leaf === true;
32126     },
32127
32128     
32129     setFirstChild : function(node){
32130         this.firstChild = node;
32131     },
32132
32133     
32134     setLastChild : function(node){
32135         this.lastChild = node;
32136     },
32137
32138
32139     
32140     isLast : function(){
32141        return (!this.parentNode ? true : this.parentNode.lastChild == this);
32142     },
32143
32144     
32145     isFirst : function(){
32146        return (!this.parentNode ? true : this.parentNode.firstChild == this);
32147     },
32148
32149     
32150     hasChildNodes : function(){
32151         return !this.isLeaf() && this.childNodes.length > 0;
32152     },
32153
32154     
32155     isExpandable : function(){
32156         return this.attributes.expandable || this.hasChildNodes();
32157     },
32158
32159     
32160     appendChild : function(node){
32161         var multi = false;
32162         if(Ext.isArray(node)){
32163             multi = node;
32164         }else if(arguments.length > 1){
32165             multi = arguments;
32166         }
32167         
32168         if(multi){
32169             for(var i = 0, len = multi.length; i < len; i++) {
32170                 this.appendChild(multi[i]);
32171             }
32172         }else{
32173             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
32174                 return false;
32175             }
32176             var index = this.childNodes.length;
32177             var oldParent = node.parentNode;
32178             
32179             if(oldParent){
32180                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
32181                     return false;
32182                 }
32183                 oldParent.removeChild(node);
32184             }
32185             index = this.childNodes.length;
32186             if(index === 0){
32187                 this.setFirstChild(node);
32188             }
32189             this.childNodes.push(node);
32190             node.parentNode = this;
32191             var ps = this.childNodes[index-1];
32192             if(ps){
32193                 node.previousSibling = ps;
32194                 ps.nextSibling = node;
32195             }else{
32196                 node.previousSibling = null;
32197             }
32198             node.nextSibling = null;
32199             this.setLastChild(node);
32200             node.setOwnerTree(this.getOwnerTree());
32201             this.fireEvent("append", this.ownerTree, this, node, index);
32202             if(oldParent){
32203                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
32204             }
32205             return node;
32206         }
32207     },
32208
32209     
32210     removeChild : function(node, destroy){
32211         var index = this.childNodes.indexOf(node);
32212         if(index == -1){
32213             return false;
32214         }
32215         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
32216             return false;
32217         }
32218
32219         
32220         this.childNodes.splice(index, 1);
32221
32222         
32223         if(node.previousSibling){
32224             node.previousSibling.nextSibling = node.nextSibling;
32225         }
32226         if(node.nextSibling){
32227             node.nextSibling.previousSibling = node.previousSibling;
32228         }
32229
32230         
32231         if(this.firstChild == node){
32232             this.setFirstChild(node.nextSibling);
32233         }
32234         if(this.lastChild == node){
32235             this.setLastChild(node.previousSibling);
32236         }
32237
32238         this.fireEvent("remove", this.ownerTree, this, node);
32239         if(destroy){
32240             node.destroy(true);
32241         }else{
32242             node.clear();
32243         }
32244         return node;
32245     },
32246
32247     
32248     clear : function(destroy){
32249         
32250         this.setOwnerTree(null, destroy);
32251         this.parentNode = this.previousSibling = this.nextSibling = null;
32252         if(destroy){
32253             this.firstChild = this.lastChild = null;
32254         }
32255     },
32256
32257     
32258     destroy : function( silent){
32259         
32260         if(silent === true){
32261             this.purgeListeners();
32262             this.clear(true);
32263             Ext.each(this.childNodes, function(n){
32264                 n.destroy(true);
32265             });
32266             this.childNodes = null;
32267         }else{
32268             this.remove(true);
32269         }
32270     },
32271
32272     
32273     insertBefore : function(node, refNode){
32274         if(!refNode){ 
32275             return this.appendChild(node);
32276         }
32277         
32278         if(node == refNode){
32279             return false;
32280         }
32281
32282         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
32283             return false;
32284         }
32285         var index = this.childNodes.indexOf(refNode);
32286         var oldParent = node.parentNode;
32287         var refIndex = index;
32288
32289         
32290         if(oldParent == this && this.childNodes.indexOf(node) < index){
32291             refIndex--;
32292         }
32293
32294         
32295         if(oldParent){
32296             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
32297                 return false;
32298             }
32299             oldParent.removeChild(node);
32300         }
32301         if(refIndex === 0){
32302             this.setFirstChild(node);
32303         }
32304         this.childNodes.splice(refIndex, 0, node);
32305         node.parentNode = this;
32306         var ps = this.childNodes[refIndex-1];
32307         if(ps){
32308             node.previousSibling = ps;
32309             ps.nextSibling = node;
32310         }else{
32311             node.previousSibling = null;
32312         }
32313         node.nextSibling = refNode;
32314         refNode.previousSibling = node;
32315         node.setOwnerTree(this.getOwnerTree());
32316         this.fireEvent("insert", this.ownerTree, this, node, refNode);
32317         if(oldParent){
32318             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
32319         }
32320         return node;
32321     },
32322
32323     
32324     remove : function(destroy){
32325         if (this.parentNode) {
32326             this.parentNode.removeChild(this, destroy);
32327         }
32328         return this;
32329     },
32330
32331     
32332     removeAll : function(destroy){
32333         var cn = this.childNodes,
32334             n;
32335         while((n = cn[0])){
32336             this.removeChild(n, destroy);
32337         }
32338         return this;
32339     },
32340
32341     
32342     item : function(index){
32343         return this.childNodes[index];
32344     },
32345
32346     
32347     replaceChild : function(newChild, oldChild){
32348         var s = oldChild ? oldChild.nextSibling : null;
32349         this.removeChild(oldChild);
32350         this.insertBefore(newChild, s);
32351         return oldChild;
32352     },
32353
32354     
32355     indexOf : function(child){
32356         return this.childNodes.indexOf(child);
32357     },
32358
32359     
32360     getOwnerTree : function(){
32361         
32362         if(!this.ownerTree){
32363             var p = this;
32364             while(p){
32365                 if(p.ownerTree){
32366                     this.ownerTree = p.ownerTree;
32367                     break;
32368                 }
32369                 p = p.parentNode;
32370             }
32371         }
32372         return this.ownerTree;
32373     },
32374
32375     
32376     getDepth : function(){
32377         var depth = 0;
32378         var p = this;
32379         while(p.parentNode){
32380             ++depth;
32381             p = p.parentNode;
32382         }
32383         return depth;
32384     },
32385
32386     
32387     setOwnerTree : function(tree, destroy){
32388         
32389         if(tree != this.ownerTree){
32390             if(this.ownerTree){
32391                 this.ownerTree.unregisterNode(this);
32392             }
32393             this.ownerTree = tree;
32394             
32395             if(destroy !== true){
32396                 Ext.each(this.childNodes, function(n){
32397                     n.setOwnerTree(tree);
32398                 });
32399             }
32400             if(tree){
32401                 tree.registerNode(this);
32402             }
32403         }
32404     },
32405
32406     
32407     setId: function(id){
32408         if(id !== this.id){
32409             var t = this.ownerTree;
32410             if(t){
32411                 t.unregisterNode(this);
32412             }
32413             this.id = this.attributes.id = id;
32414             if(t){
32415                 t.registerNode(this);
32416             }
32417             this.onIdChange(id);
32418         }
32419     },
32420
32421     
32422     onIdChange: Ext.emptyFn,
32423
32424     
32425     getPath : function(attr){
32426         attr = attr || "id";
32427         var p = this.parentNode;
32428         var b = [this.attributes[attr]];
32429         while(p){
32430             b.unshift(p.attributes[attr]);
32431             p = p.parentNode;
32432         }
32433         var sep = this.getOwnerTree().pathSeparator;
32434         return sep + b.join(sep);
32435     },
32436
32437     
32438     bubble : function(fn, scope, args){
32439         var p = this;
32440         while(p){
32441             if(fn.apply(scope || p, args || [p]) === false){
32442                 break;
32443             }
32444             p = p.parentNode;
32445         }
32446     },
32447
32448     
32449     cascade : function(fn, scope, args){
32450         if(fn.apply(scope || this, args || [this]) !== false){
32451             var cs = this.childNodes;
32452             for(var i = 0, len = cs.length; i < len; i++) {
32453                 cs[i].cascade(fn, scope, args);
32454             }
32455         }
32456     },
32457
32458     
32459     eachChild : function(fn, scope, args){
32460         var cs = this.childNodes;
32461         for(var i = 0, len = cs.length; i < len; i++) {
32462             if(fn.apply(scope || this, args || [cs[i]]) === false){
32463                 break;
32464             }
32465         }
32466     },
32467
32468     
32469     findChild : function(attribute, value, deep){
32470         return this.findChildBy(function(){
32471             return this.attributes[attribute] == value;
32472         }, null, deep);
32473     },
32474
32475     
32476     findChildBy : function(fn, scope, deep){
32477         var cs = this.childNodes,
32478             len = cs.length,
32479             i = 0,
32480             n,
32481             res;
32482         for(; i < len; i++){
32483             n = cs[i];
32484             if(fn.call(scope || n, n) === true){
32485                 return n;
32486             }else if (deep){
32487                 res = n.findChildBy(fn, scope, deep);
32488                 if(res != null){
32489                     return res;
32490                 }
32491             }
32492             
32493         }
32494         return null;
32495     },
32496
32497     
32498     sort : function(fn, scope){
32499         var cs = this.childNodes;
32500         var len = cs.length;
32501         if(len > 0){
32502             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
32503             cs.sort(sortFn);
32504             for(var i = 0; i < len; i++){
32505                 var n = cs[i];
32506                 n.previousSibling = cs[i-1];
32507                 n.nextSibling = cs[i+1];
32508                 if(i === 0){
32509                     this.setFirstChild(n);
32510                 }
32511                 if(i == len-1){
32512                     this.setLastChild(n);
32513                 }
32514             }
32515         }
32516     },
32517
32518     
32519     contains : function(node){
32520         return node.isAncestor(this);
32521     },
32522
32523     
32524     isAncestor : function(node){
32525         var p = this.parentNode;
32526         while(p){
32527             if(p == node){
32528                 return true;
32529             }
32530             p = p.parentNode;
32531         }
32532         return false;
32533     },
32534
32535     toString : function(){
32536         return "[Node"+(this.id?" "+this.id:"")+"]";
32537     }
32538 });
32539 Ext.tree.TreeNode = function(attributes){
32540     attributes = attributes || {};
32541     if(Ext.isString(attributes)){
32542         attributes = {text: attributes};
32543     }
32544     this.childrenRendered = false;
32545     this.rendered = false;
32546     Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
32547     this.expanded = attributes.expanded === true;
32548     this.isTarget = attributes.isTarget !== false;
32549     this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
32550     this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
32551
32552     
32553     this.text = attributes.text;
32554     
32555     this.disabled = attributes.disabled === true;
32556     
32557     this.hidden = attributes.hidden === true;
32558
32559     this.addEvents(
32560         
32561         'textchange',
32562         
32563         'beforeexpand',
32564         
32565         'beforecollapse',
32566         
32567         'expand',
32568         
32569         'disabledchange',
32570         
32571         'collapse',
32572         
32573         'beforeclick',
32574         
32575         'click',
32576         
32577         'checkchange',
32578         
32579         'beforedblclick',
32580         
32581         'dblclick',
32582         
32583         'contextmenu',
32584         
32585         'beforechildrenrendered'
32586     );
32587
32588     var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
32589
32590     
32591     this.ui = new uiClass(this);
32592 };
32593 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
32594     preventHScroll : true,
32595     
32596     isExpanded : function(){
32597         return this.expanded;
32598     },
32599
32600
32601     getUI : function(){
32602         return this.ui;
32603     },
32604
32605     getLoader : function(){
32606         var owner;
32607         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
32608     },
32609
32610     
32611     setFirstChild : function(node){
32612         var of = this.firstChild;
32613         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
32614         if(this.childrenRendered && of && node != of){
32615             of.renderIndent(true, true);
32616         }
32617         if(this.rendered){
32618             this.renderIndent(true, true);
32619         }
32620     },
32621
32622     
32623     setLastChild : function(node){
32624         var ol = this.lastChild;
32625         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
32626         if(this.childrenRendered && ol && node != ol){
32627             ol.renderIndent(true, true);
32628         }
32629         if(this.rendered){
32630             this.renderIndent(true, true);
32631         }
32632     },
32633
32634     
32635     
32636     appendChild : function(n){
32637         if(!n.render && !Ext.isArray(n)){
32638             n = this.getLoader().createNode(n);
32639         }
32640         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
32641         if(node && this.childrenRendered){
32642             node.render();
32643         }
32644         this.ui.updateExpandIcon();
32645         return node;
32646     },
32647
32648     
32649     removeChild : function(node, destroy){
32650         this.ownerTree.getSelectionModel().unselect(node);
32651         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
32652         
32653         if(!destroy){
32654             
32655             if(node.ui.rendered){
32656                 node.ui.remove();
32657             }
32658             if(this.childNodes.length < 1){
32659                 this.collapse(false, false);
32660             }else{
32661                 this.ui.updateExpandIcon();
32662             }
32663             if(!this.firstChild && !this.isHiddenRoot()){
32664                 this.childrenRendered = false;
32665             }
32666         }
32667         return node;
32668     },
32669
32670     
32671     insertBefore : function(node, refNode){
32672         if(!node.render){
32673             node = this.getLoader().createNode(node);
32674         }
32675         var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
32676         if(newNode && refNode && this.childrenRendered){
32677             node.render();
32678         }
32679         this.ui.updateExpandIcon();
32680         return newNode;
32681     },
32682
32683     
32684     setText : function(text){
32685         var oldText = this.text;
32686         this.text = this.attributes.text = text;
32687         if(this.rendered){ 
32688             this.ui.onTextChange(this, text, oldText);
32689         }
32690         this.fireEvent('textchange', this, text, oldText);
32691     },
32692
32693     
32694     select : function(){
32695         var t = this.getOwnerTree();
32696         if(t){
32697             t.getSelectionModel().select(this);
32698         }
32699     },
32700
32701     
32702     unselect : function(silent){
32703         var t = this.getOwnerTree();
32704         if(t){
32705             t.getSelectionModel().unselect(this, silent);
32706         }
32707     },
32708
32709     
32710     isSelected : function(){
32711         var t = this.getOwnerTree();
32712         return t ? t.getSelectionModel().isSelected(this) : false;
32713     },
32714
32715     
32716     expand : function(deep, anim, callback, scope){
32717         if(!this.expanded){
32718             if(this.fireEvent('beforeexpand', this, deep, anim) === false){
32719                 return;
32720             }
32721             if(!this.childrenRendered){
32722                 this.renderChildren();
32723             }
32724             this.expanded = true;
32725             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
32726                 this.ui.animExpand(function(){
32727                     this.fireEvent('expand', this);
32728                     this.runCallback(callback, scope || this, [this]);
32729                     if(deep === true){
32730                         this.expandChildNodes(true);
32731                     }
32732                 }.createDelegate(this));
32733                 return;
32734             }else{
32735                 this.ui.expand();
32736                 this.fireEvent('expand', this);
32737                 this.runCallback(callback, scope || this, [this]);
32738             }
32739         }else{
32740            this.runCallback(callback, scope || this, [this]);
32741         }
32742         if(deep === true){
32743             this.expandChildNodes(true);
32744         }
32745     },
32746
32747     runCallback : function(cb, scope, args){
32748         if(Ext.isFunction(cb)){
32749             cb.apply(scope, args);
32750         }
32751     },
32752
32753     isHiddenRoot : function(){
32754         return this.isRoot && !this.getOwnerTree().rootVisible;
32755     },
32756
32757     
32758     collapse : function(deep, anim, callback, scope){
32759         if(this.expanded && !this.isHiddenRoot()){
32760             if(this.fireEvent('beforecollapse', this, deep, anim) === false){
32761                 return;
32762             }
32763             this.expanded = false;
32764             if((this.getOwnerTree().animate && anim !== false) || anim){
32765                 this.ui.animCollapse(function(){
32766                     this.fireEvent('collapse', this);
32767                     this.runCallback(callback, scope || this, [this]);
32768                     if(deep === true){
32769                         this.collapseChildNodes(true);
32770                     }
32771                 }.createDelegate(this));
32772                 return;
32773             }else{
32774                 this.ui.collapse();
32775                 this.fireEvent('collapse', this);
32776                 this.runCallback(callback, scope || this, [this]);
32777             }
32778         }else if(!this.expanded){
32779             this.runCallback(callback, scope || this, [this]);
32780         }
32781         if(deep === true){
32782             var cs = this.childNodes;
32783             for(var i = 0, len = cs.length; i < len; i++) {
32784                 cs[i].collapse(true, false);
32785             }
32786         }
32787     },
32788
32789     
32790     delayedExpand : function(delay){
32791         if(!this.expandProcId){
32792             this.expandProcId = this.expand.defer(delay, this);
32793         }
32794     },
32795
32796     
32797     cancelExpand : function(){
32798         if(this.expandProcId){
32799             clearTimeout(this.expandProcId);
32800         }
32801         this.expandProcId = false;
32802     },
32803
32804     
32805     toggle : function(){
32806         if(this.expanded){
32807             this.collapse();
32808         }else{
32809             this.expand();
32810         }
32811     },
32812
32813     
32814     ensureVisible : function(callback, scope){
32815         var tree = this.getOwnerTree();
32816         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
32817             var node = tree.getNodeById(this.id);  
32818             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
32819             this.runCallback(callback, scope || this, [this]);
32820         }.createDelegate(this));
32821     },
32822
32823     
32824     expandChildNodes : function(deep){
32825         var cs = this.childNodes;
32826         for(var i = 0, len = cs.length; i < len; i++) {
32827                 cs[i].expand(deep);
32828         }
32829     },
32830
32831     
32832     collapseChildNodes : function(deep){
32833         var cs = this.childNodes;
32834         for(var i = 0, len = cs.length; i < len; i++) {
32835                 cs[i].collapse(deep);
32836         }
32837     },
32838
32839     
32840     disable : function(){
32841         this.disabled = true;
32842         this.unselect();
32843         if(this.rendered && this.ui.onDisableChange){ 
32844             this.ui.onDisableChange(this, true);
32845         }
32846         this.fireEvent('disabledchange', this, true);
32847     },
32848
32849     
32850     enable : function(){
32851         this.disabled = false;
32852         if(this.rendered && this.ui.onDisableChange){ 
32853             this.ui.onDisableChange(this, false);
32854         }
32855         this.fireEvent('disabledchange', this, false);
32856     },
32857
32858     
32859     renderChildren : function(suppressEvent){
32860         if(suppressEvent !== false){
32861             this.fireEvent('beforechildrenrendered', this);
32862         }
32863         var cs = this.childNodes;
32864         for(var i = 0, len = cs.length; i < len; i++){
32865             cs[i].render(true);
32866         }
32867         this.childrenRendered = true;
32868     },
32869
32870     
32871     sort : function(fn, scope){
32872         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
32873         if(this.childrenRendered){
32874             var cs = this.childNodes;
32875             for(var i = 0, len = cs.length; i < len; i++){
32876                 cs[i].render(true);
32877             }
32878         }
32879     },
32880
32881     
32882     render : function(bulkRender){
32883         this.ui.render(bulkRender);
32884         if(!this.rendered){
32885             
32886             this.getOwnerTree().registerNode(this);
32887             this.rendered = true;
32888             if(this.expanded){
32889                 this.expanded = false;
32890                 this.expand(false, false);
32891             }
32892         }
32893     },
32894
32895     
32896     renderIndent : function(deep, refresh){
32897         if(refresh){
32898             this.ui.childIndent = null;
32899         }
32900         this.ui.renderIndent();
32901         if(deep === true && this.childrenRendered){
32902             var cs = this.childNodes;
32903             for(var i = 0, len = cs.length; i < len; i++){
32904                 cs[i].renderIndent(true, refresh);
32905             }
32906         }
32907     },
32908
32909     beginUpdate : function(){
32910         this.childrenRendered = false;
32911     },
32912
32913     endUpdate : function(){
32914         if(this.expanded && this.rendered){
32915             this.renderChildren();
32916         }
32917     },
32918
32919     
32920     destroy : function(silent){
32921         if(silent === true){
32922             this.unselect(true);
32923         }
32924         Ext.tree.TreeNode.superclass.destroy.call(this, silent);
32925         Ext.destroy(this.ui, this.loader);
32926         this.ui = this.loader = null;
32927     },
32928
32929     
32930     onIdChange : function(id){
32931         this.ui.onIdChange(id);
32932     }
32933 });
32934
32935 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
32936  Ext.tree.AsyncTreeNode = function(config){
32937     this.loaded = config && config.loaded === true;
32938     this.loading = false;
32939     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
32940     
32941     this.addEvents('beforeload', 'load');
32942     
32943     
32944 };
32945 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
32946     expand : function(deep, anim, callback, scope){
32947         if(this.loading){ 
32948             var timer;
32949             var f = function(){
32950                 if(!this.loading){ 
32951                     clearInterval(timer);
32952                     this.expand(deep, anim, callback, scope);
32953                 }
32954             }.createDelegate(this);
32955             timer = setInterval(f, 200);
32956             return;
32957         }
32958         if(!this.loaded){
32959             if(this.fireEvent("beforeload", this) === false){
32960                 return;
32961             }
32962             this.loading = true;
32963             this.ui.beforeLoad(this);
32964             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
32965             if(loader){
32966                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
32967                 return;
32968             }
32969         }
32970         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
32971     },
32972     
32973     
32974     isLoading : function(){
32975         return this.loading;  
32976     },
32977     
32978     loadComplete : function(deep, anim, callback, scope){
32979         this.loading = false;
32980         this.loaded = true;
32981         this.ui.afterLoad(this);
32982         this.fireEvent("load", this);
32983         this.expand(deep, anim, callback, scope);
32984     },
32985     
32986     
32987     isLoaded : function(){
32988         return this.loaded;
32989     },
32990     
32991     hasChildNodes : function(){
32992         if(!this.isLeaf() && !this.loaded){
32993             return true;
32994         }else{
32995             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
32996         }
32997     },
32998
32999     
33000     reload : function(callback, scope){
33001         this.collapse(false, false);
33002         while(this.firstChild){
33003             this.removeChild(this.firstChild).destroy();
33004         }
33005         this.childrenRendered = false;
33006         this.loaded = false;
33007         if(this.isHiddenRoot()){
33008             this.expanded = false;
33009         }
33010         this.expand(false, false, callback, scope);
33011     }
33012 });
33013
33014 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
33015 Ext.tree.TreeNodeUI = function(node){
33016     this.node = node;
33017     this.rendered = false;
33018     this.animating = false;
33019     this.wasLeaf = true;
33020     this.ecc = 'x-tree-ec-icon x-tree-elbow';
33021     this.emptyIcon = Ext.BLANK_IMAGE_URL;
33022 };
33023
33024 Ext.tree.TreeNodeUI.prototype = {
33025     
33026     removeChild : function(node){
33027         if(this.rendered){
33028             this.ctNode.removeChild(node.ui.getEl());
33029         }
33030     },
33031
33032     
33033     beforeLoad : function(){
33034          this.addClass("x-tree-node-loading");
33035     },
33036
33037     
33038     afterLoad : function(){
33039          this.removeClass("x-tree-node-loading");
33040     },
33041
33042     
33043     onTextChange : function(node, text, oldText){
33044         if(this.rendered){
33045             this.textNode.innerHTML = text;
33046         }
33047     },
33048
33049     
33050     onDisableChange : function(node, state){
33051         this.disabled = state;
33052         if (this.checkbox) {
33053             this.checkbox.disabled = state;
33054         }
33055         if(state){
33056             this.addClass("x-tree-node-disabled");
33057         }else{
33058             this.removeClass("x-tree-node-disabled");
33059         }
33060     },
33061
33062     
33063     onSelectedChange : function(state){
33064         if(state){
33065             this.focus();
33066             this.addClass("x-tree-selected");
33067         }else{
33068             
33069             this.removeClass("x-tree-selected");
33070         }
33071     },
33072
33073     
33074     onMove : function(tree, node, oldParent, newParent, index, refNode){
33075         this.childIndent = null;
33076         if(this.rendered){
33077             var targetNode = newParent.ui.getContainer();
33078             if(!targetNode){
33079                 this.holder = document.createElement("div");
33080                 this.holder.appendChild(this.wrap);
33081                 return;
33082             }
33083             var insertBefore = refNode ? refNode.ui.getEl() : null;
33084             if(insertBefore){
33085                 targetNode.insertBefore(this.wrap, insertBefore);
33086             }else{
33087                 targetNode.appendChild(this.wrap);
33088             }
33089             this.node.renderIndent(true, oldParent != newParent);
33090         }
33091     },
33092
33093
33094     addClass : function(cls){
33095         if(this.elNode){
33096             Ext.fly(this.elNode).addClass(cls);
33097         }
33098     },
33099
33100
33101     removeClass : function(cls){
33102         if(this.elNode){
33103             Ext.fly(this.elNode).removeClass(cls);
33104         }
33105     },
33106
33107     
33108     remove : function(){
33109         if(this.rendered){
33110             this.holder = document.createElement("div");
33111             this.holder.appendChild(this.wrap);
33112         }
33113     },
33114
33115     
33116     fireEvent : function(){
33117         return this.node.fireEvent.apply(this.node, arguments);
33118     },
33119
33120     
33121     initEvents : function(){
33122         this.node.on("move", this.onMove, this);
33123
33124         if(this.node.disabled){
33125             this.onDisableChange(this.node, true);
33126         }
33127         if(this.node.hidden){
33128             this.hide();
33129         }
33130         var ot = this.node.getOwnerTree();
33131         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
33132         if(dd && (!this.node.isRoot || ot.rootVisible)){
33133             Ext.dd.Registry.register(this.elNode, {
33134                 node: this.node,
33135                 handles: this.getDDHandles(),
33136                 isHandle: false
33137             });
33138         }
33139     },
33140
33141     
33142     getDDHandles : function(){
33143         return [this.iconNode, this.textNode, this.elNode];
33144     },
33145
33146
33147     hide : function(){
33148         this.node.hidden = true;
33149         if(this.wrap){
33150             this.wrap.style.display = "none";
33151         }
33152     },
33153
33154
33155     show : function(){
33156         this.node.hidden = false;
33157         if(this.wrap){
33158             this.wrap.style.display = "";
33159         }
33160     },
33161
33162     
33163     onContextMenu : function(e){
33164         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
33165             e.preventDefault();
33166             this.focus();
33167             this.fireEvent("contextmenu", this.node, e);
33168         }
33169     },
33170
33171     
33172     onClick : function(e){
33173         if(this.dropping){
33174             e.stopEvent();
33175             return;
33176         }
33177         if(this.fireEvent("beforeclick", this.node, e) !== false){
33178             var a = e.getTarget('a');
33179             if(!this.disabled && this.node.attributes.href && a){
33180                 this.fireEvent("click", this.node, e);
33181                 return;
33182             }else if(a && e.ctrlKey){
33183                 e.stopEvent();
33184             }
33185             e.preventDefault();
33186             if(this.disabled){
33187                 return;
33188             }
33189
33190             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
33191                 this.node.toggle();
33192             }
33193
33194             this.fireEvent("click", this.node, e);
33195         }else{
33196             e.stopEvent();
33197         }
33198     },
33199
33200     
33201     onDblClick : function(e){
33202         e.preventDefault();
33203         if(this.disabled){
33204             return;
33205         }
33206         if(this.fireEvent("beforedblclick", this.node, e) !== false){
33207             if(this.checkbox){
33208                 this.toggleCheck();
33209             }
33210             if(!this.animating && this.node.isExpandable()){
33211                 this.node.toggle();
33212             }
33213             this.fireEvent("dblclick", this.node, e);
33214         }
33215     },
33216
33217     onOver : function(e){
33218         this.addClass('x-tree-node-over');
33219     },
33220
33221     onOut : function(e){
33222         this.removeClass('x-tree-node-over');
33223     },
33224
33225     
33226     onCheckChange : function(){
33227         var checked = this.checkbox.checked;
33228         
33229         this.checkbox.defaultChecked = checked;
33230         this.node.attributes.checked = checked;
33231         this.fireEvent('checkchange', this.node, checked);
33232     },
33233
33234     
33235     ecClick : function(e){
33236         if(!this.animating && this.node.isExpandable()){
33237             this.node.toggle();
33238         }
33239     },
33240
33241     
33242     startDrop : function(){
33243         this.dropping = true;
33244     },
33245
33246     
33247     endDrop : function(){
33248        setTimeout(function(){
33249            this.dropping = false;
33250        }.createDelegate(this), 50);
33251     },
33252
33253     
33254     expand : function(){
33255         this.updateExpandIcon();
33256         this.ctNode.style.display = "";
33257     },
33258
33259     
33260     focus : function(){
33261         if(!this.node.preventHScroll){
33262             try{this.anchor.focus();
33263             }catch(e){}
33264         }else{
33265             try{
33266                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
33267                 var l = noscroll.scrollLeft;
33268                 this.anchor.focus();
33269                 noscroll.scrollLeft = l;
33270             }catch(e){}
33271         }
33272     },
33273
33274
33275     toggleCheck : function(value){
33276         var cb = this.checkbox;
33277         if(cb){
33278             cb.checked = (value === undefined ? !cb.checked : value);
33279             this.onCheckChange();
33280         }
33281     },
33282
33283     
33284     blur : function(){
33285         try{
33286             this.anchor.blur();
33287         }catch(e){}
33288     },
33289
33290     
33291     animExpand : function(callback){
33292         var ct = Ext.get(this.ctNode);
33293         ct.stopFx();
33294         if(!this.node.isExpandable()){
33295             this.updateExpandIcon();
33296             this.ctNode.style.display = "";
33297             Ext.callback(callback);
33298             return;
33299         }
33300         this.animating = true;
33301         this.updateExpandIcon();
33302
33303         ct.slideIn('t', {
33304            callback : function(){
33305                this.animating = false;
33306                Ext.callback(callback);
33307             },
33308             scope: this,
33309             duration: this.node.ownerTree.duration || .25
33310         });
33311     },
33312
33313     
33314     highlight : function(){
33315         var tree = this.node.getOwnerTree();
33316         Ext.fly(this.wrap).highlight(
33317             tree.hlColor || "C3DAF9",
33318             {endColor: tree.hlBaseColor}
33319         );
33320     },
33321
33322     
33323     collapse : function(){
33324         this.updateExpandIcon();
33325         this.ctNode.style.display = "none";
33326     },
33327
33328     
33329     animCollapse : function(callback){
33330         var ct = Ext.get(this.ctNode);
33331         ct.enableDisplayMode('block');
33332         ct.stopFx();
33333
33334         this.animating = true;
33335         this.updateExpandIcon();
33336
33337         ct.slideOut('t', {
33338             callback : function(){
33339                this.animating = false;
33340                Ext.callback(callback);
33341             },
33342             scope: this,
33343             duration: this.node.ownerTree.duration || .25
33344         });
33345     },
33346
33347     
33348     getContainer : function(){
33349         return this.ctNode;
33350     },
33351
33352
33353     getEl : function(){
33354         return this.wrap;
33355     },
33356
33357     
33358     appendDDGhost : function(ghostNode){
33359         ghostNode.appendChild(this.elNode.cloneNode(true));
33360     },
33361
33362     
33363     getDDRepairXY : function(){
33364         return Ext.lib.Dom.getXY(this.iconNode);
33365     },
33366
33367     
33368     onRender : function(){
33369         this.render();
33370     },
33371
33372     
33373     render : function(bulkRender){
33374         var n = this.node, a = n.attributes;
33375         var targetNode = n.parentNode ?
33376               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
33377
33378         if(!this.rendered){
33379             this.rendered = true;
33380
33381             this.renderElements(n, a, targetNode, bulkRender);
33382
33383             if(a.qtip){
33384                if(this.textNode.setAttributeNS){
33385                    this.textNode.setAttributeNS("ext", "qtip", a.qtip);
33386                    if(a.qtipTitle){
33387                        this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
33388                    }
33389                }else{
33390                    this.textNode.setAttribute("ext:qtip", a.qtip);
33391                    if(a.qtipTitle){
33392                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
33393                    }
33394                }
33395             }else if(a.qtipCfg){
33396                 a.qtipCfg.target = Ext.id(this.textNode);
33397                 Ext.QuickTips.register(a.qtipCfg);
33398             }
33399             this.initEvents();
33400             if(!this.node.expanded){
33401                 this.updateExpandIcon(true);
33402             }
33403         }else{
33404             if(bulkRender === true) {
33405                 targetNode.appendChild(this.wrap);
33406             }
33407         }
33408     },
33409
33410     
33411     renderElements : function(n, a, targetNode, bulkRender){
33412         
33413         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
33414
33415         var cb = Ext.isBoolean(a.checked),
33416             nel,
33417             href = a.href ? a.href : Ext.isGecko ? "" : "#",
33418             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">',
33419             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
33420             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
33421             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
33422             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
33423             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
33424              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
33425             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
33426             "</li>"].join('');
33427
33428         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
33429             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
33430         }else{
33431             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
33432         }
33433
33434         this.elNode = this.wrap.childNodes[0];
33435         this.ctNode = this.wrap.childNodes[1];
33436         var cs = this.elNode.childNodes;
33437         this.indentNode = cs[0];
33438         this.ecNode = cs[1];
33439         this.iconNode = cs[2];
33440         var index = 3;
33441         if(cb){
33442             this.checkbox = cs[3];
33443             
33444             this.checkbox.defaultChecked = this.checkbox.checked;
33445             index++;
33446         }
33447         this.anchor = cs[index];
33448         this.textNode = cs[index].firstChild;
33449     },
33450
33451
33452     getAnchor : function(){
33453         return this.anchor;
33454     },
33455
33456
33457     getTextEl : function(){
33458         return this.textNode;
33459     },
33460
33461
33462     getIconEl : function(){
33463         return this.iconNode;
33464     },
33465
33466
33467     isChecked : function(){
33468         return this.checkbox ? this.checkbox.checked : false;
33469     },
33470
33471     
33472     updateExpandIcon : function(){
33473         if(this.rendered){
33474             var n = this.node,
33475                 c1,
33476                 c2,
33477                 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
33478                 hasChild = n.hasChildNodes();
33479             if(hasChild || n.attributes.expandable){
33480                 if(n.expanded){
33481                     cls += "-minus";
33482                     c1 = "x-tree-node-collapsed";
33483                     c2 = "x-tree-node-expanded";
33484                 }else{
33485                     cls += "-plus";
33486                     c1 = "x-tree-node-expanded";
33487                     c2 = "x-tree-node-collapsed";
33488                 }
33489                 if(this.wasLeaf){
33490                     this.removeClass("x-tree-node-leaf");
33491                     this.wasLeaf = false;
33492                 }
33493                 if(this.c1 != c1 || this.c2 != c2){
33494                     Ext.fly(this.elNode).replaceClass(c1, c2);
33495                     this.c1 = c1; this.c2 = c2;
33496                 }
33497             }else{
33498                 if(!this.wasLeaf){
33499                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
33500                     delete this.c1;
33501                     delete this.c2;
33502                     this.wasLeaf = true;
33503                 }
33504             }
33505             var ecc = "x-tree-ec-icon "+cls;
33506             if(this.ecc != ecc){
33507                 this.ecNode.className = ecc;
33508                 this.ecc = ecc;
33509             }
33510         }
33511     },
33512
33513     
33514     onIdChange: function(id){
33515         if(this.rendered){
33516             this.elNode.setAttribute('ext:tree-node-id', id);
33517         }
33518     },
33519
33520     
33521     getChildIndent : function(){
33522         if(!this.childIndent){
33523             var buf = [],
33524                 p = this.node;
33525             while(p){
33526                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
33527                     if(!p.isLast()) {
33528                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
33529                     } else {
33530                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
33531                     }
33532                 }
33533                 p = p.parentNode;
33534             }
33535             this.childIndent = buf.join("");
33536         }
33537         return this.childIndent;
33538     },
33539
33540     
33541     renderIndent : function(){
33542         if(this.rendered){
33543             var indent = "",
33544                 p = this.node.parentNode;
33545             if(p){
33546                 indent = p.ui.getChildIndent();
33547             }
33548             if(this.indentMarkup != indent){ 
33549                 this.indentNode.innerHTML = indent;
33550                 this.indentMarkup = indent;
33551             }
33552             this.updateExpandIcon();
33553         }
33554     },
33555
33556     destroy : function(){
33557         if(this.elNode){
33558             Ext.dd.Registry.unregister(this.elNode.id);
33559         }
33560
33561         Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
33562             if(this[el]){
33563                 Ext.fly(this[el]).remove();
33564                 delete this[el];
33565             }
33566         }, this);
33567         delete this.node;
33568     }
33569 };
33570
33571
33572 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
33573     
33574     render : function(){
33575         if(!this.rendered){
33576             var targetNode = this.node.ownerTree.innerCt.dom;
33577             this.node.expanded = true;
33578             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
33579             this.wrap = this.ctNode = targetNode.firstChild;
33580         }
33581     },
33582     collapse : Ext.emptyFn,
33583     expand : Ext.emptyFn
33584 });
33585 Ext.tree.TreeLoader = function(config){
33586     this.baseParams = {};
33587     Ext.apply(this, config);
33588
33589     this.addEvents(
33590         
33591         "beforeload",
33592         
33593         "load",
33594         
33595         "loadexception"
33596     );
33597     Ext.tree.TreeLoader.superclass.constructor.call(this);
33598     if(Ext.isString(this.paramOrder)){
33599         this.paramOrder = this.paramOrder.split(/[\s,|]/);
33600     }
33601 };
33602
33603 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
33604     
33605     
33606     
33607     
33608     
33609     
33610     
33611     uiProviders : {},
33612
33613     
33614     clearOnLoad : true,
33615
33616     
33617     paramOrder: undefined,
33618
33619     
33620     paramsAsHash: false,
33621
33622     
33623     nodeParameter: 'node',
33624
33625     
33626     directFn : undefined,
33627
33628     
33629     load : function(node, callback, scope){
33630         if(this.clearOnLoad){
33631             while(node.firstChild){
33632                 node.removeChild(node.firstChild);
33633             }
33634         }
33635         if(this.doPreload(node)){ 
33636             this.runCallback(callback, scope || node, [node]);
33637         }else if(this.directFn || this.dataUrl || this.url){
33638             this.requestData(node, callback, scope || node);
33639         }
33640     },
33641
33642     doPreload : function(node){
33643         if(node.attributes.children){
33644             if(node.childNodes.length < 1){ 
33645                 var cs = node.attributes.children;
33646                 node.beginUpdate();
33647                 for(var i = 0, len = cs.length; i < len; i++){
33648                     var cn = node.appendChild(this.createNode(cs[i]));
33649                     if(this.preloadChildren){
33650                         this.doPreload(cn);
33651                     }
33652                 }
33653                 node.endUpdate();
33654             }
33655             return true;
33656         }
33657         return false;
33658     },
33659
33660     getParams: function(node){
33661         var bp = Ext.apply({}, this.baseParams),
33662             np = this.nodeParameter,
33663             po = this.paramOrder;
33664
33665         np && (bp[ np ] = node.id);
33666
33667         if(this.directFn){
33668             var buf = [node.id];
33669             if(po){
33670                 
33671                 if(np && po.indexOf(np) > -1){
33672                     buf = [];
33673                 }
33674
33675                 for(var i = 0, len = po.length; i < len; i++){
33676                     buf.push(bp[ po[i] ]);
33677                 }
33678             }else if(this.paramsAsHash){
33679                 buf = [bp];
33680             }
33681             return buf;
33682         }else{
33683             return bp;
33684         }
33685     },
33686
33687     requestData : function(node, callback, scope){
33688         if(this.fireEvent("beforeload", this, node, callback) !== false){
33689             if(this.directFn){
33690                 var args = this.getParams(node);
33691                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
33692                 this.directFn.apply(window, args);
33693             }else{
33694                 this.transId = Ext.Ajax.request({
33695                     method:this.requestMethod,
33696                     url: this.dataUrl||this.url,
33697                     success: this.handleResponse,
33698                     failure: this.handleFailure,
33699                     scope: this,
33700                     argument: {callback: callback, node: node, scope: scope},
33701                     params: this.getParams(node)
33702                 });
33703             }
33704         }else{
33705             
33706             
33707             this.runCallback(callback, scope || node, []);
33708         }
33709     },
33710
33711     processDirectResponse: function(result, response, args){
33712         if(response.status){
33713             this.handleResponse({
33714                 responseData: Ext.isArray(result) ? result : null,
33715                 responseText: result,
33716                 argument: args
33717             });
33718         }else{
33719             this.handleFailure({
33720                 argument: args
33721             });
33722         }
33723     },
33724
33725     
33726     runCallback: function(cb, scope, args){
33727         if(Ext.isFunction(cb)){
33728             cb.apply(scope, args);
33729         }
33730     },
33731
33732     isLoading : function(){
33733         return !!this.transId;
33734     },
33735
33736     abort : function(){
33737         if(this.isLoading()){
33738             Ext.Ajax.abort(this.transId);
33739         }
33740     },
33741
33742     
33743     createNode : function(attr){
33744         
33745         if(this.baseAttrs){
33746             Ext.applyIf(attr, this.baseAttrs);
33747         }
33748         if(this.applyLoader !== false && !attr.loader){
33749             attr.loader = this;
33750         }
33751         if(Ext.isString(attr.uiProvider)){
33752            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
33753         }
33754         if(attr.nodeType){
33755             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
33756         }else{
33757             return attr.leaf ?
33758                         new Ext.tree.TreeNode(attr) :
33759                         new Ext.tree.AsyncTreeNode(attr);
33760         }
33761     },
33762
33763     processResponse : function(response, node, callback, scope){
33764         var json = response.responseText;
33765         try {
33766             var o = response.responseData || Ext.decode(json);
33767             node.beginUpdate();
33768             for(var i = 0, len = o.length; i < len; i++){
33769                 var n = this.createNode(o[i]);
33770                 if(n){
33771                     node.appendChild(n);
33772                 }
33773             }
33774             node.endUpdate();
33775             this.runCallback(callback, scope || node, [node]);
33776         }catch(e){
33777             this.handleFailure(response);
33778         }
33779     },
33780
33781     handleResponse : function(response){
33782         this.transId = false;
33783         var a = response.argument;
33784         this.processResponse(response, a.node, a.callback, a.scope);
33785         this.fireEvent("load", this, a.node, response);
33786     },
33787
33788     handleFailure : function(response){
33789         this.transId = false;
33790         var a = response.argument;
33791         this.fireEvent("loadexception", this, a.node, response);
33792         this.runCallback(a.callback, a.scope || a.node, [a.node]);
33793     },
33794
33795     destroy : function(){
33796         this.abort();
33797         this.purgeListeners();
33798     }
33799 });
33800 Ext.tree.TreeFilter = function(tree, config){
33801     this.tree = tree;
33802     this.filtered = {};
33803     Ext.apply(this, config);
33804 };
33805
33806 Ext.tree.TreeFilter.prototype = {
33807     clearBlank:false,
33808     reverse:false,
33809     autoClear:false,
33810     remove:false,
33811
33812      
33813     filter : function(value, attr, startNode){
33814         attr = attr || "text";
33815         var f;
33816         if(typeof value == "string"){
33817             var vlen = value.length;
33818             
33819             if(vlen == 0 && this.clearBlank){
33820                 this.clear();
33821                 return;
33822             }
33823             value = value.toLowerCase();
33824             f = function(n){
33825                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
33826             };
33827         }else if(value.exec){ 
33828             f = function(n){
33829                 return value.test(n.attributes[attr]);
33830             };
33831         }else{
33832             throw 'Illegal filter type, must be string or regex';
33833         }
33834         this.filterBy(f, null, startNode);
33835         },
33836
33837     
33838     filterBy : function(fn, scope, startNode){
33839         startNode = startNode || this.tree.root;
33840         if(this.autoClear){
33841             this.clear();
33842         }
33843         var af = this.filtered, rv = this.reverse;
33844         var f = function(n){
33845             if(n == startNode){
33846                 return true;
33847             }
33848             if(af[n.id]){
33849                 return false;
33850             }
33851             var m = fn.call(scope || n, n);
33852             if(!m || rv){
33853                 af[n.id] = n;
33854                 n.ui.hide();
33855                 return false;
33856             }
33857             return true;
33858         };
33859         startNode.cascade(f);
33860         if(this.remove){
33861            for(var id in af){
33862                if(typeof id != "function"){
33863                    var n = af[id];
33864                    if(n && n.parentNode){
33865                        n.parentNode.removeChild(n);
33866                    }
33867                }
33868            }
33869         }
33870     },
33871
33872     
33873     clear : function(){
33874         var t = this.tree;
33875         var af = this.filtered;
33876         for(var id in af){
33877             if(typeof id != "function"){
33878                 var n = af[id];
33879                 if(n){
33880                     n.ui.show();
33881                 }
33882             }
33883         }
33884         this.filtered = {};
33885     }
33886 };
33887
33888 Ext.tree.TreeSorter = function(tree, config){
33889     
33890     
33891     
33892     
33893     
33894     
33895
33896     Ext.apply(this, config);
33897     tree.on("beforechildrenrendered", this.doSort, this);
33898     tree.on("append", this.updateSort, this);
33899     tree.on("insert", this.updateSort, this);
33900     tree.on("textchange", this.updateSortParent, this);
33901
33902     var dsc = this.dir && this.dir.toLowerCase() == "desc";
33903     var p = this.property || "text";
33904     var sortType = this.sortType;
33905     var fs = this.folderSort;
33906     var cs = this.caseSensitive === true;
33907     var leafAttr = this.leafAttr || 'leaf';
33908
33909     this.sortFn = function(n1, n2){
33910         if(fs){
33911             if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
33912                 return 1;
33913             }
33914             if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
33915                 return -1;
33916             }
33917         }
33918         var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
33919         var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
33920         if(v1 < v2){
33921             return dsc ? +1 : -1;
33922         }else if(v1 > v2){
33923             return dsc ? -1 : +1;
33924         }else{
33925             return 0;
33926         }
33927     };
33928 };
33929
33930 Ext.tree.TreeSorter.prototype = {
33931     doSort : function(node){
33932         node.sort(this.sortFn);
33933     },
33934
33935     compareNodes : function(n1, n2){
33936         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
33937     },
33938
33939     updateSort : function(tree, node){
33940         if(node.childrenRendered){
33941             this.doSort.defer(1, this, [node]);
33942         }
33943     },
33944
33945     updateSortParent : function(node){
33946         var p = node.parentNode;
33947         if(p && p.childrenRendered){
33948             this.doSort.defer(1, this, [p]);
33949         }
33950     }
33951 };
33952 if(Ext.dd.DropZone){
33953     
33954 Ext.tree.TreeDropZone = function(tree, config){
33955     
33956     this.allowParentInsert = config.allowParentInsert || false;
33957     
33958     this.allowContainerDrop = config.allowContainerDrop || false;
33959     
33960     this.appendOnly = config.appendOnly || false;
33961
33962     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
33963     
33964     this.tree = tree;
33965     
33966     this.dragOverData = {};
33967     
33968     this.lastInsertClass = "x-tree-no-status";
33969 };
33970
33971 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
33972     
33973     ddGroup : "TreeDD",
33974
33975     
33976     expandDelay : 1000,
33977
33978     
33979     expandNode : function(node){
33980         if(node.hasChildNodes() && !node.isExpanded()){
33981             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
33982         }
33983     },
33984
33985     
33986     queueExpand : function(node){
33987         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
33988     },
33989
33990     
33991     cancelExpand : function(){
33992         if(this.expandProcId){
33993             clearTimeout(this.expandProcId);
33994             this.expandProcId = false;
33995         }
33996     },
33997
33998     
33999     isValidDropPoint : function(n, pt, dd, e, data){
34000         if(!n || !data){ return false; }
34001         var targetNode = n.node;
34002         var dropNode = data.node;
34003         
34004         if(!(targetNode && targetNode.isTarget && pt)){
34005             return false;
34006         }
34007         if(pt == "append" && targetNode.allowChildren === false){
34008             return false;
34009         }
34010         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
34011             return false;
34012         }
34013         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
34014             return false;
34015         }
34016         
34017         var overEvent = this.dragOverData;
34018         overEvent.tree = this.tree;
34019         overEvent.target = targetNode;
34020         overEvent.data = data;
34021         overEvent.point = pt;
34022         overEvent.source = dd;
34023         overEvent.rawEvent = e;
34024         overEvent.dropNode = dropNode;
34025         overEvent.cancel = false;  
34026         var result = this.tree.fireEvent("nodedragover", overEvent);
34027         return overEvent.cancel === false && result !== false;
34028     },
34029
34030     
34031     getDropPoint : function(e, n, dd){
34032         var tn = n.node;
34033         if(tn.isRoot){
34034             return tn.allowChildren !== false ? "append" : false; 
34035         }
34036         var dragEl = n.ddel;
34037         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
34038         var y = Ext.lib.Event.getPageY(e);
34039         var noAppend = tn.allowChildren === false || tn.isLeaf();
34040         if(this.appendOnly || tn.parentNode.allowChildren === false){
34041             return noAppend ? false : "append";
34042         }
34043         var noBelow = false;
34044         if(!this.allowParentInsert){
34045             noBelow = tn.hasChildNodes() && tn.isExpanded();
34046         }
34047         var q = (b - t) / (noAppend ? 2 : 3);
34048         if(y >= t && y < (t + q)){
34049             return "above";
34050         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
34051             return "below";
34052         }else{
34053             return "append";
34054         }
34055     },
34056
34057     
34058     onNodeEnter : function(n, dd, e, data){
34059         this.cancelExpand();
34060     },
34061     
34062     onContainerOver : function(dd, e, data) {
34063         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
34064             return this.dropAllowed;
34065         }
34066         return this.dropNotAllowed;
34067     },
34068
34069     
34070     onNodeOver : function(n, dd, e, data){
34071         var pt = this.getDropPoint(e, n, dd);
34072         var node = n.node;
34073         
34074         
34075         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
34076             this.queueExpand(node);
34077         }else if(pt != "append"){
34078             this.cancelExpand();
34079         }
34080         
34081         
34082         var returnCls = this.dropNotAllowed;
34083         if(this.isValidDropPoint(n, pt, dd, e, data)){
34084            if(pt){
34085                var el = n.ddel;
34086                var cls;
34087                if(pt == "above"){
34088                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
34089                    cls = "x-tree-drag-insert-above";
34090                }else if(pt == "below"){
34091                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
34092                    cls = "x-tree-drag-insert-below";
34093                }else{
34094                    returnCls = "x-tree-drop-ok-append";
34095                    cls = "x-tree-drag-append";
34096                }
34097                if(this.lastInsertClass != cls){
34098                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
34099                    this.lastInsertClass = cls;
34100                }
34101            }
34102        }
34103        return returnCls;
34104     },
34105
34106     
34107     onNodeOut : function(n, dd, e, data){
34108         this.cancelExpand();
34109         this.removeDropIndicators(n);
34110     },
34111
34112     
34113     onNodeDrop : function(n, dd, e, data){
34114         var point = this.getDropPoint(e, n, dd);
34115         var targetNode = n.node;
34116         targetNode.ui.startDrop();
34117         if(!this.isValidDropPoint(n, point, dd, e, data)){
34118             targetNode.ui.endDrop();
34119             return false;
34120         }
34121         
34122         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
34123         return this.processDrop(targetNode, data, point, dd, e, dropNode);
34124     },
34125     
34126     onContainerDrop : function(dd, e, data){
34127         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
34128             var targetNode = this.tree.getRootNode();       
34129             targetNode.ui.startDrop();
34130             var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
34131             return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
34132         }
34133         return false;
34134     },
34135     
34136     
34137     processDrop: function(target, data, point, dd, e, dropNode){
34138         var dropEvent = {
34139             tree : this.tree,
34140             target: target,
34141             data: data,
34142             point: point,
34143             source: dd,
34144             rawEvent: e,
34145             dropNode: dropNode,
34146             cancel: !dropNode,
34147             dropStatus: false
34148         };
34149         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
34150         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
34151             target.ui.endDrop();
34152             return dropEvent.dropStatus;
34153         }
34154     
34155         target = dropEvent.target;
34156         if(point == 'append' && !target.isExpanded()){
34157             target.expand(false, null, function(){
34158                 this.completeDrop(dropEvent);
34159             }.createDelegate(this));
34160         }else{
34161             this.completeDrop(dropEvent);
34162         }
34163         return true;
34164     },
34165
34166     
34167     completeDrop : function(de){
34168         var ns = de.dropNode, p = de.point, t = de.target;
34169         if(!Ext.isArray(ns)){
34170             ns = [ns];
34171         }
34172         var n;
34173         for(var i = 0, len = ns.length; i < len; i++){
34174             n = ns[i];
34175             if(p == "above"){
34176                 t.parentNode.insertBefore(n, t);
34177             }else if(p == "below"){
34178                 t.parentNode.insertBefore(n, t.nextSibling);
34179             }else{
34180                 t.appendChild(n);
34181             }
34182         }
34183         n.ui.focus();
34184         if(Ext.enableFx && this.tree.hlDrop){
34185             n.ui.highlight();
34186         }
34187         t.ui.endDrop();
34188         this.tree.fireEvent("nodedrop", de);
34189     },
34190
34191     
34192     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
34193         if(Ext.enableFx && this.tree.hlDrop){
34194             dropNode.ui.focus();
34195             dropNode.ui.highlight();
34196         }
34197         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
34198     },
34199
34200     
34201     getTree : function(){
34202         return this.tree;
34203     },
34204
34205     
34206     removeDropIndicators : function(n){
34207         if(n && n.ddel){
34208             var el = n.ddel;
34209             Ext.fly(el).removeClass([
34210                     "x-tree-drag-insert-above",
34211                     "x-tree-drag-insert-below",
34212                     "x-tree-drag-append"]);
34213             this.lastInsertClass = "_noclass";
34214         }
34215     },
34216
34217     
34218     beforeDragDrop : function(target, e, id){
34219         this.cancelExpand();
34220         return true;
34221     },
34222
34223     
34224     afterRepair : function(data){
34225         if(data && Ext.enableFx){
34226             data.node.ui.highlight();
34227         }
34228         this.hideProxy();
34229     }    
34230 });
34231
34232 }
34233 if(Ext.dd.DragZone){
34234 Ext.tree.TreeDragZone = function(tree, config){
34235     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
34236     
34237     this.tree = tree;
34238 };
34239
34240 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
34241     
34242     ddGroup : "TreeDD",
34243
34244     
34245     onBeforeDrag : function(data, e){
34246         var n = data.node;
34247         return n && n.draggable && !n.disabled;
34248     },
34249
34250     
34251     onInitDrag : function(e){
34252         var data = this.dragData;
34253         this.tree.getSelectionModel().select(data.node);
34254         this.tree.eventModel.disable();
34255         this.proxy.update("");
34256         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
34257         this.tree.fireEvent("startdrag", this.tree, data.node, e);
34258     },
34259
34260     
34261     getRepairXY : function(e, data){
34262         return data.node.ui.getDDRepairXY();
34263     },
34264
34265     
34266     onEndDrag : function(data, e){
34267         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
34268         this.tree.fireEvent("enddrag", this.tree, data.node, e);
34269     },
34270
34271     
34272     onValidDrop : function(dd, e, id){
34273         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
34274         this.hideProxy();
34275     },
34276
34277     
34278     beforeInvalidDrop : function(e, id){
34279         
34280         var sm = this.tree.getSelectionModel();
34281         sm.clearSelections();
34282         sm.select(this.dragData.node);
34283     },
34284     
34285     
34286     afterRepair : function(){
34287         if (Ext.enableFx && this.tree.hlDrop) {
34288             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
34289         }
34290         this.dragging = false;
34291     }
34292 });
34293 }
34294 Ext.tree.TreeEditor = function(tree, fc, config){
34295     fc = fc || {};
34296     var field = fc.events ? fc : new Ext.form.TextField(fc);
34297     
34298     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
34299
34300     this.tree = tree;
34301
34302     if(!tree.rendered){
34303         tree.on('render', this.initEditor, this);
34304     }else{
34305         this.initEditor(tree);
34306     }
34307 };
34308
34309 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
34310     
34311     alignment: "l-l",
34312     
34313     autoSize: false,
34314     
34315     hideEl : false,
34316     
34317     cls: "x-small-editor x-tree-editor",
34318     
34319     shim:false,
34320     
34321     shadow:"frame",
34322     
34323     maxWidth: 250,
34324     
34325     editDelay : 350,
34326
34327     initEditor : function(tree){
34328         tree.on({
34329             scope      : this,
34330             beforeclick: this.beforeNodeClick,
34331             dblclick   : this.onNodeDblClick
34332         });
34333         
34334         this.on({
34335             scope          : this,
34336             complete       : this.updateNode,
34337             beforestartedit: this.fitToTree,
34338             specialkey     : this.onSpecialKey
34339         });
34340         
34341         this.on('startedit', this.bindScroll, this, {delay:10});
34342     },
34343
34344     
34345     fitToTree : function(ed, el){
34346         var td = this.tree.getTreeEl().dom, nd = el.dom;
34347         if(td.scrollLeft >  nd.offsetLeft){ 
34348             td.scrollLeft = nd.offsetLeft;
34349         }
34350         var w = Math.min(
34351                 this.maxWidth,
34352                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
34353         this.setSize(w, '');
34354     },
34355
34356     
34357     triggerEdit : function(node, defer){
34358         this.completeEdit();
34359                 if(node.attributes.editable !== false){
34360            
34361                         this.editNode = node;
34362             if(this.tree.autoScroll){
34363                 Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
34364             }
34365             var value = node.text || '';
34366             if (!Ext.isGecko && Ext.isEmpty(node.text)){
34367                 node.setText('&#160;');
34368             }
34369             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
34370             return false;
34371         }
34372     },
34373
34374     
34375     bindScroll : function(){
34376         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
34377     },
34378
34379     
34380     beforeNodeClick : function(node, e){
34381         clearTimeout(this.autoEditTimer);
34382         if(this.tree.getSelectionModel().isSelected(node)){
34383             e.stopEvent();
34384             return this.triggerEdit(node);
34385         }
34386     },
34387
34388     onNodeDblClick : function(node, e){
34389         clearTimeout(this.autoEditTimer);
34390     },
34391
34392     
34393     updateNode : function(ed, value){
34394         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
34395         this.editNode.setText(value);
34396     },
34397
34398     
34399     onHide : function(){
34400         Ext.tree.TreeEditor.superclass.onHide.call(this);
34401         if(this.editNode){
34402             this.editNode.ui.focus.defer(50, this.editNode.ui);
34403         }
34404     },
34405
34406     
34407     onSpecialKey : function(field, e){
34408         var k = e.getKey();
34409         if(k == e.ESC){
34410             e.stopEvent();
34411             this.cancelEdit();
34412         }else if(k == e.ENTER && !e.hasModifier()){
34413             e.stopEvent();
34414             this.completeEdit();
34415         }
34416     },
34417     
34418     onDestroy : function(){
34419         clearTimeout(this.autoEditTimer);
34420         Ext.tree.TreeEditor.superclass.onDestroy.call(this);
34421         var tree = this.tree;
34422         tree.un('beforeclick', this.beforeNodeClick, this);
34423         tree.un('dblclick', this.onNodeDblClick, this);
34424     }
34425 });
34426
34427 var swfobject = function() {
34428     
34429     var UNDEF = "undefined",
34430         OBJECT = "object",
34431         SHOCKWAVE_FLASH = "Shockwave Flash",
34432         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
34433         FLASH_MIME_TYPE = "application/x-shockwave-flash",
34434         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
34435         ON_READY_STATE_CHANGE = "onreadystatechange",
34436         
34437         win = window,
34438         doc = document,
34439         nav = navigator,
34440         
34441         plugin = false,
34442         domLoadFnArr = [main],
34443         regObjArr = [],
34444         objIdArr = [],
34445         listenersArr = [],
34446         storedAltContent,
34447         storedAltContentId,
34448         storedCallbackFn,
34449         storedCallbackObj,
34450         isDomLoaded = false,
34451         isExpressInstallActive = false,
34452         dynamicStylesheet,
34453         dynamicStylesheetMedia,
34454         autoHideShow = true,
34455     
34456       
34457     ua = function() {
34458         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
34459             u = nav.userAgent.toLowerCase(),
34460             p = nav.platform.toLowerCase(),
34461             windows = p ? /win/.test(p) : /win/.test(u),
34462             mac = p ? /mac/.test(p) : /mac/.test(u),
34463             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
34464             ie = !+"\v1", 
34465             playerVersion = [0,0,0],
34466             d = null;
34467         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
34468             d = nav.plugins[SHOCKWAVE_FLASH].description;
34469             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
34470                 plugin = true;
34471                 ie = false; 
34472                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
34473                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
34474                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
34475                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
34476             }
34477         }
34478         else if (typeof win.ActiveXObject != UNDEF) {
34479             try {
34480                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
34481                 if (a) { 
34482                     d = a.GetVariable("$version");
34483                     if (d) {
34484                         ie = true; 
34485                         d = d.split(" ")[1].split(",");
34486                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
34487                     }
34488                 }
34489             }
34490             catch(e) {}
34491         }
34492         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
34493     }(),
34494     
34495      
34496     onDomLoad = function() {
34497         if (!ua.w3) { return; }
34498         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
34499             callDomLoadFunctions();
34500         }
34501         if (!isDomLoaded) {
34502             if (typeof doc.addEventListener != UNDEF) {
34503                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
34504             }       
34505             if (ua.ie && ua.win) {
34506                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
34507                     if (doc.readyState == "complete") {
34508                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
34509                         callDomLoadFunctions();
34510                     }
34511                 });
34512                 if (win == top) { 
34513                     (function(){
34514                         if (isDomLoaded) { return; }
34515                         try {
34516                             doc.documentElement.doScroll("left");
34517                         }
34518                         catch(e) {
34519                             setTimeout(arguments.callee, 0);
34520                             return;
34521                         }
34522                         callDomLoadFunctions();
34523                     })();
34524                 }
34525             }
34526             if (ua.wk) {
34527                 (function(){
34528                     if (isDomLoaded) { return; }
34529                     if (!/loaded|complete/.test(doc.readyState)) {
34530                         setTimeout(arguments.callee, 0);
34531                         return;
34532                     }
34533                     callDomLoadFunctions();
34534                 })();
34535             }
34536             addLoadEvent(callDomLoadFunctions);
34537         }
34538     }();
34539     
34540     function callDomLoadFunctions() {
34541         if (isDomLoaded) { return; }
34542         try { 
34543             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
34544             t.parentNode.removeChild(t);
34545         }
34546         catch (e) { return; }
34547         isDomLoaded = true;
34548         var dl = domLoadFnArr.length;
34549         for (var i = 0; i < dl; i++) {
34550             domLoadFnArr[i]();
34551         }
34552     }
34553     
34554     function addDomLoadEvent(fn) {
34555         if (isDomLoaded) {
34556             fn();
34557         }
34558         else { 
34559             domLoadFnArr[domLoadFnArr.length] = fn; 
34560         }
34561     }
34562     
34563     
34564     function addLoadEvent(fn) {
34565         if (typeof win.addEventListener != UNDEF) {
34566             win.addEventListener("load", fn, false);
34567         }
34568         else if (typeof doc.addEventListener != UNDEF) {
34569             doc.addEventListener("load", fn, false);
34570         }
34571         else if (typeof win.attachEvent != UNDEF) {
34572             addListener(win, "onload", fn);
34573         }
34574         else if (typeof win.onload == "function") {
34575             var fnOld = win.onload;
34576             win.onload = function() {
34577                 fnOld();
34578                 fn();
34579             };
34580         }
34581         else {
34582             win.onload = fn;
34583         }
34584     }
34585     
34586     
34587     function main() { 
34588         if (plugin) {
34589             testPlayerVersion();
34590         }
34591         else {
34592             matchVersions();
34593         }
34594     }
34595     
34596     
34597     function testPlayerVersion() {
34598         var b = doc.getElementsByTagName("body")[0];
34599         var o = createElement(OBJECT);
34600         o.setAttribute("type", FLASH_MIME_TYPE);
34601         var t = b.appendChild(o);
34602         if (t) {
34603             var counter = 0;
34604             (function(){
34605                 if (typeof t.GetVariable != UNDEF) {
34606                     var d = t.GetVariable("$version");
34607                     if (d) {
34608                         d = d.split(" ")[1].split(",");
34609                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
34610                     }
34611                 }
34612                 else if (counter < 10) {
34613                     counter++;
34614                     setTimeout(arguments.callee, 10);
34615                     return;
34616                 }
34617                 b.removeChild(o);
34618                 t = null;
34619                 matchVersions();
34620             })();
34621         }
34622         else {
34623             matchVersions();
34624         }
34625     }
34626     
34627     
34628     function matchVersions() {
34629         var rl = regObjArr.length;
34630         if (rl > 0) {
34631             for (var i = 0; i < rl; i++) { 
34632                 var id = regObjArr[i].id;
34633                 var cb = regObjArr[i].callbackFn;
34634                 var cbObj = {success:false, id:id};
34635                 if (ua.pv[0] > 0) {
34636                     var obj = getElementById(id);
34637                     if (obj) {
34638                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
34639                             setVisibility(id, true);
34640                             if (cb) {
34641                                 cbObj.success = true;
34642                                 cbObj.ref = getObjectById(id);
34643                                 cb(cbObj);
34644                             }
34645                         }
34646                         else if (regObjArr[i].expressInstall && canExpressInstall()) { 
34647                             var att = {};
34648                             att.data = regObjArr[i].expressInstall;
34649                             att.width = obj.getAttribute("width") || "0";
34650                             att.height = obj.getAttribute("height") || "0";
34651                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
34652                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
34653                             
34654                             var par = {};
34655                             var p = obj.getElementsByTagName("param");
34656                             var pl = p.length;
34657                             for (var j = 0; j < pl; j++) {
34658                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
34659                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
34660                                 }
34661                             }
34662                             showExpressInstall(att, par, id, cb);
34663                         }
34664                         else { 
34665                             displayAltContent(obj);
34666                             if (cb) { cb(cbObj); }
34667                         }
34668                     }
34669                 }
34670                 else {  
34671                     setVisibility(id, true);
34672                     if (cb) {
34673                         var o = getObjectById(id); 
34674                         if (o && typeof o.SetVariable != UNDEF) { 
34675                             cbObj.success = true;
34676                             cbObj.ref = o;
34677                         }
34678                         cb(cbObj);
34679                     }
34680                 }
34681             }
34682         }
34683     }
34684     
34685     function getObjectById(objectIdStr) {
34686         var r = null;
34687         var o = getElementById(objectIdStr);
34688         if (o && o.nodeName == "OBJECT") {
34689             if (typeof o.SetVariable != UNDEF) {
34690                 r = o;
34691             }
34692             else {
34693                 var n = o.getElementsByTagName(OBJECT)[0];
34694                 if (n) {
34695                     r = n;
34696                 }
34697             }
34698         }
34699         return r;
34700     }
34701     
34702     
34703     function canExpressInstall() {
34704         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
34705     }
34706     
34707     
34708     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
34709         isExpressInstallActive = true;
34710         storedCallbackFn = callbackFn || null;
34711         storedCallbackObj = {success:false, id:replaceElemIdStr};
34712         var obj = getElementById(replaceElemIdStr);
34713         if (obj) {
34714             if (obj.nodeName == "OBJECT") { 
34715                 storedAltContent = abstractAltContent(obj);
34716                 storedAltContentId = null;
34717             }
34718             else { 
34719                 storedAltContent = obj;
34720                 storedAltContentId = replaceElemIdStr;
34721             }
34722             att.id = EXPRESS_INSTALL_ID;
34723             if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
34724             if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
34725             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
34726             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
34727                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
34728             if (typeof par.flashvars != UNDEF) {
34729                 par.flashvars += "&" + fv;
34730             }
34731             else {
34732                 par.flashvars = fv;
34733             }
34734             
34735             
34736             if (ua.ie && ua.win && obj.readyState != 4) {
34737                 var newObj = createElement("div");
34738                 replaceElemIdStr += "SWFObjectNew";
34739                 newObj.setAttribute("id", replaceElemIdStr);
34740                 obj.parentNode.insertBefore(newObj, obj); 
34741                 obj.style.display = "none";
34742                 (function(){
34743                     if (obj.readyState == 4) {
34744                         obj.parentNode.removeChild(obj);
34745                     }
34746                     else {
34747                         setTimeout(arguments.callee, 10);
34748                     }
34749                 })();
34750             }
34751             createSWF(att, par, replaceElemIdStr);
34752         }
34753     }
34754     
34755     
34756     function displayAltContent(obj) {
34757         if (ua.ie && ua.win && obj.readyState != 4) {
34758             
34759             
34760             var el = createElement("div");
34761             obj.parentNode.insertBefore(el, obj); 
34762             el.parentNode.replaceChild(abstractAltContent(obj), el);
34763             obj.style.display = "none";
34764             (function(){
34765                 if (obj.readyState == 4) {
34766                     obj.parentNode.removeChild(obj);
34767                 }
34768                 else {
34769                     setTimeout(arguments.callee, 10);
34770                 }
34771             })();
34772         }
34773         else {
34774             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
34775         }
34776     } 
34777
34778     function abstractAltContent(obj) {
34779         var ac = createElement("div");
34780         if (ua.win && ua.ie) {
34781             ac.innerHTML = obj.innerHTML;
34782         }
34783         else {
34784             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
34785             if (nestedObj) {
34786                 var c = nestedObj.childNodes;
34787                 if (c) {
34788                     var cl = c.length;
34789                     for (var i = 0; i < cl; i++) {
34790                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
34791                             ac.appendChild(c[i].cloneNode(true));
34792                         }
34793                     }
34794                 }
34795             }
34796         }
34797         return ac;
34798     }
34799     
34800     
34801     function createSWF(attObj, parObj, id) {
34802         var r, el = getElementById(id);
34803         if (ua.wk && ua.wk < 312) { return r; }
34804         if (el) {
34805             if (typeof attObj.id == UNDEF) { 
34806                 attObj.id = id;
34807             }
34808             if (ua.ie && ua.win) { 
34809                 var att = "";
34810                 for (var i in attObj) {
34811                     if (attObj[i] != Object.prototype[i]) { 
34812                         if (i.toLowerCase() == "data") {
34813                             parObj.movie = attObj[i];
34814                         }
34815                         else if (i.toLowerCase() == "styleclass") { 
34816                             att += ' class="' + attObj[i] + '"';
34817                         }
34818                         else if (i.toLowerCase() != "classid") {
34819                             att += ' ' + i + '="' + attObj[i] + '"';
34820                         }
34821                     }
34822                 }
34823                 var par = "";
34824                 for (var j in parObj) {
34825                     if (parObj[j] != Object.prototype[j]) { 
34826                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
34827                     }
34828                 }
34829                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
34830                 objIdArr[objIdArr.length] = attObj.id; 
34831                 r = getElementById(attObj.id);  
34832             }
34833             else { 
34834                 var o = createElement(OBJECT);
34835                 o.setAttribute("type", FLASH_MIME_TYPE);
34836                 for (var m in attObj) {
34837                     if (attObj[m] != Object.prototype[m]) { 
34838                         if (m.toLowerCase() == "styleclass") { 
34839                             o.setAttribute("class", attObj[m]);
34840                         }
34841                         else if (m.toLowerCase() != "classid") { 
34842                             o.setAttribute(m, attObj[m]);
34843                         }
34844                     }
34845                 }
34846                 for (var n in parObj) {
34847                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
34848                         createObjParam(o, n, parObj[n]);
34849                     }
34850                 }
34851                 el.parentNode.replaceChild(o, el);
34852                 r = o;
34853             }
34854         }
34855         return r;
34856     }
34857     
34858     function createObjParam(el, pName, pValue) {
34859         var p = createElement("param");
34860         p.setAttribute("name", pName);  
34861         p.setAttribute("value", pValue);
34862         el.appendChild(p);
34863     }
34864     
34865     
34866     function removeSWF(id) {
34867         var obj = getElementById(id);
34868         if (obj && obj.nodeName == "OBJECT") {
34869             if (ua.ie && ua.win) {
34870                 obj.style.display = "none";
34871                 (function(){
34872                     if (obj.readyState == 4) {
34873                         removeObjectInIE(id);
34874                     }
34875                     else {
34876                         setTimeout(arguments.callee, 10);
34877                     }
34878                 })();
34879             }
34880             else {
34881                 obj.parentNode.removeChild(obj);
34882             }
34883         }
34884     }
34885     
34886     function removeObjectInIE(id) {
34887         var obj = getElementById(id);
34888         if (obj) {
34889             for (var i in obj) {
34890                 if (typeof obj[i] == "function") {
34891                     obj[i] = null;
34892                 }
34893             }
34894             obj.parentNode.removeChild(obj);
34895         }
34896     }
34897     
34898     
34899     function getElementById(id) {
34900         var el = null;
34901         try {
34902             el = doc.getElementById(id);
34903         }
34904         catch (e) {}
34905         return el;
34906     }
34907     
34908     function createElement(el) {
34909         return doc.createElement(el);
34910     }
34911     
34912       
34913     function addListener(target, eventType, fn) {
34914         target.attachEvent(eventType, fn);
34915         listenersArr[listenersArr.length] = [target, eventType, fn];
34916     }
34917     
34918     
34919     function hasPlayerVersion(rv) {
34920         var pv = ua.pv, v = rv.split(".");
34921         v[0] = parseInt(v[0], 10);
34922         v[1] = parseInt(v[1], 10) || 0; 
34923         v[2] = parseInt(v[2], 10) || 0;
34924         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;
34925     }
34926     
34927       
34928     function createCSS(sel, decl, media, newStyle) {
34929         if (ua.ie && ua.mac) { return; }
34930         var h = doc.getElementsByTagName("head")[0];
34931         if (!h) { return; } 
34932         var m = (media && typeof media == "string") ? media : "screen";
34933         if (newStyle) {
34934             dynamicStylesheet = null;
34935             dynamicStylesheetMedia = null;
34936         }
34937         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
34938             
34939             var s = createElement("style");
34940             s.setAttribute("type", "text/css");
34941             s.setAttribute("media", m);
34942             dynamicStylesheet = h.appendChild(s);
34943             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
34944                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
34945             }
34946             dynamicStylesheetMedia = m;
34947         }
34948         
34949         if (ua.ie && ua.win) {
34950             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
34951                 dynamicStylesheet.addRule(sel, decl);
34952             }
34953         }
34954         else {
34955             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
34956                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
34957             }
34958         }
34959     }
34960     
34961     function setVisibility(id, isVisible) {
34962         if (!autoHideShow) { return; }
34963         var v = isVisible ? "visible" : "hidden";
34964         if (isDomLoaded && getElementById(id)) {
34965             getElementById(id).style.visibility = v;
34966         }
34967         else {
34968             createCSS("#" + id, "visibility:" + v);
34969         }
34970     }
34971
34972     
34973     function urlEncodeIfNecessary(s) {
34974         var regex = /[\\\"<>\.;]/;
34975         var hasBadChars = regex.exec(s) != null;
34976         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
34977     }
34978     
34979     
34980     var cleanup = function() {
34981         if (ua.ie && ua.win) {
34982             window.attachEvent("onunload", function() {
34983                 
34984                 var ll = listenersArr.length;
34985                 for (var i = 0; i < ll; i++) {
34986                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
34987                 }
34988                 
34989                 var il = objIdArr.length;
34990                 for (var j = 0; j < il; j++) {
34991                     removeSWF(objIdArr[j]);
34992                 }
34993                 
34994                 for (var k in ua) {
34995                     ua[k] = null;
34996                 }
34997                 ua = null;
34998                 for (var l in swfobject) {
34999                     swfobject[l] = null;
35000                 }
35001                 swfobject = null;
35002             });
35003         }
35004     }();
35005     
35006     return {
35007          
35008         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
35009             if (ua.w3 && objectIdStr && swfVersionStr) {
35010                 var regObj = {};
35011                 regObj.id = objectIdStr;
35012                 regObj.swfVersion = swfVersionStr;
35013                 regObj.expressInstall = xiSwfUrlStr;
35014                 regObj.callbackFn = callbackFn;
35015                 regObjArr[regObjArr.length] = regObj;
35016                 setVisibility(objectIdStr, false);
35017             }
35018             else if (callbackFn) {
35019                 callbackFn({success:false, id:objectIdStr});
35020             }
35021         },
35022         
35023         getObjectById: function(objectIdStr) {
35024             if (ua.w3) {
35025                 return getObjectById(objectIdStr);
35026             }
35027         },
35028         
35029         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
35030             var callbackObj = {success:false, id:replaceElemIdStr};
35031             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
35032                 setVisibility(replaceElemIdStr, false);
35033                 addDomLoadEvent(function() {
35034                     widthStr += ""; 
35035                     heightStr += "";
35036                     var att = {};
35037                     if (attObj && typeof attObj === OBJECT) {
35038                         for (var i in attObj) { 
35039                             att[i] = attObj[i];
35040                         }
35041                     }
35042                     att.data = swfUrlStr;
35043                     att.width = widthStr;
35044                     att.height = heightStr;
35045                     var par = {}; 
35046                     if (parObj && typeof parObj === OBJECT) {
35047                         for (var j in parObj) { 
35048                             par[j] = parObj[j];
35049                         }
35050                     }
35051                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
35052                         for (var k in flashvarsObj) { 
35053                             if (typeof par.flashvars != UNDEF) {
35054                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
35055                             }
35056                             else {
35057                                 par.flashvars = k + "=" + flashvarsObj[k];
35058                             }
35059                         }
35060                     }
35061                     if (hasPlayerVersion(swfVersionStr)) { 
35062                         var obj = createSWF(att, par, replaceElemIdStr);
35063                         if (att.id == replaceElemIdStr) {
35064                             setVisibility(replaceElemIdStr, true);
35065                         }
35066                         callbackObj.success = true;
35067                         callbackObj.ref = obj;
35068                     }
35069                     else if (xiSwfUrlStr && canExpressInstall()) { 
35070                         att.data = xiSwfUrlStr;
35071                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
35072                         return;
35073                     }
35074                     else { 
35075                         setVisibility(replaceElemIdStr, true);
35076                     }
35077                     if (callbackFn) { callbackFn(callbackObj); }
35078                 });
35079             }
35080             else if (callbackFn) { callbackFn(callbackObj); }
35081         },
35082         
35083         switchOffAutoHideShow: function() {
35084             autoHideShow = false;
35085         },
35086         
35087         ua: ua,
35088         
35089         getFlashPlayerVersion: function() {
35090             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
35091         },
35092         
35093         hasFlashPlayerVersion: hasPlayerVersion,
35094         
35095         createSWF: function(attObj, parObj, replaceElemIdStr) {
35096             if (ua.w3) {
35097                 return createSWF(attObj, parObj, replaceElemIdStr);
35098             }
35099             else {
35100                 return undefined;
35101             }
35102         },
35103         
35104         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
35105             if (ua.w3 && canExpressInstall()) {
35106                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
35107             }
35108         },
35109         
35110         removeSWF: function(objElemIdStr) {
35111             if (ua.w3) {
35112                 removeSWF(objElemIdStr);
35113             }
35114         },
35115         
35116         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
35117             if (ua.w3) {
35118                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
35119             }
35120         },
35121         
35122         addDomLoadEvent: addDomLoadEvent,
35123         
35124         addLoadEvent: addLoadEvent,
35125         
35126         getQueryParamValue: function(param) {
35127             var q = doc.location.search || doc.location.hash;
35128             if (q) {
35129                 if (/\?/.test(q)) { q = q.split("?")[1]; } 
35130                 if (param == null) {
35131                     return urlEncodeIfNecessary(q);
35132                 }
35133                 var pairs = q.split("&");
35134                 for (var i = 0; i < pairs.length; i++) {
35135                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
35136                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
35137                     }
35138                 }
35139             }
35140             return "";
35141         },
35142         
35143         
35144         expressInstallCallback: function() {
35145             if (isExpressInstallActive) {
35146                 var obj = getElementById(EXPRESS_INSTALL_ID);
35147                 if (obj && storedAltContent) {
35148                     obj.parentNode.replaceChild(storedAltContent, obj);
35149                     if (storedAltContentId) {
35150                         setVisibility(storedAltContentId, true);
35151                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
35152                     }
35153                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
35154                 }
35155                 isExpressInstallActive = false;
35156             } 
35157         }
35158     };
35159 }();
35160
35161 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
35162     
35163     flashVersion : '9.0.115',
35164
35165     
35166     backgroundColor: '#ffffff',
35167
35168     
35169     wmode: 'opaque',
35170
35171     
35172     flashVars: undefined,
35173
35174     
35175     flashParams: undefined,
35176
35177     
35178     url: undefined,
35179     swfId : undefined,
35180     swfWidth: '100%',
35181     swfHeight: '100%',
35182
35183     
35184     expressInstall: false,
35185
35186     initComponent : function(){
35187         Ext.FlashComponent.superclass.initComponent.call(this);
35188
35189         this.addEvents(
35190             
35191             'initialize'
35192         );
35193     },
35194
35195     onRender : function(){
35196         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
35197
35198         var params = Ext.apply({
35199             allowScriptAccess: 'always',
35200             bgcolor: this.backgroundColor,
35201             wmode: this.wmode
35202         }, this.flashParams), vars = Ext.apply({
35203             allowedDomain: document.location.hostname,
35204             YUISwfId: this.getId(),
35205             YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
35206         }, this.flashVars);
35207
35208         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
35209             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
35210
35211         this.swf = Ext.getDom(this.id);
35212         this.el = Ext.get(this.swf);
35213     },
35214
35215     getSwfId : function(){
35216         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
35217     },
35218
35219     getId : function(){
35220         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
35221     },
35222
35223     onFlashEvent : function(e){
35224         switch(e.type){
35225             case "swfReady":
35226                 this.initSwf();
35227                 return;
35228             case "log":
35229                 return;
35230         }
35231         e.component = this;
35232         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
35233     },
35234
35235     initSwf : function(){
35236         this.onSwfReady(!!this.isInitialized);
35237         this.isInitialized = true;
35238         this.fireEvent('initialize', this);
35239     },
35240
35241     beforeDestroy: function(){
35242         if(this.rendered){
35243             swfobject.removeSWF(this.swf.id);
35244         }
35245         Ext.FlashComponent.superclass.beforeDestroy.call(this);
35246     },
35247
35248     onSwfReady : Ext.emptyFn
35249 });
35250
35251
35252 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
35253
35254 Ext.reg('flash', Ext.FlashComponent);
35255 Ext.FlashEventProxy = {
35256     onEvent : function(id, e){
35257         var fp = Ext.getCmp(id);
35258         if(fp){
35259             fp.onFlashEvent(e);
35260         }else{
35261             arguments.callee.defer(10, this, [id, e]);
35262         }
35263     }
35264 };
35265
35266  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
35267     refreshBuffer: 100,
35268
35269     
35270
35271     
35272     chartStyle: {
35273         padding: 10,
35274         animationEnabled: true,
35275         font: {
35276             name: 'Tahoma',
35277             color: 0x444444,
35278             size: 11
35279         },
35280         dataTip: {
35281             padding: 5,
35282             border: {
35283                 color: 0x99bbe8,
35284                 size:1
35285             },
35286             background: {
35287                 color: 0xDAE7F6,
35288                 alpha: .9
35289             },
35290             font: {
35291                 name: 'Tahoma',
35292                 color: 0x15428B,
35293                 size: 10,
35294                 bold: true
35295             }
35296         }
35297     },
35298
35299     
35300
35301     
35302     extraStyle: null,
35303
35304     
35305     seriesStyles: null,
35306
35307     
35308     disableCaching: Ext.isIE || Ext.isOpera,
35309     disableCacheParam: '_dc',
35310
35311     initComponent : function(){
35312         Ext.chart.Chart.superclass.initComponent.call(this);
35313         if(!this.url){
35314             this.url = Ext.chart.Chart.CHART_URL;
35315         }
35316         if(this.disableCaching){
35317             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
35318         }
35319         this.addEvents(
35320             'itemmouseover',
35321             'itemmouseout',
35322             'itemclick',
35323             'itemdoubleclick',
35324             'itemdragstart',
35325             'itemdrag',
35326             'itemdragend',
35327             
35328             'beforerefresh',
35329             
35330             'refresh'
35331         );
35332         this.store = Ext.StoreMgr.lookup(this.store);
35333     },
35334
35335     
35336      setStyle: function(name, value){
35337          this.swf.setStyle(name, Ext.encode(value));
35338      },
35339
35340     
35341     setStyles: function(styles){
35342         this.swf.setStyles(Ext.encode(styles));
35343     },
35344
35345     
35346     setSeriesStyles: function(styles){
35347         this.seriesStyles = styles;
35348         var s = [];
35349         Ext.each(styles, function(style){
35350             s.push(Ext.encode(style));
35351         });
35352         this.swf.setSeriesStyles(s);
35353     },
35354
35355     setCategoryNames : function(names){
35356         this.swf.setCategoryNames(names);
35357     },
35358
35359     setLegendRenderer : function(fn, scope){
35360         var chart = this;
35361         scope = scope || chart;
35362         chart.removeFnProxy(chart.legendFnName);
35363         chart.legendFnName = chart.createFnProxy(function(name){
35364             return fn.call(scope, name);
35365         });
35366         chart.swf.setLegendLabelFunction(chart.legendFnName);
35367     },
35368
35369     setTipRenderer : function(fn, scope){
35370         var chart = this;
35371         scope = scope || chart;
35372         chart.removeFnProxy(chart.tipFnName);
35373         chart.tipFnName = chart.createFnProxy(function(item, index, series){
35374             var record = chart.store.getAt(index);
35375             return fn.call(scope, chart, record, index, series);
35376         });
35377         chart.swf.setDataTipFunction(chart.tipFnName);
35378     },
35379
35380     setSeries : function(series){
35381         this.series = series;
35382         this.refresh();
35383     },
35384
35385     
35386     bindStore : function(store, initial){
35387         if(!initial && this.store){
35388             if(store !== this.store && this.store.autoDestroy){
35389                 this.store.destroy();
35390             }else{
35391                 this.store.un("datachanged", this.refresh, this);
35392                 this.store.un("add", this.delayRefresh, this);
35393                 this.store.un("remove", this.delayRefresh, this);
35394                 this.store.un("update", this.delayRefresh, this);
35395                 this.store.un("clear", this.refresh, this);
35396             }
35397         }
35398         if(store){
35399             store = Ext.StoreMgr.lookup(store);
35400             store.on({
35401                 scope: this,
35402                 datachanged: this.refresh,
35403                 add: this.delayRefresh,
35404                 remove: this.delayRefresh,
35405                 update: this.delayRefresh,
35406                 clear: this.refresh
35407             });
35408         }
35409         this.store = store;
35410         if(store && !initial){
35411             this.refresh();
35412         }
35413     },
35414
35415     onSwfReady : function(isReset){
35416         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
35417         var ref;
35418         this.swf.setType(this.type);
35419
35420         if(this.chartStyle){
35421             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
35422         }
35423
35424         if(this.categoryNames){
35425             this.setCategoryNames(this.categoryNames);
35426         }
35427
35428         if(this.tipRenderer){
35429             ref = this.getFunctionRef(this.tipRenderer);
35430             this.setTipRenderer(ref.fn, ref.scope);
35431         }
35432         if(this.legendRenderer){
35433             ref = this.getFunctionRef(this.legendRenderer);
35434             this.setLegendRenderer(ref.fn, ref.scope);
35435         }
35436         if(!isReset){
35437             this.bindStore(this.store, true);
35438         }
35439         this.refresh.defer(10, this);
35440     },
35441
35442     delayRefresh : function(){
35443         if(!this.refreshTask){
35444             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
35445         }
35446         this.refreshTask.delay(this.refreshBuffer);
35447     },
35448
35449     refresh : function(){
35450         if(this.fireEvent('beforerefresh', this) !== false){
35451             var styleChanged = false;
35452             
35453             var data = [], rs = this.store.data.items;
35454             for(var j = 0, len = rs.length; j < len; j++){
35455                 data[j] = rs[j].data;
35456             }
35457             
35458             
35459             var dataProvider = [];
35460             var seriesCount = 0;
35461             var currentSeries = null;
35462             var i = 0;
35463             if(this.series){
35464                 seriesCount = this.series.length;
35465                 for(i = 0; i < seriesCount; i++){
35466                     currentSeries = this.series[i];
35467                     var clonedSeries = {};
35468                     for(var prop in currentSeries){
35469                         if(prop == "style" && currentSeries.style !== null){
35470                             clonedSeries.style = Ext.encode(currentSeries.style);
35471                             styleChanged = true;
35472                             
35473                             
35474                             
35475                             
35476                         } else{
35477                             clonedSeries[prop] = currentSeries[prop];
35478                         }
35479                     }
35480                     dataProvider.push(clonedSeries);
35481                 }
35482             }
35483
35484             if(seriesCount > 0){
35485                 for(i = 0; i < seriesCount; i++){
35486                     currentSeries = dataProvider[i];
35487                     if(!currentSeries.type){
35488                         currentSeries.type = this.type;
35489                     }
35490                     currentSeries.dataProvider = data;
35491                 }
35492             } else{
35493                 dataProvider.push({type: this.type, dataProvider: data});
35494             }
35495             this.swf.setDataProvider(dataProvider);
35496             if(this.seriesStyles){
35497                 this.setSeriesStyles(this.seriesStyles);
35498             }
35499             this.fireEvent('refresh', this);
35500         }
35501     },
35502
35503     
35504     createFnProxy : function(fn){
35505         var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
35506         Ext.chart.Chart.proxyFunction[fnName] = fn;
35507         return 'Ext.chart.Chart.proxyFunction.' + fnName;
35508     },
35509
35510     
35511     removeFnProxy : function(fn){
35512         if(!Ext.isEmpty(fn)){
35513             fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
35514             delete Ext.chart.Chart.proxyFunction[fn];
35515         }
35516     },
35517
35518     
35519     getFunctionRef : function(val){
35520         if(Ext.isFunction(val)){
35521             return {
35522                 fn: val,
35523                 scope: this
35524             };
35525         }else{
35526             return {
35527                 fn: val.fn,
35528                 scope: val.scope || this
35529             }
35530         }
35531     },
35532
35533     
35534     onDestroy: function(){
35535         if (this.refreshTask && this.refreshTask.cancel){
35536             this.refreshTask.cancel();
35537         }
35538         Ext.chart.Chart.superclass.onDestroy.call(this);
35539         this.bindStore(null);
35540         this.removeFnProxy(this.tipFnName);
35541         this.removeFnProxy(this.legendFnName);
35542     }
35543 });
35544 Ext.reg('chart', Ext.chart.Chart);
35545 Ext.chart.Chart.PROXY_FN_ID = 0;
35546 Ext.chart.Chart.proxyFunction = {};
35547
35548
35549 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.0/build/charts/assets/charts.swf';
35550
35551
35552 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
35553     type: 'pie',
35554
35555     onSwfReady : function(isReset){
35556         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
35557
35558         this.setDataField(this.dataField);
35559         this.setCategoryField(this.categoryField);
35560     },
35561
35562     setDataField : function(field){
35563         this.dataField = field;
35564         this.swf.setDataField(field);
35565     },
35566
35567     setCategoryField : function(field){
35568         this.categoryField = field;
35569         this.swf.setCategoryField(field);
35570     }
35571 });
35572 Ext.reg('piechart', Ext.chart.PieChart);
35573
35574
35575 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
35576     onSwfReady : function(isReset){
35577         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
35578         this.labelFn = [];
35579         if(this.xField){
35580             this.setXField(this.xField);
35581         }
35582         if(this.yField){
35583             this.setYField(this.yField);
35584         }
35585         if(this.xAxis){
35586             this.setXAxis(this.xAxis);
35587         }
35588         if(this.xAxes){
35589             this.setXAxes(this.xAxes);
35590         }
35591         if(this.yAxis){
35592             this.setYAxis(this.yAxis);
35593         }
35594         if(this.yAxes){
35595             this.setYAxes(this.yAxes);
35596         }
35597         if(Ext.isDefined(this.constrainViewport)){
35598             this.swf.setConstrainViewport(this.constrainViewport);
35599         }
35600     },
35601
35602     setXField : function(value){
35603         this.xField = value;
35604         this.swf.setHorizontalField(value);
35605     },
35606
35607     setYField : function(value){
35608         this.yField = value;
35609         this.swf.setVerticalField(value);
35610     },
35611
35612     setXAxis : function(value){
35613         this.xAxis = this.createAxis('xAxis', value);
35614         this.swf.setHorizontalAxis(this.xAxis);
35615     },
35616
35617     setXAxes : function(value){
35618         var axis;
35619         for(var i = 0; i < value.length; i++) {
35620             axis = this.createAxis('xAxis' + i, value[i]);
35621             this.swf.setHorizontalAxis(axis);
35622         }
35623     },
35624
35625     setYAxis : function(value){
35626         this.yAxis = this.createAxis('yAxis', value);
35627         this.swf.setVerticalAxis(this.yAxis);
35628     },
35629
35630     setYAxes : function(value){
35631         var axis;
35632         for(var i = 0; i < value.length; i++) {
35633             axis = this.createAxis('yAxis' + i, value[i]);
35634             this.swf.setVerticalAxis(axis);
35635         }
35636     },
35637
35638     createAxis : function(axis, value){
35639         var o = Ext.apply({}, value),
35640             ref,
35641             old;
35642
35643         if(this[axis]){
35644             old = this[axis].labelFunction;
35645             this.removeFnProxy(old);
35646             this.labelFn.remove(old);
35647         }
35648         if(o.labelRenderer){
35649             ref = this.getFunctionRef(o.labelRenderer);
35650             o.labelFunction = this.createFnProxy(function(v){
35651                 return ref.fn.call(ref.scope, v);
35652             });
35653             delete o.labelRenderer;
35654             this.labelFn.push(o.labelFunction);
35655         }
35656         if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
35657             o.position = 'bottom';
35658         }
35659         return o;
35660     },
35661
35662     onDestroy : function(){
35663         Ext.chart.CartesianChart.superclass.onDestroy.call(this);
35664         Ext.each(this.labelFn, function(fn){
35665             this.removeFnProxy(fn);
35666         }, this);
35667     }
35668 });
35669 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
35670
35671
35672 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
35673     type: 'line'
35674 });
35675 Ext.reg('linechart', Ext.chart.LineChart);
35676
35677
35678 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
35679     type: 'column'
35680 });
35681 Ext.reg('columnchart', Ext.chart.ColumnChart);
35682
35683
35684 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
35685     type: 'stackcolumn'
35686 });
35687 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
35688
35689
35690 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
35691     type: 'bar'
35692 });
35693 Ext.reg('barchart', Ext.chart.BarChart);
35694
35695
35696 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
35697     type: 'stackbar'
35698 });
35699 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
35700
35701
35702
35703
35704 Ext.chart.Axis = function(config){
35705     Ext.apply(this, config);
35706 };
35707
35708 Ext.chart.Axis.prototype =
35709 {
35710     
35711     type: null,
35712
35713     
35714     orientation: "horizontal",
35715
35716     
35717     reverse: false,
35718
35719     
35720     labelFunction: null,
35721
35722     
35723     hideOverlappingLabels: true,
35724
35725     
35726     labelSpacing: 2
35727 };
35728
35729
35730 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
35731     type: "numeric",
35732
35733     
35734     minimum: NaN,
35735
35736     
35737     maximum: NaN,
35738
35739     
35740     majorUnit: NaN,
35741
35742     
35743     minorUnit: NaN,
35744
35745     
35746     snapToUnits: true,
35747
35748     
35749     alwaysShowZero: true,
35750
35751     
35752     scale: "linear",
35753
35754     
35755     roundMajorUnit: true,
35756
35757     
35758     calculateByLabelSize: true,
35759
35760     
35761     position: 'left',
35762
35763     
35764     adjustMaximumByMajorUnit: true,
35765
35766     
35767     adjustMinimumByMajorUnit: true
35768
35769 });
35770
35771
35772 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
35773     type: "time",
35774
35775     
35776     minimum: null,
35777
35778     
35779     maximum: null,
35780
35781     
35782     majorUnit: NaN,
35783
35784     
35785     majorTimeUnit: null,
35786
35787     
35788     minorUnit: NaN,
35789
35790     
35791     minorTimeUnit: null,
35792
35793     
35794     snapToUnits: true,
35795
35796     
35797     stackingEnabled: false,
35798
35799     
35800     calculateByLabelSize: true
35801
35802 });
35803
35804
35805 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
35806     type: "category",
35807
35808     
35809     categoryNames: null,
35810
35811     
35812     calculateCategoryCount: false
35813
35814 });
35815
35816
35817 Ext.chart.Series = function(config) { Ext.apply(this, config); };
35818
35819 Ext.chart.Series.prototype =
35820 {
35821     
35822     type: null,
35823
35824     
35825     displayName: null
35826 };
35827
35828
35829 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
35830     
35831     xField: null,
35832
35833     
35834     yField: null,
35835
35836     
35837     showInLegend: true,
35838
35839     
35840     axis: 'primary'
35841 });
35842
35843
35844 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
35845     type: "column"
35846 });
35847
35848
35849 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
35850     type: "line"
35851 });
35852
35853
35854 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
35855     type: "bar"
35856 });
35857
35858
35859
35860 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
35861     type: "pie",
35862     dataField: null,
35863     categoryField: null
35864 });
35865 Ext.menu.Menu = Ext.extend(Ext.Container, {
35866     
35867     
35868     
35869     minWidth : 120,
35870     
35871     shadow : 'sides',
35872     
35873     subMenuAlign : 'tl-tr?',
35874     
35875     defaultAlign : 'tl-bl?',
35876     
35877     allowOtherMenus : false,
35878     
35879     ignoreParentClicks : false,
35880     
35881     enableScrolling : true,
35882     
35883     maxHeight : null,
35884     
35885     scrollIncrement : 24,
35886     
35887     showSeparator : true,
35888     
35889     defaultOffsets : [0, 0],
35890
35891     
35892     plain : false,
35893
35894     
35895     floating : true,
35896
35897
35898     
35899     zIndex: 15000,
35900
35901     
35902     hidden : true,
35903
35904     
35905     layout : 'menu',
35906     hideMode : 'offsets',    
35907     scrollerHeight : 8,
35908     autoLayout : true,       
35909     defaultType : 'menuitem',
35910     bufferResize : false,
35911
35912     initComponent : function(){
35913         if(Ext.isArray(this.initialConfig)){
35914             Ext.apply(this, {items:this.initialConfig});
35915         }
35916         this.addEvents(
35917             
35918             'click',
35919             
35920             'mouseover',
35921             
35922             'mouseout',
35923             
35924             'itemclick'
35925         );
35926         Ext.menu.MenuMgr.register(this);
35927         if(this.floating){
35928             Ext.EventManager.onWindowResize(this.hide, this);
35929         }else{
35930             if(this.initialConfig.hidden !== false){
35931                 this.hidden = false;
35932             }
35933             this.internalDefaults = {hideOnClick: false};
35934         }
35935         Ext.menu.Menu.superclass.initComponent.call(this);
35936         if(this.autoLayout){
35937             var fn = this.doLayout.createDelegate(this, []);
35938             this.on({
35939                 add: fn,
35940                 remove: fn
35941             });
35942         }
35943     },
35944
35945     
35946     getLayoutTarget : function() {
35947         return this.ul;
35948     },
35949
35950     
35951     onRender : function(ct, position){
35952         if(!ct){
35953             ct = Ext.getBody();
35954         }
35955
35956         var dh = {
35957             id: this.getId(),
35958             cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
35959             style: this.style,
35960             cn: [
35961                 {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
35962                 {tag: 'ul', cls: 'x-menu-list'}
35963             ]
35964         };
35965         if(this.floating){
35966             this.el = new Ext.Layer({
35967                 shadow: this.shadow,
35968                 dh: dh,
35969                 constrain: false,
35970                 parentEl: ct,
35971                 zindex: this.zIndex
35972             });
35973         }else{
35974             this.el = ct.createChild(dh);
35975         }
35976         Ext.menu.Menu.superclass.onRender.call(this, ct, position);
35977
35978         if(!this.keyNav){
35979             this.keyNav = new Ext.menu.MenuNav(this);
35980         }
35981         
35982         this.focusEl = this.el.child('a.x-menu-focus');
35983         this.ul = this.el.child('ul.x-menu-list');
35984         this.mon(this.ul, {
35985             scope: this,
35986             click: this.onClick,
35987             mouseover: this.onMouseOver,
35988             mouseout: this.onMouseOut
35989         });
35990         if(this.enableScrolling){
35991             this.mon(this.el, {
35992                 scope: this,
35993                 delegate: '.x-menu-scroller',
35994                 click: this.onScroll,
35995                 mouseover: this.deactivateActive
35996             });
35997         }
35998     },
35999
36000     
36001     findTargetItem : function(e){
36002         var t = e.getTarget('.x-menu-list-item', this.ul, true);
36003         if(t && t.menuItemId){
36004             return this.items.get(t.menuItemId);
36005         }
36006     },
36007
36008     
36009     onClick : function(e){
36010         var t = this.findTargetItem(e);
36011         if(t){
36012             if(t.isFormField){
36013                 this.setActiveItem(t);
36014             }else if(t instanceof Ext.menu.BaseItem){
36015                 if(t.menu && this.ignoreParentClicks){
36016                     t.expandMenu();
36017                     e.preventDefault();
36018                 }else if(t.onClick){
36019                     t.onClick(e);
36020                     this.fireEvent('click', this, t, e);
36021                 }
36022             }
36023         }
36024     },
36025
36026     
36027     setActiveItem : function(item, autoExpand){
36028         if(item != this.activeItem){
36029             this.deactivateActive();
36030             if((this.activeItem = item).isFormField){
36031                 item.focus();
36032             }else{
36033                 item.activate(autoExpand);
36034             }
36035         }else if(autoExpand){
36036             item.expandMenu();
36037         }
36038     },
36039
36040     deactivateActive : function(){
36041         var a = this.activeItem;
36042         if(a){
36043             if(a.isFormField){
36044                 
36045                 if(a.collapse){
36046                     a.collapse();
36047                 }
36048             }else{
36049                 a.deactivate();
36050             }
36051             delete this.activeItem;
36052         }
36053     },
36054
36055     
36056     tryActivate : function(start, step){
36057         var items = this.items;
36058         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
36059             var item = items.get(i);
36060             if(!item.disabled && (item.canActivate || item.isFormField)){
36061                 this.setActiveItem(item, false);
36062                 return item;
36063             }
36064         }
36065         return false;
36066     },
36067
36068     
36069     onMouseOver : function(e){
36070         var t = this.findTargetItem(e);
36071         if(t){
36072             if(t.canActivate && !t.disabled){
36073                 this.setActiveItem(t, true);
36074             }
36075         }
36076         this.over = true;
36077         this.fireEvent('mouseover', this, e, t);
36078     },
36079
36080     
36081     onMouseOut : function(e){
36082         var t = this.findTargetItem(e);
36083         if(t){
36084             if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
36085                 this.activeItem.deactivate();
36086                 delete this.activeItem;
36087             }
36088         }
36089         this.over = false;
36090         this.fireEvent('mouseout', this, e, t);
36091     },
36092
36093     
36094     onScroll : function(e, t){
36095         if(e){
36096             e.stopEvent();
36097         }
36098         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
36099         ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
36100         if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
36101            this.onScrollerOut(null, t);
36102         }
36103     },
36104
36105     
36106     onScrollerIn : function(e, t){
36107         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
36108         if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
36109             Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
36110         }
36111     },
36112
36113     
36114     onScrollerOut : function(e, t){
36115         Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
36116     },
36117
36118     
36119     show : function(el, pos, parentMenu){
36120         if(this.floating){
36121             this.parentMenu = parentMenu;
36122             if(!this.el){
36123                 this.render();
36124                 this.doLayout(false, true);
36125             }
36126             this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
36127         }else{
36128             Ext.menu.Menu.superclass.show.call(this);
36129         }
36130     },
36131
36132     
36133     showAt : function(xy, parentMenu){
36134         if(this.fireEvent('beforeshow', this) !== false){
36135             this.parentMenu = parentMenu;
36136             if(!this.el){
36137                 this.render();
36138             }
36139             if(this.enableScrolling){
36140                 
36141                 this.el.setXY(xy);
36142                 
36143                 xy[1] = this.constrainScroll(xy[1]);
36144                 xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
36145             }else{
36146                 
36147                 xy = this.el.adjustForConstraints(xy);
36148             }
36149             this.el.setXY(xy);
36150             this.el.show();
36151             Ext.menu.Menu.superclass.onShow.call(this);
36152             if(Ext.isIE){
36153                 
36154                 this.fireEvent('autosize', this);
36155                 if(!Ext.isIE8){
36156                     this.el.repaint();
36157                 }
36158             }
36159             this.hidden = false;
36160             this.focus();
36161             this.fireEvent('show', this);
36162         }
36163     },
36164
36165     constrainScroll : function(y){
36166         var max, full = this.ul.setHeight('auto').getHeight(),
36167             returnY = y, normalY, parentEl, scrollTop, viewHeight;
36168         if(this.floating){
36169             parentEl = Ext.fly(this.el.dom.parentNode);
36170             scrollTop = parentEl.getScroll().top;
36171             viewHeight = parentEl.getViewSize().height;
36172             
36173             
36174             normalY = y - scrollTop;
36175             max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
36176             if(full > viewHeight) {
36177                 max = viewHeight;
36178                 
36179                 returnY = y - normalY;
36180             } else if(max < full) {
36181                 returnY = y - (full - max);
36182                 max = full;
36183             }
36184         }else{
36185             max = this.getHeight();
36186         }
36187         
36188         if (this.maxHeight){
36189             max = Math.min(this.maxHeight, max);
36190         }
36191         if(full > max && max > 0){
36192             this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
36193             this.ul.setHeight(this.activeMax);
36194             this.createScrollers();
36195             this.el.select('.x-menu-scroller').setDisplayed('');
36196         }else{
36197             this.ul.setHeight(full);
36198             this.el.select('.x-menu-scroller').setDisplayed('none');
36199         }
36200         this.ul.dom.scrollTop = 0;
36201         return returnY;
36202     },
36203
36204     createScrollers : function(){
36205         if(!this.scroller){
36206             this.scroller = {
36207                 pos: 0,
36208                 top: this.el.insertFirst({
36209                     tag: 'div',
36210                     cls: 'x-menu-scroller x-menu-scroller-top',
36211                     html: '&#160;'
36212                 }),
36213                 bottom: this.el.createChild({
36214                     tag: 'div',
36215                     cls: 'x-menu-scroller x-menu-scroller-bottom',
36216                     html: '&#160;'
36217                 })
36218             };
36219             this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
36220             this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
36221                 listeners: {
36222                     click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
36223                 }
36224             });
36225             this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
36226             this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
36227                 listeners: {
36228                     click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
36229                 }
36230             });
36231         }
36232     },
36233
36234     onLayout : function(){
36235         if(this.isVisible()){
36236             if(this.enableScrolling){
36237                 this.constrainScroll(this.el.getTop());
36238             }
36239             if(this.floating){
36240                 this.el.sync();
36241             }
36242         }
36243     },
36244
36245     focus : function(){
36246         if(!this.hidden){
36247             this.doFocus.defer(50, this);
36248         }
36249     },
36250
36251     doFocus : function(){
36252         if(!this.hidden){
36253             this.focusEl.focus();
36254         }
36255     },
36256
36257     
36258     hide : function(deep){
36259         if (!this.isDestroyed) {
36260             this.deepHide = deep;
36261             Ext.menu.Menu.superclass.hide.call(this);
36262             delete this.deepHide;
36263         }
36264     },
36265
36266     
36267     onHide : function(){
36268         Ext.menu.Menu.superclass.onHide.call(this);
36269         this.deactivateActive();
36270         if(this.el && this.floating){
36271             this.el.hide();
36272         }
36273         var pm = this.parentMenu;
36274         if(this.deepHide === true && pm){
36275             if(pm.floating){
36276                 pm.hide(true);
36277             }else{
36278                 pm.deactivateActive();
36279             }
36280         }
36281     },
36282
36283     
36284     lookupComponent : function(c){
36285          if(Ext.isString(c)){
36286             c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
36287              this.applyDefaults(c);
36288          }else{
36289             if(Ext.isObject(c)){
36290                 c = this.getMenuItem(c);
36291             }else if(c.tagName || c.el){ 
36292                 c = new Ext.BoxComponent({
36293                     el: c
36294                 });
36295             }
36296          }
36297          return c;
36298     },
36299
36300     applyDefaults : function(c){
36301         if(!Ext.isString(c)){
36302             c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
36303             var d = this.internalDefaults;
36304             if(d){
36305                 if(c.events){
36306                     Ext.applyIf(c.initialConfig, d);
36307                     Ext.apply(c, d);
36308                 }else{
36309                     Ext.applyIf(c, d);
36310                 }
36311             }
36312         }
36313         return c;
36314     },
36315
36316     
36317     getMenuItem : function(config){
36318        if(!config.isXType){
36319             if(!config.xtype && Ext.isBoolean(config.checked)){
36320                 return new Ext.menu.CheckItem(config)
36321             }
36322             return Ext.create(config, this.defaultType);
36323         }
36324         return config;
36325     },
36326
36327     
36328     addSeparator : function(){
36329         return this.add(new Ext.menu.Separator());
36330     },
36331
36332     
36333     addElement : function(el){
36334         return this.add(new Ext.menu.BaseItem({
36335             el: el
36336         }));
36337     },
36338
36339     
36340     addItem : function(item){
36341         return this.add(item);
36342     },
36343
36344     
36345     addMenuItem : function(config){
36346         return this.add(this.getMenuItem(config));
36347     },
36348
36349     
36350     addText : function(text){
36351         return this.add(new Ext.menu.TextItem(text));
36352     },
36353
36354     
36355     onDestroy : function(){
36356         Ext.EventManager.removeResizeListener(this.hide, this);
36357         var pm = this.parentMenu;
36358         if(pm && pm.activeChild == this){
36359             delete pm.activeChild;
36360         }
36361         delete this.parentMenu;
36362         Ext.menu.Menu.superclass.onDestroy.call(this);
36363         Ext.menu.MenuMgr.unregister(this);
36364         if(this.keyNav) {
36365             this.keyNav.disable();
36366         }
36367         var s = this.scroller;
36368         if(s){
36369             Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
36370         }
36371         Ext.destroy(
36372             this.el,
36373             this.focusEl,
36374             this.ul
36375         );
36376     }
36377 });
36378
36379 Ext.reg('menu', Ext.menu.Menu);
36380
36381
36382 Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
36383     function up(e, m){
36384         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
36385             m.tryActivate(m.items.length-1, -1);
36386         }
36387     }
36388     function down(e, m){
36389         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
36390             m.tryActivate(0, 1);
36391         }
36392     }
36393     return {
36394         constructor : function(menu){
36395             Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
36396             this.scope = this.menu = menu;
36397         },
36398
36399         doRelay : function(e, h){
36400             var k = e.getKey();
36401
36402             if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
36403                 return false;
36404             }
36405             if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
36406                 this.menu.tryActivate(0, 1);
36407                 return false;
36408             }
36409             return h.call(this.scope || this, e, this.menu);
36410         },
36411
36412         tab: function(e, m) {
36413             e.stopEvent();
36414             if (e.shiftKey) {
36415                 up(e, m);
36416             } else {
36417                 down(e, m);
36418             }
36419         },
36420
36421         up : up,
36422
36423         down : down,
36424
36425         right : function(e, m){
36426             if(m.activeItem){
36427                 m.activeItem.expandMenu(true);
36428             }
36429         },
36430
36431         left : function(e, m){
36432             m.hide();
36433             if(m.parentMenu && m.parentMenu.activeItem){
36434                 m.parentMenu.activeItem.activate();
36435             }
36436         },
36437
36438         enter : function(e, m){
36439             if(m.activeItem){
36440                 e.stopPropagation();
36441                 m.activeItem.onClick(e);
36442                 m.fireEvent('click', this, m.activeItem);
36443                 return true;
36444             }
36445         }
36446     };
36447 }());
36448
36449 Ext.menu.MenuMgr = function(){
36450    var menus, active, groups = {}, attached = false, lastShow = new Date();
36451
36452    
36453    function init(){
36454        menus = {};
36455        active = new Ext.util.MixedCollection();
36456        Ext.getDoc().addKeyListener(27, function(){
36457            if(active.length > 0){
36458                hideAll();
36459            }
36460        });
36461    }
36462
36463    
36464    function hideAll(){
36465        if(active && active.length > 0){
36466            var c = active.clone();
36467            c.each(function(m){
36468                m.hide();
36469            });
36470            return true;
36471        }
36472        return false;
36473    }
36474
36475    
36476    function onHide(m){
36477        active.remove(m);
36478        if(active.length < 1){
36479            Ext.getDoc().un("mousedown", onMouseDown);
36480            attached = false;
36481        }
36482    }
36483
36484    
36485    function onShow(m){
36486        var last = active.last();
36487        lastShow = new Date();
36488        active.add(m);
36489        if(!attached){
36490            Ext.getDoc().on("mousedown", onMouseDown);
36491            attached = true;
36492        }
36493        if(m.parentMenu){
36494           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
36495           m.parentMenu.activeChild = m;
36496        }else if(last && !last.isDestroyed && last.isVisible()){
36497           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
36498        }
36499    }
36500
36501    
36502    function onBeforeHide(m){
36503        if(m.activeChild){
36504            m.activeChild.hide();
36505        }
36506        if(m.autoHideTimer){
36507            clearTimeout(m.autoHideTimer);
36508            delete m.autoHideTimer;
36509        }
36510    }
36511
36512    
36513    function onBeforeShow(m){
36514        var pm = m.parentMenu;
36515        if(!pm && !m.allowOtherMenus){
36516            hideAll();
36517        }else if(pm && pm.activeChild){
36518            pm.activeChild.hide();
36519        }
36520    }
36521
36522    
36523    function onMouseDown(e){
36524        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
36525            hideAll();
36526        }
36527    }
36528
36529    
36530    function onBeforeCheck(mi, state){
36531        if(state){
36532            var g = groups[mi.group];
36533            for(var i = 0, l = g.length; i < l; i++){
36534                if(g[i] != mi){
36535                    g[i].setChecked(false);
36536                }
36537            }
36538        }
36539    }
36540
36541    return {
36542
36543        
36544        hideAll : function(){
36545             return hideAll();
36546        },
36547
36548        
36549        register : function(menu){
36550            if(!menus){
36551                init();
36552            }
36553            menus[menu.id] = menu;
36554            menu.on({
36555                beforehide: onBeforeHide,
36556                hide: onHide,
36557                beforeshow: onBeforeShow,
36558                show: onShow
36559            });
36560        },
36561
36562         
36563        get : function(menu){
36564            if(typeof menu == "string"){ 
36565                if(!menus){  
36566                    return null;
36567                }
36568                return menus[menu];
36569            }else if(menu.events){  
36570                return menu;
36571            }else if(typeof menu.length == 'number'){ 
36572                return new Ext.menu.Menu({items:menu});
36573            }else{ 
36574                return Ext.create(menu, 'menu');
36575            }
36576        },
36577
36578        
36579        unregister : function(menu){
36580            delete menus[menu.id];
36581            menu.un("beforehide", onBeforeHide);
36582            menu.un("hide", onHide);
36583            menu.un("beforeshow", onBeforeShow);
36584            menu.un("show", onShow);
36585        },
36586
36587        
36588        registerCheckable : function(menuItem){
36589            var g = menuItem.group;
36590            if(g){
36591                if(!groups[g]){
36592                    groups[g] = [];
36593                }
36594                groups[g].push(menuItem);
36595                menuItem.on("beforecheckchange", onBeforeCheck);
36596            }
36597        },
36598
36599        
36600        unregisterCheckable : function(menuItem){
36601            var g = menuItem.group;
36602            if(g){
36603                groups[g].remove(menuItem);
36604                menuItem.un("beforecheckchange", onBeforeCheck);
36605            }
36606        },
36607
36608        getCheckedItem : function(groupId){
36609            var g = groups[groupId];
36610            if(g){
36611                for(var i = 0, l = g.length; i < l; i++){
36612                    if(g[i].checked){
36613                        return g[i];
36614                    }
36615                }
36616            }
36617            return null;
36618        },
36619
36620        setCheckedItem : function(groupId, itemId){
36621            var g = groups[groupId];
36622            if(g){
36623                for(var i = 0, l = g.length; i < l; i++){
36624                    if(g[i].id == itemId){
36625                        g[i].setChecked(true);
36626                    }
36627                }
36628            }
36629            return null;
36630        }
36631    };
36632 }();
36633
36634 Ext.menu.BaseItem = Ext.extend(Ext.Component, {
36635     
36636     
36637     
36638     
36639     canActivate : false,
36640     
36641     activeClass : "x-menu-item-active",
36642     
36643     hideOnClick : true,
36644     
36645     clickHideDelay : 1,
36646
36647     
36648     ctype : "Ext.menu.BaseItem",
36649
36650     
36651     actionMode : "container",
36652
36653     initComponent : function(){
36654         Ext.menu.BaseItem.superclass.initComponent.call(this);
36655         this.addEvents(
36656             
36657             'click',
36658             
36659             'activate',
36660             
36661             'deactivate'
36662         );
36663         if(this.handler){
36664             this.on("click", this.handler, this.scope);
36665         }
36666     },
36667
36668     
36669     onRender : function(container, position){
36670         Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
36671         if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
36672             this.parentMenu = this.ownerCt;
36673         }else{
36674             this.container.addClass('x-menu-list-item');
36675             this.mon(this.el, {
36676                 scope: this,
36677                 click: this.onClick,
36678                 mouseenter: this.activate,
36679                 mouseleave: this.deactivate
36680             });
36681         }
36682     },
36683
36684     
36685     setHandler : function(handler, scope){
36686         if(this.handler){
36687             this.un("click", this.handler, this.scope);
36688         }
36689         this.on("click", this.handler = handler, this.scope = scope);
36690     },
36691
36692     
36693     onClick : function(e){
36694         if(!this.disabled && this.fireEvent("click", this, e) !== false
36695                 && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
36696             this.handleClick(e);
36697         }else{
36698             e.stopEvent();
36699         }
36700     },
36701
36702     
36703     activate : function(){
36704         if(this.disabled){
36705             return false;
36706         }
36707         var li = this.container;
36708         li.addClass(this.activeClass);
36709         this.region = li.getRegion().adjust(2, 2, -2, -2);
36710         this.fireEvent("activate", this);
36711         return true;
36712     },
36713
36714     
36715     deactivate : function(){
36716         this.container.removeClass(this.activeClass);
36717         this.fireEvent("deactivate", this);
36718     },
36719
36720     
36721     shouldDeactivate : function(e){
36722         return !this.region || !this.region.contains(e.getPoint());
36723     },
36724
36725     
36726     handleClick : function(e){
36727         var pm = this.parentMenu;
36728         if(this.hideOnClick){
36729             if(pm.floating){
36730                 pm.hide.defer(this.clickHideDelay, pm, [true]);
36731             }else{
36732                 pm.deactivateActive();
36733             }
36734         }
36735     },
36736
36737     
36738     expandMenu : Ext.emptyFn,
36739
36740     
36741     hideMenu : Ext.emptyFn
36742 });
36743 Ext.reg('menubaseitem', Ext.menu.BaseItem);
36744 Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
36745     
36746     
36747     hideOnClick : false,
36748     
36749     itemCls : "x-menu-text",
36750     
36751     constructor : function(config){
36752         if(typeof config == 'string'){
36753             config = {text: config}
36754         }
36755         Ext.menu.TextItem.superclass.constructor.call(this, config);
36756     },
36757
36758     
36759     onRender : function(){
36760         var s = document.createElement("span");
36761         s.className = this.itemCls;
36762         s.innerHTML = this.text;
36763         this.el = s;
36764         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
36765     }
36766 });
36767 Ext.reg('menutextitem', Ext.menu.TextItem);
36768 Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
36769     
36770     itemCls : "x-menu-sep",
36771     
36772     hideOnClick : false,
36773     
36774     
36775     activeClass: '',
36776
36777     
36778     onRender : function(li){
36779         var s = document.createElement("span");
36780         s.className = this.itemCls;
36781         s.innerHTML = "&#160;";
36782         this.el = s;
36783         li.addClass("x-menu-sep-li");
36784         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
36785     }
36786 });
36787 Ext.reg('menuseparator', Ext.menu.Separator);
36788 Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
36789     
36790     
36791     
36792     
36793     
36794     
36795     
36796     
36797     itemCls : 'x-menu-item',
36798     
36799     canActivate : true,
36800     
36801     showDelay: 200,
36802     
36803     hideDelay: 200,
36804
36805     
36806     ctype: 'Ext.menu.Item',
36807
36808     initComponent : function(){
36809         Ext.menu.Item.superclass.initComponent.call(this);
36810         if(this.menu){
36811             this.menu = Ext.menu.MenuMgr.get(this.menu);
36812             this.menu.ownerCt = this;
36813         }
36814     },
36815
36816     
36817     onRender : function(container, position){
36818         if (!this.itemTpl) {
36819             this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
36820                 '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
36821                     '<tpl if="hrefTarget">',
36822                         ' target="{hrefTarget}"',
36823                     '</tpl>',
36824                  '>',
36825                      '<img src="{icon}" class="x-menu-item-icon {iconCls}"/>',
36826                      '<span class="x-menu-item-text">{text}</span>',
36827                  '</a>'
36828              );
36829         }
36830         var a = this.getTemplateArgs();
36831         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
36832         this.iconEl = this.el.child('img.x-menu-item-icon');
36833         this.textEl = this.el.child('.x-menu-item-text');
36834         if(!this.href) { 
36835             this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
36836         }
36837         Ext.menu.Item.superclass.onRender.call(this, container, position);
36838     },
36839
36840     getTemplateArgs: function() {
36841         return {
36842             id: this.id,
36843             cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
36844             href: this.href || '#',
36845             hrefTarget: this.hrefTarget,
36846             icon: this.icon || Ext.BLANK_IMAGE_URL,
36847             iconCls: this.iconCls || '',
36848             text: this.itemText||this.text||'&#160;'
36849         };
36850     },
36851
36852     
36853     setText : function(text){
36854         this.text = text||'&#160;';
36855         if(this.rendered){
36856             this.textEl.update(this.text);
36857             this.parentMenu.layout.doAutoSize();
36858         }
36859     },
36860
36861     
36862     setIconClass : function(cls){
36863         var oldCls = this.iconCls;
36864         this.iconCls = cls;
36865         if(this.rendered){
36866             this.iconEl.replaceClass(oldCls, this.iconCls);
36867         }
36868     },
36869
36870     
36871     beforeDestroy: function(){
36872         if (this.menu){
36873             delete this.menu.ownerCt;
36874             this.menu.destroy();
36875         }
36876         Ext.menu.Item.superclass.beforeDestroy.call(this);
36877     },
36878
36879     
36880     handleClick : function(e){
36881         if(!this.href){ 
36882             e.stopEvent();
36883         }
36884         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
36885     },
36886
36887     
36888     activate : function(autoExpand){
36889         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
36890             this.focus();
36891             if(autoExpand){
36892                 this.expandMenu();
36893             }
36894         }
36895         return true;
36896     },
36897
36898     
36899     shouldDeactivate : function(e){
36900         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
36901             if(this.menu && this.menu.isVisible()){
36902                 return !this.menu.getEl().getRegion().contains(e.getPoint());
36903             }
36904             return true;
36905         }
36906         return false;
36907     },
36908
36909     
36910     deactivate : function(){
36911         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
36912         this.hideMenu();
36913     },
36914
36915     
36916     expandMenu : function(autoActivate){
36917         if(!this.disabled && this.menu){
36918             clearTimeout(this.hideTimer);
36919             delete this.hideTimer;
36920             if(!this.menu.isVisible() && !this.showTimer){
36921                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
36922             }else if (this.menu.isVisible() && autoActivate){
36923                 this.menu.tryActivate(0, 1);
36924             }
36925         }
36926     },
36927
36928     
36929     deferExpand : function(autoActivate){
36930         delete this.showTimer;
36931         this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
36932         if(autoActivate){
36933             this.menu.tryActivate(0, 1);
36934         }
36935     },
36936
36937     
36938     hideMenu : function(){
36939         clearTimeout(this.showTimer);
36940         delete this.showTimer;
36941         if(!this.hideTimer && this.menu && this.menu.isVisible()){
36942             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
36943         }
36944     },
36945
36946     
36947     deferHide : function(){
36948         delete this.hideTimer;
36949         if(this.menu.over){
36950             this.parentMenu.setActiveItem(this, false);
36951         }else{
36952             this.menu.hide();
36953         }
36954     }
36955 });
36956 Ext.reg('menuitem', Ext.menu.Item);
36957 Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
36958     
36959     
36960     itemCls : "x-menu-item x-menu-check-item",
36961     
36962     groupClass : "x-menu-group-item",
36963
36964     
36965     checked: false,
36966
36967     
36968     ctype: "Ext.menu.CheckItem",
36969     
36970     initComponent : function(){
36971         Ext.menu.CheckItem.superclass.initComponent.call(this);
36972             this.addEvents(
36973                 
36974                 "beforecheckchange" ,
36975                 
36976                 "checkchange"
36977             );
36978             
36979             if(this.checkHandler){
36980                 this.on('checkchange', this.checkHandler, this.scope);
36981             }
36982             Ext.menu.MenuMgr.registerCheckable(this);
36983     },
36984
36985     
36986     onRender : function(c){
36987         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
36988         if(this.group){
36989             this.el.addClass(this.groupClass);
36990         }
36991         if(this.checked){
36992             this.checked = false;
36993             this.setChecked(true, true);
36994         }
36995     },
36996
36997     
36998     destroy : function(){
36999         Ext.menu.MenuMgr.unregisterCheckable(this);
37000         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
37001     },
37002
37003     
37004     setChecked : function(state, suppressEvent){
37005         var suppress = suppressEvent === true;
37006         if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
37007             if(this.container){
37008                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
37009             }
37010             this.checked = state;
37011             if(!suppress){
37012                 this.fireEvent("checkchange", this, state);
37013             }
37014         }
37015     },
37016
37017     
37018     handleClick : function(e){
37019        if(!this.disabled && !(this.checked && this.group)){
37020            this.setChecked(!this.checked);
37021        }
37022        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
37023     }
37024 });
37025 Ext.reg('menucheckitem', Ext.menu.CheckItem);
37026  Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
37027     
37028     enableScrolling : false,
37029     
37030         
37031     
37032     hideOnClick : true,
37033     
37034     
37035     pickerId : null,
37036     
37037     
37038     
37039     
37040     cls : 'x-date-menu',
37041     
37042     
37043     
37044     
37045
37046     initComponent : function(){
37047         this.on('beforeshow', this.onBeforeShow, this);
37048         if(this.strict = (Ext.isIE7 && Ext.isStrict)){
37049             this.on('show', this.onShow, this, {single: true, delay: 20});
37050         }
37051         Ext.apply(this, {
37052             plain: true,
37053             showSeparator: false,
37054             items: this.picker = new Ext.DatePicker(Ext.applyIf({
37055                 internalRender: this.strict || !Ext.isIE,
37056                 ctCls: 'x-menu-date-item',
37057                 id: this.pickerId
37058             }, this.initialConfig))
37059         });
37060         this.picker.purgeListeners();
37061         Ext.menu.DateMenu.superclass.initComponent.call(this);
37062         
37063         this.relayEvents(this.picker, ['select']);
37064         this.on('show', this.picker.focus, this.picker);
37065         this.on('select', this.menuHide, this);
37066         if(this.handler){
37067             this.on('select', this.handler, this.scope || this);
37068         }
37069     },
37070
37071     menuHide : function() {
37072         if(this.hideOnClick){
37073             this.hide(true);
37074         }
37075     },
37076
37077     onBeforeShow : function(){
37078         if(this.picker){
37079             this.picker.hideMonthPicker(true);
37080         }
37081     },
37082
37083     onShow : function(){
37084         var el = this.picker.getEl();
37085         el.setWidth(el.getWidth()); 
37086     }
37087  });
37088  Ext.reg('datemenu', Ext.menu.DateMenu);
37089  
37090  Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
37091     
37092     enableScrolling : false,
37093     
37094         
37095     
37096     
37097     hideOnClick : true,
37098     
37099     cls : 'x-color-menu',
37100     
37101     
37102     paletteId : null,
37103     
37104     
37105     
37106     
37107     
37108     
37109     
37110     
37111     
37112     
37113     initComponent : function(){
37114         Ext.apply(this, {
37115             plain: true,
37116             showSeparator: false,
37117             items: this.palette = new Ext.ColorPalette(Ext.applyIf({
37118                 id: this.paletteId
37119             }, this.initialConfig))
37120         });
37121         this.palette.purgeListeners();
37122         Ext.menu.ColorMenu.superclass.initComponent.call(this);
37123         
37124         this.relayEvents(this.palette, ['select']);
37125         this.on('select', this.menuHide, this);
37126         if(this.handler){
37127             this.on('select', this.handler, this.scope || this);
37128         }
37129     },
37130
37131     menuHide : function(){
37132         if(this.hideOnClick){
37133             this.hide(true);
37134         }
37135     }
37136 });
37137 Ext.reg('colormenu', Ext.menu.ColorMenu);
37138
37139 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
37140     
37141     
37142     
37143     
37144     
37145     
37146
37147     
37148     invalidClass : 'x-form-invalid',
37149     
37150     invalidText : 'The value in this field is invalid',
37151     
37152     focusClass : 'x-form-focus',
37153     
37154     
37155     validationEvent : 'keyup',
37156     
37157     validateOnBlur : true,
37158     
37159     validationDelay : 250,
37160     
37161     defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
37162     
37163     fieldClass : 'x-form-field',
37164     
37165     msgTarget : 'qtip',
37166     
37167     msgFx : 'normal',
37168     
37169     readOnly : false,
37170     
37171     disabled : false,
37172     
37173     submitValue: true,
37174
37175     
37176     isFormField : true,
37177
37178     
37179     msgDisplay: '',
37180
37181     
37182     hasFocus : false,
37183
37184     
37185     initComponent : function(){
37186         Ext.form.Field.superclass.initComponent.call(this);
37187         this.addEvents(
37188             
37189             'focus',
37190             
37191             'blur',
37192             
37193             'specialkey',
37194             
37195             'change',
37196             
37197             'invalid',
37198             
37199             'valid'
37200         );
37201     },
37202
37203     
37204     getName : function(){
37205         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
37206     },
37207
37208     
37209     onRender : function(ct, position){
37210         if(!this.el){
37211             var cfg = this.getAutoCreate();
37212
37213             if(!cfg.name){
37214                 cfg.name = this.name || this.id;
37215             }
37216             if(this.inputType){
37217                 cfg.type = this.inputType;
37218             }
37219             this.autoEl = cfg;
37220         }
37221         Ext.form.Field.superclass.onRender.call(this, ct, position);
37222         if(this.submitValue === false){
37223             this.el.dom.removeAttribute('name');
37224         }
37225         var type = this.el.dom.type;
37226         if(type){
37227             if(type == 'password'){
37228                 type = 'text';
37229             }
37230             this.el.addClass('x-form-'+type);
37231         }
37232         if(this.readOnly){
37233             this.setReadOnly(true);
37234         }
37235         if(this.tabIndex !== undefined){
37236             this.el.dom.setAttribute('tabIndex', this.tabIndex);
37237         }
37238
37239         this.el.addClass([this.fieldClass, this.cls]);
37240     },
37241
37242     
37243     getItemCt : function(){
37244         return this.itemCt;
37245     },
37246
37247     
37248     initValue : function(){
37249         if(this.value !== undefined){
37250             this.setValue(this.value);
37251         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
37252             this.setValue(this.el.dom.value);
37253         }
37254         
37255         this.originalValue = this.getValue();
37256     },
37257
37258     
37259     isDirty : function() {
37260         if(this.disabled || !this.rendered) {
37261             return false;
37262         }
37263         return String(this.getValue()) !== String(this.originalValue);
37264     },
37265
37266     
37267     setReadOnly : function(readOnly){
37268         if(this.rendered){
37269             this.el.dom.readOnly = readOnly;
37270         }
37271         this.readOnly = readOnly;
37272     },
37273
37274     
37275     afterRender : function(){
37276         Ext.form.Field.superclass.afterRender.call(this);
37277         this.initEvents();
37278         this.initValue();
37279     },
37280
37281     
37282     fireKey : function(e){
37283         if(e.isSpecialKey()){
37284             this.fireEvent('specialkey', this, e);
37285         }
37286     },
37287
37288     
37289     reset : function(){
37290         this.setValue(this.originalValue);
37291         this.clearInvalid();
37292     },
37293
37294     
37295     initEvents : function(){
37296         this.mon(this.el, Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.fireKey,  this);
37297         this.mon(this.el, 'focus', this.onFocus, this);
37298
37299         
37300         
37301         this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
37302     },
37303
37304     
37305     preFocus: Ext.emptyFn,
37306
37307     
37308     onFocus : function(){
37309         this.preFocus();
37310         if(this.focusClass){
37311             this.el.addClass(this.focusClass);
37312         }
37313         if(!this.hasFocus){
37314             this.hasFocus = true;
37315             
37316             this.startValue = this.getValue();
37317             this.fireEvent('focus', this);
37318         }
37319     },
37320
37321     
37322     beforeBlur : Ext.emptyFn,
37323
37324     
37325     onBlur : function(){
37326         this.beforeBlur();
37327         if(this.focusClass){
37328             this.el.removeClass(this.focusClass);
37329         }
37330         this.hasFocus = false;
37331         if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
37332             this.validate();
37333         }
37334         var v = this.getValue();
37335         if(String(v) !== String(this.startValue)){
37336             this.fireEvent('change', this, v, this.startValue);
37337         }
37338         this.fireEvent('blur', this);
37339         this.postBlur();
37340     },
37341
37342     
37343     postBlur : Ext.emptyFn,
37344
37345     
37346     isValid : function(preventMark){
37347         if(this.disabled){
37348             return true;
37349         }
37350         var restore = this.preventMark;
37351         this.preventMark = preventMark === true;
37352         var v = this.validateValue(this.processValue(this.getRawValue()));
37353         this.preventMark = restore;
37354         return v;
37355     },
37356
37357     
37358     validate : function(){
37359         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
37360             this.clearInvalid();
37361             return true;
37362         }
37363         return false;
37364     },
37365
37366     
37367     processValue : function(value){
37368         return value;
37369     },
37370
37371     
37372      validateValue : function(value) {
37373          
37374          var error = this.getErrors(value)[0];
37375
37376          if (error == undefined) {
37377              return true;
37378          } else {
37379              this.markInvalid(error);
37380              return false;
37381          }
37382      },
37383     
37384     
37385     getErrors: function() {
37386         return [];
37387     },
37388
37389     
37390     getActiveError : function(){
37391         return this.activeError || '';
37392     },
37393
37394     
37395     markInvalid : function(msg){
37396         
37397         if (this.rendered && !this.preventMark) {
37398             msg = msg || this.invalidText;
37399
37400             var mt = this.getMessageHandler();
37401             if(mt){
37402                 mt.mark(this, msg);
37403             }else if(this.msgTarget){
37404                 this.el.addClass(this.invalidClass);
37405                 var t = Ext.getDom(this.msgTarget);
37406                 if(t){
37407                     t.innerHTML = msg;
37408                     t.style.display = this.msgDisplay;
37409                 }
37410             }
37411         }
37412         
37413         this.setActiveError(msg);
37414     },
37415     
37416     
37417     clearInvalid : function(){
37418         
37419         if (this.rendered && !this.preventMark) {
37420             this.el.removeClass(this.invalidClass);
37421             var mt = this.getMessageHandler();
37422             if(mt){
37423                 mt.clear(this);
37424             }else if(this.msgTarget){
37425                 this.el.removeClass(this.invalidClass);
37426                 var t = Ext.getDom(this.msgTarget);
37427                 if(t){
37428                     t.innerHTML = '';
37429                     t.style.display = 'none';
37430                 }
37431             }
37432         }
37433         
37434         this.unsetActiveError();
37435     },
37436
37437     
37438     setActiveError: function(msg, suppressEvent) {
37439         this.activeError = msg;
37440         if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
37441     },
37442     
37443     
37444     unsetActiveError: function(suppressEvent) {
37445         delete this.activeError;
37446         if (suppressEvent !== true) this.fireEvent('valid', this);
37447     },
37448
37449     
37450     getMessageHandler : function(){
37451         return Ext.form.MessageTargets[this.msgTarget];
37452     },
37453
37454     
37455     getErrorCt : function(){
37456         return this.el.findParent('.x-form-element', 5, true) || 
37457             this.el.findParent('.x-form-field-wrap', 5, true);   
37458     },
37459
37460     
37461     alignErrorEl : function(){
37462         this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
37463     },
37464
37465     
37466     alignErrorIcon : function(){
37467         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
37468     },
37469
37470     
37471     getRawValue : function(){
37472         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
37473         if(v === this.emptyText){
37474             v = '';
37475         }
37476         return v;
37477     },
37478
37479     
37480     getValue : function(){
37481         if(!this.rendered) {
37482             return this.value;
37483         }
37484         var v = this.el.getValue();
37485         if(v === this.emptyText || v === undefined){
37486             v = '';
37487         }
37488         return v;
37489     },
37490
37491     
37492     setRawValue : function(v){
37493         return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
37494     },
37495
37496     
37497     setValue : function(v){
37498         this.value = v;
37499         if(this.rendered){
37500             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
37501             this.validate();
37502         }
37503         return this;
37504     },
37505
37506     
37507     append : function(v){
37508          this.setValue([this.getValue(), v].join(''));
37509     }
37510
37511     
37512     
37513
37514     
37515 });
37516
37517
37518 Ext.form.MessageTargets = {
37519     'qtip' : {
37520         mark: function(field, msg){
37521             field.el.addClass(field.invalidClass);
37522             field.el.dom.qtip = msg;
37523             field.el.dom.qclass = 'x-form-invalid-tip';
37524             if(Ext.QuickTips){ 
37525                 Ext.QuickTips.enable();
37526             }
37527         },
37528         clear: function(field){
37529             field.el.removeClass(field.invalidClass);
37530             field.el.dom.qtip = '';
37531         }
37532     },
37533     'title' : {
37534         mark: function(field, msg){
37535             field.el.addClass(field.invalidClass);
37536             field.el.dom.title = msg;
37537         },
37538         clear: function(field){
37539             field.el.dom.title = '';
37540         }
37541     },
37542     'under' : {
37543         mark: function(field, msg){
37544             field.el.addClass(field.invalidClass);
37545             if(!field.errorEl){
37546                 var elp = field.getErrorCt();
37547                 if(!elp){ 
37548                     field.el.dom.title = msg;
37549                     return;
37550                 }
37551                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
37552                 field.on('resize', field.alignErrorEl, field);
37553                 field.on('destroy', function(){
37554                     Ext.destroy(this.errorEl);
37555                 }, field);
37556             }
37557             field.alignErrorEl();
37558             field.errorEl.update(msg);
37559             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
37560         },
37561         clear: function(field){
37562             field.el.removeClass(field.invalidClass);
37563             if(field.errorEl){
37564                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
37565             }else{
37566                 field.el.dom.title = '';
37567             }
37568         }
37569     },
37570     'side' : {
37571         mark: function(field, msg){
37572             field.el.addClass(field.invalidClass);
37573             if(!field.errorIcon){
37574                 var elp = field.getErrorCt();
37575                 
37576                 if(!elp){
37577                     field.el.dom.title = msg;
37578                     return;
37579                 }
37580                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
37581                 if (field.ownerCt) {
37582                     field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
37583                     field.ownerCt.on('expand', field.alignErrorIcon, field);
37584                 }
37585                 field.on('resize', field.alignErrorIcon, field);
37586                 field.on('destroy', function(){
37587                     Ext.destroy(this.errorIcon);
37588                 }, field);
37589             }
37590             field.alignErrorIcon();
37591             field.errorIcon.dom.qtip = msg;
37592             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
37593             field.errorIcon.show();
37594         },
37595         clear: function(field){
37596             field.el.removeClass(field.invalidClass);
37597             if(field.errorIcon){
37598                 field.errorIcon.dom.qtip = '';
37599                 field.errorIcon.hide();
37600             }else{
37601                 field.el.dom.title = '';
37602             }
37603         }
37604     }
37605 };
37606
37607
37608 Ext.form.Field.msgFx = {
37609     normal : {
37610         show: function(msgEl, f){
37611             msgEl.setDisplayed('block');
37612         },
37613
37614         hide : function(msgEl, f){
37615             msgEl.setDisplayed(false).update('');
37616         }
37617     },
37618
37619     slide : {
37620         show: function(msgEl, f){
37621             msgEl.slideIn('t', {stopFx:true});
37622         },
37623
37624         hide : function(msgEl, f){
37625             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
37626         }
37627     },
37628
37629     slideRight : {
37630         show: function(msgEl, f){
37631             msgEl.fixDisplay();
37632             msgEl.alignTo(f.el, 'tl-tr');
37633             msgEl.slideIn('l', {stopFx:true});
37634         },
37635
37636         hide : function(msgEl, f){
37637             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
37638         }
37639     }
37640 };
37641 Ext.reg('field', Ext.form.Field);
37642
37643 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
37644     
37645     
37646     
37647     grow : false,
37648     
37649     growMin : 30,
37650     
37651     growMax : 800,
37652     
37653     vtype : null,
37654     
37655     maskRe : null,
37656     
37657     disableKeyFilter : false,
37658     
37659     allowBlank : true,
37660     
37661     minLength : 0,
37662     
37663     maxLength : Number.MAX_VALUE,
37664     
37665     minLengthText : 'The minimum length for this field is {0}',
37666     
37667     maxLengthText : 'The maximum length for this field is {0}',
37668     
37669     selectOnFocus : false,
37670     
37671     blankText : 'This field is required',
37672     
37673     validator : null,
37674     
37675     regex : null,
37676     
37677     regexText : '',
37678     
37679     emptyText : null,
37680     
37681     emptyClass : 'x-form-empty-field',
37682
37683     
37684
37685     initComponent : function(){
37686         Ext.form.TextField.superclass.initComponent.call(this);
37687         this.addEvents(
37688             
37689             'autosize',
37690
37691             
37692             'keydown',
37693             
37694             'keyup',
37695             
37696             'keypress'
37697         );
37698     },
37699
37700     
37701     initEvents : function(){
37702         Ext.form.TextField.superclass.initEvents.call(this);
37703         if(this.validationEvent == 'keyup'){
37704             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
37705             this.mon(this.el, 'keyup', this.filterValidation, this);
37706         }
37707         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
37708                 this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
37709         }
37710         if(this.selectOnFocus || this.emptyText){            
37711             this.mon(this.el, 'mousedown', this.onMouseDown, this);
37712             
37713             if(this.emptyText){
37714                 this.applyEmptyText();
37715             }
37716         }
37717         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
37718                 this.mon(this.el, 'keypress', this.filterKeys, this);
37719         }
37720         if(this.grow){
37721                 this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
37722                         this.mon(this.el, 'click', this.autoSize, this);
37723         }
37724         if(this.enableKeyEvents){
37725             this.mon(this.el, {
37726                 scope: this,
37727                 keyup: this.onKeyUp,
37728                 keydown: this.onKeyDown,
37729                 keypress: this.onKeyPress
37730             });
37731         }
37732     },
37733     
37734     onMouseDown: function(e){
37735         if(!this.hasFocus){
37736             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
37737         }
37738     },
37739
37740     processValue : function(value){
37741         if(this.stripCharsRe){
37742             var newValue = value.replace(this.stripCharsRe, '');
37743             if(newValue !== value){
37744                 this.setRawValue(newValue);
37745                 return newValue;
37746             }
37747         }
37748         return value;
37749     },
37750
37751     filterValidation : function(e){
37752         if(!e.isNavKeyPress()){
37753             this.validationTask.delay(this.validationDelay);
37754         }
37755     },
37756     
37757     
37758     onDisable: function(){
37759         Ext.form.TextField.superclass.onDisable.call(this);
37760         if(Ext.isIE){
37761             this.el.dom.unselectable = 'on';
37762         }
37763     },
37764     
37765     
37766     onEnable: function(){
37767         Ext.form.TextField.superclass.onEnable.call(this);
37768         if(Ext.isIE){
37769             this.el.dom.unselectable = '';
37770         }
37771     },
37772
37773     
37774     onKeyUpBuffered : function(e){
37775         if(this.doAutoSize(e)){
37776             this.autoSize();
37777         }
37778     },
37779     
37780     
37781     doAutoSize : function(e){
37782         return !e.isNavKeyPress();
37783     },
37784
37785     
37786     onKeyUp : function(e){
37787         this.fireEvent('keyup', this, e);
37788     },
37789
37790     
37791     onKeyDown : function(e){
37792         this.fireEvent('keydown', this, e);
37793     },
37794
37795     
37796     onKeyPress : function(e){
37797         this.fireEvent('keypress', this, e);
37798     },
37799
37800     
37801     reset : function(){
37802         Ext.form.TextField.superclass.reset.call(this);
37803         this.applyEmptyText();
37804     },
37805
37806     applyEmptyText : function(){
37807         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
37808             this.setRawValue(this.emptyText);
37809             this.el.addClass(this.emptyClass);
37810         }
37811     },
37812
37813     
37814     preFocus : function(){
37815         var el = this.el;
37816         if(this.emptyText){
37817             if(el.dom.value == this.emptyText){
37818                 this.setRawValue('');
37819             }
37820             el.removeClass(this.emptyClass);
37821         }
37822         if(this.selectOnFocus){
37823             el.dom.select();
37824         }
37825     },
37826
37827     
37828     postBlur : function(){
37829         this.applyEmptyText();
37830     },
37831
37832     
37833     filterKeys : function(e){
37834         if(e.ctrlKey){
37835             return;
37836         }
37837         var k = e.getKey();
37838         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
37839             return;
37840         }
37841         var cc = String.fromCharCode(e.getCharCode());
37842         if(!Ext.isGecko && e.isSpecialKey() && !cc){
37843             return;
37844         }
37845         if(!this.maskRe.test(cc)){
37846             e.stopEvent();
37847         }
37848     },
37849
37850     setValue : function(v){
37851         if(this.emptyText && this.el && !Ext.isEmpty(v)){
37852             this.el.removeClass(this.emptyClass);
37853         }
37854         Ext.form.TextField.superclass.setValue.apply(this, arguments);
37855         this.applyEmptyText();
37856         this.autoSize();
37857         return this;
37858     },
37859
37860     
37861     getErrors: function(value) {
37862         var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
37863         
37864         value = value || this.processValue(this.getRawValue());        
37865         
37866         if (Ext.isFunction(this.validator)) {
37867             var msg = this.validator(value);
37868             if (msg !== true) {
37869                 errors.push(msg);
37870             }
37871         }
37872         
37873         if (value.length < 1 || value === this.emptyText) {
37874             if (this.allowBlank) {
37875                 
37876                 return errors;
37877             } else {
37878                 errors.push(this.blankText);
37879             }
37880         }
37881         
37882         if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
37883             errors.push(this.blankText);
37884         }
37885         
37886         if (value.length < this.minLength) {
37887             errors.push(String.format(this.minLengthText, this.minLength));
37888         }
37889         
37890         if (value.length > this.maxLength) {
37891             errors.push(String.format(this.maxLengthText, this.maxLength));
37892         }
37893         
37894         if (this.vtype) {
37895             var vt = Ext.form.VTypes;
37896             if(!vt[this.vtype](value, this)){
37897                 errors.push(this.vtypeText || vt[this.vtype +'Text']);
37898             }
37899         }
37900         
37901         if (this.regex && !this.regex.test(value)) {
37902             errors.push(this.regexText);
37903         }
37904         
37905         return errors;
37906     },
37907
37908     
37909     selectText : function(start, end){
37910         var v = this.getRawValue();
37911         var doFocus = false;
37912         if(v.length > 0){
37913             start = start === undefined ? 0 : start;
37914             end = end === undefined ? v.length : end;
37915             var d = this.el.dom;
37916             if(d.setSelectionRange){
37917                 d.setSelectionRange(start, end);
37918             }else if(d.createTextRange){
37919                 var range = d.createTextRange();
37920                 range.moveStart('character', start);
37921                 range.moveEnd('character', end-v.length);
37922                 range.select();
37923             }
37924             doFocus = Ext.isGecko || Ext.isOpera;
37925         }else{
37926             doFocus = true;
37927         }
37928         if(doFocus){
37929             this.focus();
37930         }
37931     },
37932
37933     
37934     autoSize : function(){
37935         if(!this.grow || !this.rendered){
37936             return;
37937         }
37938         if(!this.metrics){
37939             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
37940         }
37941         var el = this.el;
37942         var v = el.dom.value;
37943         var d = document.createElement('div');
37944         d.appendChild(document.createTextNode(v));
37945         v = d.innerHTML;
37946         Ext.removeNode(d);
37947         d = null;
37948         v += '&#160;';
37949         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
37950         this.el.setWidth(w);
37951         this.fireEvent('autosize', this, w);
37952     },
37953         
37954         onDestroy: function(){
37955                 if(this.validationTask){
37956                         this.validationTask.cancel();
37957                         this.validationTask = null;
37958                 }
37959                 Ext.form.TextField.superclass.onDestroy.call(this);
37960         }
37961 });
37962 Ext.reg('textfield', Ext.form.TextField);
37963
37964 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
37965     
37966     
37967     
37968     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
37969     
37970     hideTrigger:false,
37971     
37972     editable: true,
37973     
37974     readOnly: false,
37975     
37976     wrapFocusClass: 'x-trigger-wrap-focus',
37977     
37978     autoSize: Ext.emptyFn,
37979     
37980     monitorTab : true,
37981     
37982     deferHeight : true,
37983     
37984     mimicing : false,
37985
37986     actionMode: 'wrap',
37987
37988     defaultTriggerWidth: 17,
37989
37990     
37991     onResize : function(w, h){
37992         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
37993         var tw = this.getTriggerWidth();
37994         if(Ext.isNumber(w)){
37995             this.el.setWidth(w - tw);
37996         }
37997         this.wrap.setWidth(this.el.getWidth() + tw);
37998     },
37999
38000     getTriggerWidth: function(){
38001         var tw = this.trigger.getWidth();
38002         if(!this.hideTrigger && !this.readOnly && tw === 0){
38003             tw = this.defaultTriggerWidth;
38004         }
38005         return tw;
38006     },
38007
38008     
38009     alignErrorIcon : function(){
38010         if(this.wrap){
38011             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
38012         }
38013     },
38014
38015     
38016     onRender : function(ct, position){
38017         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
38018         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
38019
38020         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
38021         this.trigger = this.wrap.createChild(this.triggerConfig ||
38022                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
38023         this.initTrigger();
38024         if(!this.width){
38025             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
38026         }
38027         this.resizeEl = this.positionEl = this.wrap;
38028     },
38029
38030     getWidth: function() {
38031         return(this.el.getWidth() + this.trigger.getWidth());
38032     },
38033
38034     updateEditState: function(){
38035         if(this.rendered){
38036             if (this.readOnly) {
38037                 this.el.dom.readOnly = true;
38038                 this.el.addClass('x-trigger-noedit');
38039                 this.mun(this.el, 'click', this.onTriggerClick, this);
38040                 this.trigger.setDisplayed(false);
38041             } else {
38042                 if (!this.editable) {
38043                     this.el.dom.readOnly = true;
38044                     this.el.addClass('x-trigger-noedit');
38045                     this.mon(this.el, 'click', this.onTriggerClick, this);
38046                 } else {
38047                     this.el.dom.readOnly = false;
38048                     this.el.removeClass('x-trigger-noedit');
38049                     this.mun(this.el, 'click', this.onTriggerClick, this);
38050                 }
38051                 this.trigger.setDisplayed(!this.hideTrigger);
38052             }
38053             this.onResize(this.width || this.wrap.getWidth());
38054         }
38055     },
38056
38057     setHideTrigger: function(hideTrigger){
38058         if(hideTrigger != this.hideTrigger){
38059             this.hideTrigger = hideTrigger;
38060             this.updateEditState();
38061         }
38062     },
38063
38064     
38065     setEditable: function(editable){
38066         if(editable != this.editable){
38067             this.editable = editable;
38068             this.updateEditState();
38069         }
38070     },
38071
38072     
38073     setReadOnly: function(readOnly){
38074         if(readOnly != this.readOnly){
38075             this.readOnly = readOnly;
38076             this.updateEditState();
38077         }
38078     },
38079
38080     afterRender : function(){
38081         Ext.form.TriggerField.superclass.afterRender.call(this);
38082         this.updateEditState();
38083     },
38084
38085     
38086     initTrigger : function(){
38087         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
38088         this.trigger.addClassOnOver('x-form-trigger-over');
38089         this.trigger.addClassOnClick('x-form-trigger-click');
38090     },
38091
38092     
38093     onDestroy : function(){
38094         Ext.destroy(this.trigger, this.wrap);
38095         if (this.mimicing){
38096             this.doc.un('mousedown', this.mimicBlur, this);
38097         }
38098         delete this.doc;
38099         Ext.form.TriggerField.superclass.onDestroy.call(this);
38100     },
38101
38102     
38103     onFocus : function(){
38104         Ext.form.TriggerField.superclass.onFocus.call(this);
38105         if(!this.mimicing){
38106             this.wrap.addClass(this.wrapFocusClass);
38107             this.mimicing = true;
38108             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
38109             if(this.monitorTab){
38110                 this.on('specialkey', this.checkTab, this);
38111             }
38112         }
38113     },
38114
38115     
38116     checkTab : function(me, e){
38117         if(e.getKey() == e.TAB){
38118             this.triggerBlur();
38119         }
38120     },
38121
38122     
38123     onBlur : Ext.emptyFn,
38124
38125     
38126     mimicBlur : function(e){
38127         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
38128             this.triggerBlur();
38129         }
38130     },
38131
38132     
38133     triggerBlur : function(){
38134         this.mimicing = false;
38135         this.doc.un('mousedown', this.mimicBlur, this);
38136         if(this.monitorTab && this.el){
38137             this.un('specialkey', this.checkTab, this);
38138         }
38139         Ext.form.TriggerField.superclass.onBlur.call(this);
38140         if(this.wrap){
38141             this.wrap.removeClass(this.wrapFocusClass);
38142         }
38143     },
38144
38145     beforeBlur : Ext.emptyFn,
38146
38147     
38148     
38149     validateBlur : function(e){
38150         return true;
38151     },
38152
38153     
38154     onTriggerClick : Ext.emptyFn
38155
38156     
38157     
38158     
38159 });
38160
38161
38162 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
38163     
38164     
38165     
38166
38167     initComponent : function(){
38168         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
38169
38170         this.triggerConfig = {
38171             tag:'span', cls:'x-form-twin-triggers', cn:[
38172             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
38173             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
38174         ]};
38175     },
38176
38177     getTrigger : function(index){
38178         return this.triggers[index];
38179     },
38180     
38181     afterRender: function(){
38182         Ext.form.TwinTriggerField.superclass.afterRender.call(this);
38183         var triggers = this.triggers,
38184             i = 0,
38185             len = triggers.length;
38186             
38187         for(; i < len; ++i){
38188             if(this['hideTrigger' + (i + 1)]){
38189                     triggers[i].hide();
38190                 }
38191
38192         }    
38193     },
38194
38195     initTrigger : function(){
38196         var ts = this.trigger.select('.x-form-trigger', true),
38197             triggerField = this;
38198             
38199         ts.each(function(t, all, index){
38200             var triggerIndex = 'Trigger'+(index+1);
38201             t.hide = function(){
38202                 var w = triggerField.wrap.getWidth();
38203                 this.dom.style.display = 'none';
38204                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
38205                 this['hidden' + triggerIndex] = true;
38206             };
38207             t.show = function(){
38208                 var w = triggerField.wrap.getWidth();
38209                 this.dom.style.display = '';
38210                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
38211                 this['hidden' + triggerIndex] = false;
38212             };
38213             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
38214             t.addClassOnOver('x-form-trigger-over');
38215             t.addClassOnClick('x-form-trigger-click');
38216         }, this);
38217         this.triggers = ts.elements;
38218     },
38219
38220     getTriggerWidth: function(){
38221         var tw = 0;
38222         Ext.each(this.triggers, function(t, index){
38223             var triggerIndex = 'Trigger' + (index + 1),
38224                 w = t.getWidth();
38225             if(w === 0 && !this['hidden' + triggerIndex]){
38226                 tw += this.defaultTriggerWidth;
38227             }else{
38228                 tw += w;
38229             }
38230         }, this);
38231         return tw;
38232     },
38233
38234     
38235     onDestroy : function() {
38236         Ext.destroy(this.triggers);
38237         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
38238     },
38239
38240     
38241     onTrigger1Click : Ext.emptyFn,
38242     
38243     onTrigger2Click : Ext.emptyFn
38244 });
38245 Ext.reg('trigger', Ext.form.TriggerField);
38246
38247 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
38248     
38249     growMin : 60,
38250     
38251     growMax: 1000,
38252     growAppend : '&#160;\n&#160;',
38253
38254     enterIsSpecial : false,
38255
38256     
38257     preventScrollbars: false,
38258     
38259
38260     
38261     onRender : function(ct, position){
38262         if(!this.el){
38263             this.defaultAutoCreate = {
38264                 tag: "textarea",
38265                 style:"width:100px;height:60px;",
38266                 autocomplete: "off"
38267             };
38268         }
38269         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
38270         if(this.grow){
38271             this.textSizeEl = Ext.DomHelper.append(document.body, {
38272                 tag: "pre", cls: "x-form-grow-sizer"
38273             });
38274             if(this.preventScrollbars){
38275                 this.el.setStyle("overflow", "hidden");
38276             }
38277             this.el.setHeight(this.growMin);
38278         }
38279     },
38280
38281     onDestroy : function(){
38282         Ext.removeNode(this.textSizeEl);
38283         Ext.form.TextArea.superclass.onDestroy.call(this);
38284     },
38285
38286     fireKey : function(e){
38287         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
38288             this.fireEvent("specialkey", this, e);
38289         }
38290     },
38291     
38292     
38293     doAutoSize : function(e){
38294         return !e.isNavKeyPress() || e.getKey() == e.ENTER;
38295     },
38296
38297     
38298     autoSize: function(){
38299         if(!this.grow || !this.textSizeEl){
38300             return;
38301         }
38302         var el = this.el,
38303             v = Ext.util.Format.htmlEncode(el.dom.value),
38304             ts = this.textSizeEl,
38305             h;
38306             
38307         Ext.fly(ts).setWidth(this.el.getWidth());
38308         if(v.length < 1){
38309             v = "&#160;&#160;";
38310         }else{
38311             v += this.growAppend;
38312             if(Ext.isIE){
38313                 v = v.replace(/\n/g, '&#160;<br />');
38314             }
38315         }
38316         ts.innerHTML = v;
38317         h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
38318         if(h != this.lastHeight){
38319             this.lastHeight = h;
38320             this.el.setHeight(h);
38321             this.fireEvent("autosize", this, h);
38322         }
38323     }
38324 });
38325 Ext.reg('textarea', Ext.form.TextArea);
38326 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
38327     
38328     
38329     
38330     fieldClass: "x-form-field x-form-num-field",
38331     
38332     allowDecimals : true,
38333     
38334     decimalSeparator : ".",
38335     
38336     decimalPrecision : 2,
38337     
38338     allowNegative : true,
38339     
38340     minValue : Number.NEGATIVE_INFINITY,
38341     
38342     maxValue : Number.MAX_VALUE,
38343     
38344     minText : "The minimum value for this field is {0}",
38345     
38346     maxText : "The maximum value for this field is {0}",
38347     
38348     nanText : "{0} is not a valid number",
38349     
38350     baseChars : "0123456789",
38351
38352     
38353     initEvents : function(){
38354         var allowed = this.baseChars + '';
38355         if (this.allowDecimals) {
38356             allowed += this.decimalSeparator;
38357         }
38358         if (this.allowNegative) {
38359             allowed += '-';
38360         }
38361         this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');
38362         Ext.form.NumberField.superclass.initEvents.call(this);
38363     },
38364     
38365     
38366     getErrors: function(value) {
38367         var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
38368         
38369         value = value || this.processValue(this.getRawValue());
38370         
38371         if (value.length < 1) { 
38372              return errors;
38373         }
38374         
38375         value = String(value).replace(this.decimalSeparator, ".");
38376         
38377         if(isNaN(value)){
38378             errors.push(String.format(this.nanText, value));
38379         }
38380         
38381         var num = this.parseValue(value);
38382         
38383         if(num < this.minValue){
38384             errors.push(String.format(this.minText, this.minValue));
38385         }
38386         
38387         if(num > this.maxValue){
38388             errors.push(String.format(this.maxText, this.maxValue));
38389         }
38390         
38391         return errors;
38392     },
38393
38394     getValue : function(){
38395         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
38396     },
38397
38398     setValue : function(v){
38399         v = this.fixPrecision(v);
38400         v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
38401         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
38402         return Ext.form.NumberField.superclass.setValue.call(this, v);
38403     },
38404     
38405     
38406     setMinValue : function(value){
38407         this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
38408     },
38409     
38410     
38411     setMaxValue : function(value){
38412         this.maxValue = Ext.num(value, Number.MAX_VALUE);    
38413     },
38414
38415     
38416     parseValue : function(value){
38417         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
38418         return isNaN(value) ? '' : value;
38419     },
38420
38421     
38422     fixPrecision : function(value){
38423         var nan = isNaN(value);
38424         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
38425            return nan ? '' : value;
38426         }
38427         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
38428     },
38429
38430     beforeBlur : function(){
38431         var v = this.parseValue(this.getRawValue());
38432         if(!Ext.isEmpty(v)){
38433             this.setValue(v);
38434         }
38435     }
38436 });
38437 Ext.reg('numberfield', Ext.form.NumberField);
38438 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
38439     
38440     format : "m/d/Y",
38441     
38442     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",
38443     
38444     disabledDaysText : "Disabled",
38445     
38446     disabledDatesText : "Disabled",
38447     
38448     minText : "The date in this field must be equal to or after {0}",
38449     
38450     maxText : "The date in this field must be equal to or before {0}",
38451     
38452     invalidText : "{0} is not a valid date - it must be in the format {1}",
38453     
38454     triggerClass : 'x-form-date-trigger',
38455     
38456     showToday : true,
38457     
38458     
38459     
38460     
38461     
38462
38463     
38464     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
38465
38466     
38467     
38468     initTime: '12', 
38469
38470     initTimeFormat: 'H',
38471
38472     
38473     safeParse : function(value, format) {
38474         if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {
38475             
38476             return Date.parseDate(value, format);
38477         } else {
38478             
38479             var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
38480
38481             if (parsedDate) return parsedDate.clearTime();
38482         }
38483     },
38484
38485     initComponent : function(){
38486         Ext.form.DateField.superclass.initComponent.call(this);
38487
38488         this.addEvents(
38489             
38490             'select'
38491         );
38492
38493         if(Ext.isString(this.minValue)){
38494             this.minValue = this.parseDate(this.minValue);
38495         }
38496         if(Ext.isString(this.maxValue)){
38497             this.maxValue = this.parseDate(this.maxValue);
38498         }
38499         this.disabledDatesRE = null;
38500         this.initDisabledDays();
38501     },
38502
38503     initEvents: function() {
38504         Ext.form.DateField.superclass.initEvents.call(this);
38505         this.keyNav = new Ext.KeyNav(this.el, {
38506             "down": function(e) {
38507                 this.onTriggerClick();
38508             },
38509             scope: this,
38510             forceKeyDown: true
38511         });
38512     },
38513
38514
38515     
38516     initDisabledDays : function(){
38517         if(this.disabledDates){
38518             var dd = this.disabledDates,
38519                 len = dd.length - 1,
38520                 re = "(?:";
38521
38522             Ext.each(dd, function(d, i){
38523                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
38524                 if(i != len){
38525                     re += '|';
38526                 }
38527             }, this);
38528             this.disabledDatesRE = new RegExp(re + ')');
38529         }
38530     },
38531
38532     
38533     setDisabledDates : function(dd){
38534         this.disabledDates = dd;
38535         this.initDisabledDays();
38536         if(this.menu){
38537             this.menu.picker.setDisabledDates(this.disabledDatesRE);
38538         }
38539     },
38540
38541     
38542     setDisabledDays : function(dd){
38543         this.disabledDays = dd;
38544         if(this.menu){
38545             this.menu.picker.setDisabledDays(dd);
38546         }
38547     },
38548
38549     
38550     setMinValue : function(dt){
38551         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
38552         if(this.menu){
38553             this.menu.picker.setMinDate(this.minValue);
38554         }
38555     },
38556
38557     
38558     setMaxValue : function(dt){
38559         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
38560         if(this.menu){
38561             this.menu.picker.setMaxDate(this.maxValue);
38562         }
38563     },
38564
38565     
38566     getErrors: function(value) {
38567         var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
38568
38569         value = this.formatDate(value || this.processValue(this.getRawValue()));
38570
38571         if (value.length < 1) { 
38572              return errors;
38573         }
38574
38575         var svalue = value;
38576         value = this.parseDate(value);
38577         if (!value) {
38578             errors.push(String.format(this.invalidText, svalue, this.format));
38579             return errors;
38580         }
38581
38582         var time = value.getTime();
38583         if (this.minValue && time < this.minValue.clearTime().getTime()) {
38584             errors.push(String.format(this.minText, this.formatDate(this.minValue)));
38585         }
38586
38587         if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
38588             errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
38589         }
38590
38591         if (this.disabledDays) {
38592             var day = value.getDay();
38593
38594             for(var i = 0; i < this.disabledDays.length; i++) {
38595                 if (day === this.disabledDays[i]) {
38596                     errors.push(this.disabledDaysText);
38597                     break;
38598                 }
38599             }
38600         }
38601
38602         var fvalue = this.formatDate(value);
38603         if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
38604             errors.push(String.format(this.disabledDatesText, fvalue));
38605         }
38606
38607         return errors;
38608     },
38609
38610     
38611     
38612     validateBlur : function(){
38613         return !this.menu || !this.menu.isVisible();
38614     },
38615
38616     
38617     getValue : function(){
38618         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
38619     },
38620
38621     
38622     setValue : function(date){
38623         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
38624     },
38625
38626     
38627     parseDate : function(value) {
38628         if(!value || Ext.isDate(value)){
38629             return value;
38630         }
38631
38632         var v = this.safeParse(value, this.format),
38633             af = this.altFormats,
38634             afa = this.altFormatsArray;
38635
38636         if (!v && af) {
38637             afa = afa || af.split("|");
38638
38639             for (var i = 0, len = afa.length; i < len && !v; i++) {
38640                 v = this.safeParse(value, afa[i]);
38641             }
38642         }
38643         return v;
38644     },
38645
38646     
38647     onDestroy : function(){
38648         Ext.destroy(this.menu, this.keyNav);
38649         Ext.form.DateField.superclass.onDestroy.call(this);
38650     },
38651
38652     
38653     formatDate : function(date){
38654         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
38655     },
38656
38657     
38658     
38659     
38660     onTriggerClick : function(){
38661         if(this.disabled){
38662             return;
38663         }
38664         if(this.menu == null){
38665             this.menu = new Ext.menu.DateMenu({
38666                 hideOnClick: false,
38667                 focusOnSelect: false
38668             });
38669         }
38670         this.onFocus();
38671         Ext.apply(this.menu.picker,  {
38672             minDate : this.minValue,
38673             maxDate : this.maxValue,
38674             disabledDatesRE : this.disabledDatesRE,
38675             disabledDatesText : this.disabledDatesText,
38676             disabledDays : this.disabledDays,
38677             disabledDaysText : this.disabledDaysText,
38678             format : this.format,
38679             showToday : this.showToday,
38680             minText : String.format(this.minText, this.formatDate(this.minValue)),
38681             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
38682         });
38683         this.menu.picker.setValue(this.getValue() || new Date());
38684         this.menu.show(this.el, "tl-bl?");
38685         this.menuEvents('on');
38686     },
38687
38688     
38689     menuEvents: function(method){
38690         this.menu[method]('select', this.onSelect, this);
38691         this.menu[method]('hide', this.onMenuHide, this);
38692         this.menu[method]('show', this.onFocus, this);
38693     },
38694
38695     onSelect: function(m, d){
38696         this.setValue(d);
38697         this.fireEvent('select', this, d);
38698         this.menu.hide();
38699     },
38700
38701     onMenuHide: function(){
38702         this.focus(false, 60);
38703         this.menuEvents('un');
38704     },
38705
38706     
38707     beforeBlur : function(){
38708         var v = this.parseDate(this.getRawValue());
38709         if(v){
38710             this.setValue(v);
38711         }
38712     }
38713
38714     
38715     
38716     
38717     
38718 });
38719 Ext.reg('datefield', Ext.form.DateField);
38720
38721 Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
38722     validationEvent : false,
38723     validateOnBlur : false,
38724     defaultAutoCreate : {tag: "div"},
38725     
38726     fieldClass : "x-form-display-field",
38727     
38728     htmlEncode: false,
38729
38730     
38731     initEvents : Ext.emptyFn,
38732
38733     isValid : function(){
38734         return true;
38735     },
38736
38737     validate : function(){
38738         return true;
38739     },
38740
38741     getRawValue : function(){
38742         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
38743         if(v === this.emptyText){
38744             v = '';
38745         }
38746         if(this.htmlEncode){
38747             v = Ext.util.Format.htmlDecode(v);
38748         }
38749         return v;
38750     },
38751
38752     getValue : function(){
38753         return this.getRawValue();
38754     },
38755     
38756     getName: function() {
38757         return this.name;
38758     },
38759
38760     setRawValue : function(v){
38761         if(this.htmlEncode){
38762             v = Ext.util.Format.htmlEncode(v);
38763         }
38764         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
38765     },
38766
38767     setValue : function(v){
38768         this.setRawValue(v);
38769         return this;
38770     }
38771     
38772     
38773     
38774     
38775     
38776     
38777 });
38778
38779 Ext.reg('displayfield', Ext.form.DisplayField);
38780
38781 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
38782     
38783     
38784     
38785     
38786     
38787
38788     
38789     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
38790     
38791     
38792     
38793     
38794     
38795     
38796     
38797     listClass : '',
38798     
38799     selectedClass : 'x-combo-selected',
38800     
38801     listEmptyText: '',
38802     
38803     triggerClass : 'x-form-arrow-trigger',
38804     
38805     shadow : 'sides',
38806     
38807     listAlign : 'tl-bl?',
38808     
38809     maxHeight : 300,
38810     
38811     minHeight : 90,
38812     
38813     triggerAction : 'query',
38814     
38815     minChars : 4,
38816     
38817     autoSelect : true,
38818     
38819     typeAhead : false,
38820     
38821     queryDelay : 500,
38822     
38823     pageSize : 0,
38824     
38825     selectOnFocus : false,
38826     
38827     queryParam : 'query',
38828     
38829     loadingText : 'Loading...',
38830     
38831     resizable : false,
38832     
38833     handleHeight : 8,
38834     
38835     allQuery: '',
38836     
38837     mode: 'remote',
38838     
38839     minListWidth : 70,
38840     
38841     forceSelection : false,
38842     
38843     typeAheadDelay : 250,
38844     
38845
38846     
38847     lazyInit : true,
38848
38849     
38850     clearFilterOnReset : true,
38851
38852     
38853     submitValue: undefined,
38854
38855     
38856
38857     
38858     initComponent : function(){
38859         Ext.form.ComboBox.superclass.initComponent.call(this);
38860         this.addEvents(
38861             
38862             'expand',
38863             
38864             'collapse',
38865
38866             
38867             'beforeselect',
38868             
38869             'select',
38870             
38871             'beforequery'
38872         );
38873         if(this.transform){
38874             var s = Ext.getDom(this.transform);
38875             if(!this.hiddenName){
38876                 this.hiddenName = s.name;
38877             }
38878             if(!this.store){
38879                 this.mode = 'local';
38880                 var d = [], opts = s.options;
38881                 for(var i = 0, len = opts.length;i < len; i++){
38882                     var o = opts[i],
38883                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
38884                     if(o.selected && Ext.isEmpty(this.value, true)) {
38885                         this.value = value;
38886                     }
38887                     d.push([value, o.text]);
38888                 }
38889                 this.store = new Ext.data.ArrayStore({
38890                     'id': 0,
38891                     fields: ['value', 'text'],
38892                     data : d,
38893                     autoDestroy: true
38894                 });
38895                 this.valueField = 'value';
38896                 this.displayField = 'text';
38897             }
38898             s.name = Ext.id(); 
38899             if(!this.lazyRender){
38900                 this.target = true;
38901                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
38902                 this.render(this.el.parentNode, s);
38903             }
38904             Ext.removeNode(s);
38905         }
38906         
38907         else if(this.store){
38908             this.store = Ext.StoreMgr.lookup(this.store);
38909             if(this.store.autoCreated){
38910                 this.displayField = this.valueField = 'field1';
38911                 if(!this.store.expandData){
38912                     this.displayField = 'field2';
38913                 }
38914                 this.mode = 'local';
38915             }
38916         }
38917
38918         this.selectedIndex = -1;
38919         if(this.mode == 'local'){
38920             if(!Ext.isDefined(this.initialConfig.queryDelay)){
38921                 this.queryDelay = 10;
38922             }
38923             if(!Ext.isDefined(this.initialConfig.minChars)){
38924                 this.minChars = 0;
38925             }
38926         }
38927     },
38928
38929     
38930     onRender : function(ct, position){
38931         if(this.hiddenName && !Ext.isDefined(this.submitValue)){
38932             this.submitValue = false;
38933         }
38934         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
38935         if(this.hiddenName){
38936             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
38937                     id: (this.hiddenId||this.hiddenName)}, 'before', true);
38938
38939         }
38940         if(Ext.isGecko){
38941             this.el.dom.setAttribute('autocomplete', 'off');
38942         }
38943
38944         if(!this.lazyInit){
38945             this.initList();
38946         }else{
38947             this.on('focus', this.initList, this, {single: true});
38948         }
38949     },
38950
38951     
38952     initValue : function(){
38953         Ext.form.ComboBox.superclass.initValue.call(this);
38954         if(this.hiddenField){
38955             this.hiddenField.value =
38956                 Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
38957         }
38958     },
38959
38960     getParentZIndex : function(){
38961         var zindex;
38962         if (this.ownerCt){
38963             this.findParentBy(function(ct){
38964                 zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
38965                 return !!zindex;
38966             });
38967         }
38968         return zindex;
38969     },
38970     
38971     getZIndex : function(listParent){
38972         listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
38973         var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
38974         if(!zindex){
38975             zindex = this.getParentZIndex();
38976         }
38977         return (zindex || 12000) + 5;
38978     },
38979
38980     
38981     initList : function(){
38982         if(!this.list){
38983             var cls = 'x-combo-list',
38984                 listParent = Ext.getDom(this.getListParent() || Ext.getBody());
38985
38986             this.list = new Ext.Layer({
38987                 parentEl: listParent,
38988                 shadow: this.shadow,
38989                 cls: [cls, this.listClass].join(' '),
38990                 constrain:false,
38991                 zindex: this.getZIndex(listParent)
38992             });
38993
38994             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
38995             this.list.setSize(lw, 0);
38996             this.list.swallowEvent('mousewheel');
38997             this.assetHeight = 0;
38998             if(this.syncFont !== false){
38999                 this.list.setStyle('font-size', this.el.getStyle('font-size'));
39000             }
39001             if(this.title){
39002                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
39003                 this.assetHeight += this.header.getHeight();
39004             }
39005
39006             this.innerList = this.list.createChild({cls:cls+'-inner'});
39007             this.mon(this.innerList, 'mouseover', this.onViewOver, this);
39008             this.mon(this.innerList, 'mousemove', this.onViewMove, this);
39009             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
39010
39011             if(this.pageSize){
39012                 this.footer = this.list.createChild({cls:cls+'-ft'});
39013                 this.pageTb = new Ext.PagingToolbar({
39014                     store: this.store,
39015                     pageSize: this.pageSize,
39016                     renderTo:this.footer
39017                 });
39018                 this.assetHeight += this.footer.getHeight();
39019             }
39020
39021             if(!this.tpl){
39022                 
39023                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
39024                 
39025             }
39026
39027             
39028             this.view = new Ext.DataView({
39029                 applyTo: this.innerList,
39030                 tpl: this.tpl,
39031                 singleSelect: true,
39032                 selectedClass: this.selectedClass,
39033                 itemSelector: this.itemSelector || '.' + cls + '-item',
39034                 emptyText: this.listEmptyText,
39035                 deferEmptyText: false
39036             });
39037
39038             this.mon(this.view, {
39039                 containerclick : this.onViewClick,
39040                 click : this.onViewClick,
39041                 scope :this
39042             });
39043
39044             this.bindStore(this.store, true);
39045
39046             if(this.resizable){
39047                 this.resizer = new Ext.Resizable(this.list,  {
39048                    pinned:true, handles:'se'
39049                 });
39050                 this.mon(this.resizer, 'resize', function(r, w, h){
39051                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
39052                     this.listWidth = w;
39053                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
39054                     this.restrictHeight();
39055                 }, this);
39056
39057                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
39058             }
39059         }
39060     },
39061
39062     
39063     getListParent : function() {
39064         return document.body;
39065     },
39066
39067     
39068     getStore : function(){
39069         return this.store;
39070     },
39071
39072     
39073     bindStore : function(store, initial){
39074         if(this.store && !initial){
39075             if(this.store !== store && this.store.autoDestroy){
39076                 this.store.destroy();
39077             }else{
39078                 this.store.un('beforeload', this.onBeforeLoad, this);
39079                 this.store.un('load', this.onLoad, this);
39080                 this.store.un('exception', this.collapse, this);
39081             }
39082             if(!store){
39083                 this.store = null;
39084                 if(this.view){
39085                     this.view.bindStore(null);
39086                 }
39087                 if(this.pageTb){
39088                     this.pageTb.bindStore(null);
39089                 }
39090             }
39091         }
39092         if(store){
39093             if(!initial) {
39094                 this.lastQuery = null;
39095                 if(this.pageTb) {
39096                     this.pageTb.bindStore(store);
39097                 }
39098             }
39099
39100             this.store = Ext.StoreMgr.lookup(store);
39101             this.store.on({
39102                 scope: this,
39103                 beforeload: this.onBeforeLoad,
39104                 load: this.onLoad,
39105                 exception: this.collapse
39106             });
39107
39108             if(this.view){
39109                 this.view.bindStore(store);
39110             }
39111         }
39112     },
39113
39114     reset : function(){
39115         Ext.form.ComboBox.superclass.reset.call(this);
39116         if(this.clearFilterOnReset && this.mode == 'local'){
39117             this.store.clearFilter();
39118         }
39119     },
39120
39121     
39122     initEvents : function(){
39123         Ext.form.ComboBox.superclass.initEvents.call(this);
39124
39125         
39126         this.keyNav = new Ext.KeyNav(this.el, {
39127             "up" : function(e){
39128                 this.inKeyMode = true;
39129                 this.selectPrev();
39130             },
39131
39132             "down" : function(e){
39133                 if(!this.isExpanded()){
39134                     this.onTriggerClick();
39135                 }else{
39136                     this.inKeyMode = true;
39137                     this.selectNext();
39138                 }
39139             },
39140
39141             "enter" : function(e){
39142                 this.onViewClick();
39143             },
39144
39145             "esc" : function(e){
39146                 this.collapse();
39147             },
39148
39149             "tab" : function(e){
39150                 if (this.forceSelection === true) {
39151                     this.collapse();
39152                 } else {
39153                     this.onViewClick(false);
39154                 }
39155                 return true;
39156             },
39157
39158             scope : this,
39159
39160             doRelay : function(e, h, hname){
39161                 if(hname == 'down' || this.scope.isExpanded()){
39162                     
39163                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
39164                     if(!Ext.isIE && Ext.EventManager.useKeydown){
39165                         
39166                         this.scope.fireKey(e);
39167                     }
39168                     return relay;
39169                 }
39170                 return true;
39171             },
39172
39173             forceKeyDown : true,
39174             defaultEventAction: 'stopEvent'
39175         });
39176         this.queryDelay = Math.max(this.queryDelay || 10,
39177                 this.mode == 'local' ? 10 : 250);
39178         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
39179         if(this.typeAhead){
39180             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
39181         }
39182         if(!this.enableKeyEvents){
39183             this.mon(this.el, 'keyup', this.onKeyUp, this);
39184         }
39185     },
39186
39187
39188     
39189     onDestroy : function(){
39190         if (this.dqTask){
39191             this.dqTask.cancel();
39192             this.dqTask = null;
39193         }
39194         this.bindStore(null);
39195         Ext.destroy(
39196             this.resizer,
39197             this.view,
39198             this.pageTb,
39199             this.list
39200         );
39201         Ext.destroyMembers(this, 'hiddenField');
39202         Ext.form.ComboBox.superclass.onDestroy.call(this);
39203     },
39204
39205     
39206     fireKey : function(e){
39207         if (!this.isExpanded()) {
39208             Ext.form.ComboBox.superclass.fireKey.call(this, e);
39209         }
39210     },
39211
39212     
39213     onResize : function(w, h){
39214         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
39215         if(!isNaN(w) && this.isVisible() && this.list){
39216             this.doResize(w);
39217         }else{
39218             this.bufferSize = w;
39219         }
39220     },
39221
39222     doResize: function(w){
39223         if(!Ext.isDefined(this.listWidth)){
39224             var lw = Math.max(w, this.minListWidth);
39225             this.list.setWidth(lw);
39226             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
39227         }
39228     },
39229
39230     
39231     onEnable : function(){
39232         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
39233         if(this.hiddenField){
39234             this.hiddenField.disabled = false;
39235         }
39236     },
39237
39238     
39239     onDisable : function(){
39240         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
39241         if(this.hiddenField){
39242             this.hiddenField.disabled = true;
39243         }
39244     },
39245
39246     
39247     onBeforeLoad : function(){
39248         if(!this.hasFocus){
39249             return;
39250         }
39251         this.innerList.update(this.loadingText ?
39252                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
39253         this.restrictHeight();
39254         this.selectedIndex = -1;
39255     },
39256
39257     
39258     onLoad : function(){
39259         if(!this.hasFocus){
39260             return;
39261         }
39262         if(this.store.getCount() > 0 || this.listEmptyText){
39263             this.expand();
39264             this.restrictHeight();
39265             if(this.lastQuery == this.allQuery){
39266                 if(this.editable){
39267                     this.el.dom.select();
39268                 }
39269
39270                 if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
39271                     this.select(0, true);
39272                 }
39273             }else{
39274                 if(this.autoSelect !== false){
39275                     this.selectNext();
39276                 }
39277                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
39278                     this.taTask.delay(this.typeAheadDelay);
39279                 }
39280             }
39281         }else{
39282             this.collapse();
39283         }
39284
39285     },
39286
39287     
39288     onTypeAhead : function(){
39289         if(this.store.getCount() > 0){
39290             var r = this.store.getAt(0);
39291             var newValue = r.data[this.displayField];
39292             var len = newValue.length;
39293             var selStart = this.getRawValue().length;
39294             if(selStart != len){
39295                 this.setRawValue(newValue);
39296                 this.selectText(selStart, newValue.length);
39297             }
39298         }
39299     },
39300
39301     
39302     assertValue  : function(){
39303         var val = this.getRawValue(),
39304             rec = this.findRecord(this.displayField, val);
39305
39306         if(!rec && this.forceSelection){
39307             if(val.length > 0 && val != this.emptyText){
39308                 this.el.dom.value = Ext.value(this.lastSelectionText, '');
39309                 this.applyEmptyText();
39310             }else{
39311                 this.clearValue();
39312             }
39313         }else{
39314             if(rec){
39315                 
39316                 
39317                 
39318                 if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
39319                     return;
39320                 }
39321                 val = rec.get(this.valueField || this.displayField);
39322             }
39323             this.setValue(val);
39324         }
39325     },
39326
39327     
39328     onSelect : function(record, index){
39329         if(this.fireEvent('beforeselect', this, record, index) !== false){
39330             this.setValue(record.data[this.valueField || this.displayField]);
39331             this.collapse();
39332             this.fireEvent('select', this, record, index);
39333         }
39334     },
39335
39336     
39337     getName: function(){
39338         var hf = this.hiddenField;
39339         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
39340     },
39341
39342     
39343     getValue : function(){
39344         if(this.valueField){
39345             return Ext.isDefined(this.value) ? this.value : '';
39346         }else{
39347             return Ext.form.ComboBox.superclass.getValue.call(this);
39348         }
39349     },
39350
39351     
39352     clearValue : function(){
39353         if(this.hiddenField){
39354             this.hiddenField.value = '';
39355         }
39356         this.setRawValue('');
39357         this.lastSelectionText = '';
39358         this.applyEmptyText();
39359         this.value = '';
39360     },
39361
39362     
39363     setValue : function(v){
39364         var text = v;
39365         if(this.valueField){
39366             var r = this.findRecord(this.valueField, v);
39367             if(r){
39368                 text = r.data[this.displayField];
39369             }else if(Ext.isDefined(this.valueNotFoundText)){
39370                 text = this.valueNotFoundText;
39371             }
39372         }
39373         this.lastSelectionText = text;
39374         if(this.hiddenField){
39375             this.hiddenField.value = Ext.value(v, '');
39376         }
39377         Ext.form.ComboBox.superclass.setValue.call(this, text);
39378         this.value = v;
39379         return this;
39380     },
39381
39382     
39383     findRecord : function(prop, value){
39384         var record;
39385         if(this.store.getCount() > 0){
39386             this.store.each(function(r){
39387                 if(r.data[prop] == value){
39388                     record = r;
39389                     return false;
39390                 }
39391             });
39392         }
39393         return record;
39394     },
39395
39396     
39397     onViewMove : function(e, t){
39398         this.inKeyMode = false;
39399     },
39400
39401     
39402     onViewOver : function(e, t){
39403         if(this.inKeyMode){ 
39404             return;
39405         }
39406         var item = this.view.findItemFromChild(t);
39407         if(item){
39408             var index = this.view.indexOf(item);
39409             this.select(index, false);
39410         }
39411     },
39412
39413     
39414     onViewClick : function(doFocus){
39415         var index = this.view.getSelectedIndexes()[0],
39416             s = this.store,
39417             r = s.getAt(index);
39418         if(r){
39419             this.onSelect(r, index);
39420         }else {
39421             this.collapse();
39422         }
39423         if(doFocus !== false){
39424             this.el.focus();
39425         }
39426     },
39427
39428
39429     
39430     restrictHeight : function(){
39431         this.innerList.dom.style.height = '';
39432         var inner = this.innerList.dom,
39433             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
39434             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
39435             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
39436             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
39437             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
39438
39439         h = Math.min(h, space, this.maxHeight);
39440
39441         this.innerList.setHeight(h);
39442         this.list.beginUpdate();
39443         this.list.setHeight(h+pad);
39444         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
39445         this.list.endUpdate();
39446     },
39447
39448     
39449     isExpanded : function(){
39450         return this.list && this.list.isVisible();
39451     },
39452
39453     
39454     selectByValue : function(v, scrollIntoView){
39455         if(!Ext.isEmpty(v, true)){
39456             var r = this.findRecord(this.valueField || this.displayField, v);
39457             if(r){
39458                 this.select(this.store.indexOf(r), scrollIntoView);
39459                 return true;
39460             }
39461         }
39462         return false;
39463     },
39464
39465     
39466     select : function(index, scrollIntoView){
39467         this.selectedIndex = index;
39468         this.view.select(index);
39469         if(scrollIntoView !== false){
39470             var el = this.view.getNode(index);
39471             if(el){
39472                 this.innerList.scrollChildIntoView(el, false);
39473             }
39474         }
39475
39476     },
39477
39478     
39479     selectNext : function(){
39480         var ct = this.store.getCount();
39481         if(ct > 0){
39482             if(this.selectedIndex == -1){
39483                 this.select(0);
39484             }else if(this.selectedIndex < ct-1){
39485                 this.select(this.selectedIndex+1);
39486             }
39487         }
39488     },
39489
39490     
39491     selectPrev : function(){
39492         var ct = this.store.getCount();
39493         if(ct > 0){
39494             if(this.selectedIndex == -1){
39495                 this.select(0);
39496             }else if(this.selectedIndex !== 0){
39497                 this.select(this.selectedIndex-1);
39498             }
39499         }
39500     },
39501
39502     
39503     onKeyUp : function(e){
39504         var k = e.getKey();
39505         if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
39506
39507             this.lastKey = k;
39508             this.dqTask.delay(this.queryDelay);
39509         }
39510         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
39511     },
39512
39513     
39514     validateBlur : function(){
39515         return !this.list || !this.list.isVisible();
39516     },
39517
39518     
39519     initQuery : function(){
39520         this.doQuery(this.getRawValue());
39521     },
39522
39523     
39524     beforeBlur : function(){
39525         this.assertValue();
39526     },
39527
39528     
39529     postBlur  : function(){
39530         Ext.form.ComboBox.superclass.postBlur.call(this);
39531         this.collapse();
39532         this.inKeyMode = false;
39533     },
39534
39535     
39536     doQuery : function(q, forceAll){
39537         q = Ext.isEmpty(q) ? '' : q;
39538         var qe = {
39539             query: q,
39540             forceAll: forceAll,
39541             combo: this,
39542             cancel:false
39543         };
39544         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
39545             return false;
39546         }
39547         q = qe.query;
39548         forceAll = qe.forceAll;
39549         if(forceAll === true || (q.length >= this.minChars)){
39550             if(this.lastQuery !== q){
39551                 this.lastQuery = q;
39552                 if(this.mode == 'local'){
39553                     this.selectedIndex = -1;
39554                     if(forceAll){
39555                         this.store.clearFilter();
39556                     }else{
39557                         this.store.filter(this.displayField, q);
39558                     }
39559                     this.onLoad();
39560                 }else{
39561                     this.store.baseParams[this.queryParam] = q;
39562                     this.store.load({
39563                         params: this.getParams(q)
39564                     });
39565                     this.expand();
39566                 }
39567             }else{
39568                 this.selectedIndex = -1;
39569                 this.onLoad();
39570             }
39571         }
39572     },
39573
39574     
39575     getParams : function(q){
39576         var p = {};
39577         
39578         if(this.pageSize){
39579             p.start = 0;
39580             p.limit = this.pageSize;
39581         }
39582         return p;
39583     },
39584
39585     
39586     collapse : function(){
39587         if(!this.isExpanded()){
39588             return;
39589         }
39590         this.list.hide();
39591         Ext.getDoc().un('mousewheel', this.collapseIf, this);
39592         Ext.getDoc().un('mousedown', this.collapseIf, this);
39593         this.fireEvent('collapse', this);
39594     },
39595
39596     
39597     collapseIf : function(e){
39598         if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
39599             this.collapse();
39600         }
39601     },
39602
39603     
39604     expand : function(){
39605         if(this.isExpanded() || !this.hasFocus){
39606             return;
39607         }
39608
39609         if(this.title || this.pageSize){
39610             this.assetHeight = 0;
39611             if(this.title){
39612                 this.assetHeight += this.header.getHeight();
39613             }
39614             if(this.pageSize){
39615                 this.assetHeight += this.footer.getHeight();
39616             }
39617         }
39618
39619         if(this.bufferSize){
39620             this.doResize(this.bufferSize);
39621             delete this.bufferSize;
39622         }
39623         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
39624
39625         
39626         this.list.setZIndex(this.getZIndex());
39627         this.list.show();
39628         if(Ext.isGecko2){
39629             this.innerList.setOverflow('auto'); 
39630         }
39631         this.mon(Ext.getDoc(), {
39632             scope: this,
39633             mousewheel: this.collapseIf,
39634             mousedown: this.collapseIf
39635         });
39636         this.fireEvent('expand', this);
39637     },
39638
39639     
39640     
39641     
39642     onTriggerClick : function(){
39643         if(this.readOnly || this.disabled){
39644             return;
39645         }
39646         if(this.isExpanded()){
39647             this.collapse();
39648             this.el.focus();
39649         }else {
39650             this.onFocus({});
39651             if(this.triggerAction == 'all') {
39652                 this.doQuery(this.allQuery, true);
39653             } else {
39654                 this.doQuery(this.getRawValue());
39655             }
39656             this.el.focus();
39657         }
39658     }
39659
39660     
39661     
39662     
39663     
39664
39665 });
39666 Ext.reg('combo', Ext.form.ComboBox);
39667
39668 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
39669     
39670     focusClass : undefined,
39671     
39672     fieldClass : 'x-form-field',
39673     
39674     checked : false,
39675     
39676     boxLabel: '&#160;',
39677     
39678     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
39679     
39680     
39681     
39682     
39683
39684     
39685     actionMode : 'wrap',
39686
39687         
39688     initComponent : function(){
39689         Ext.form.Checkbox.superclass.initComponent.call(this);
39690         this.addEvents(
39691             
39692             'check'
39693         );
39694     },
39695
39696     
39697     onResize : function(){
39698         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
39699         if(!this.boxLabel && !this.fieldLabel){
39700             this.el.alignTo(this.wrap, 'c-c');
39701         }
39702     },
39703
39704     
39705     initEvents : function(){
39706         Ext.form.Checkbox.superclass.initEvents.call(this);
39707         this.mon(this.el, {
39708             scope: this,
39709             click: this.onClick,
39710             change: this.onClick
39711         });
39712     },
39713
39714     
39715     markInvalid : Ext.emptyFn,
39716     
39717     clearInvalid : Ext.emptyFn,
39718
39719     
39720     onRender : function(ct, position){
39721         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
39722         if(this.inputValue !== undefined){
39723             this.el.dom.value = this.inputValue;
39724         }
39725         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
39726         if(this.boxLabel){
39727             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
39728         }
39729         if(this.checked){
39730             this.setValue(true);
39731         }else{
39732             this.checked = this.el.dom.checked;
39733         }
39734         
39735         if (Ext.isIE && !Ext.isStrict) {
39736             this.wrap.repaint();
39737         }
39738         this.resizeEl = this.positionEl = this.wrap;
39739     },
39740
39741     
39742     onDestroy : function(){
39743         Ext.destroy(this.wrap);
39744         Ext.form.Checkbox.superclass.onDestroy.call(this);
39745     },
39746
39747     
39748     initValue : function() {
39749         this.originalValue = this.getValue();
39750     },
39751
39752     
39753     getValue : function(){
39754         if(this.rendered){
39755             return this.el.dom.checked;
39756         }
39757         return this.checked;
39758     },
39759
39760         
39761     onClick : function(){
39762         if(this.el.dom.checked != this.checked){
39763             this.setValue(this.el.dom.checked);
39764         }
39765     },
39766
39767     
39768     setValue : function(v){
39769         var checked = this.checked ;
39770         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
39771         if(this.rendered){
39772             this.el.dom.checked = this.checked;
39773             this.el.dom.defaultChecked = this.checked;
39774         }
39775         if(checked != this.checked){
39776             this.fireEvent('check', this, this.checked);
39777             if(this.handler){
39778                 this.handler.call(this.scope || this, this, this.checked);
39779             }
39780         }
39781         return this;
39782     }
39783 });
39784 Ext.reg('checkbox', Ext.form.Checkbox);
39785
39786 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
39787     
39788     
39789     columns : 'auto',
39790     
39791     vertical : false,
39792     
39793     allowBlank : true,
39794     
39795     blankText : "You must select at least one item in this group",
39796
39797     
39798     defaultType : 'checkbox',
39799
39800     
39801     groupCls : 'x-form-check-group',
39802
39803     
39804     initComponent: function(){
39805         this.addEvents(
39806             
39807             'change'
39808         );
39809         this.on('change', this.validate, this);
39810         Ext.form.CheckboxGroup.superclass.initComponent.call(this);
39811     },
39812
39813     
39814     onRender : function(ct, position){
39815         if(!this.el){
39816             var panelCfg = {
39817                 autoEl: {
39818                     id: this.id
39819                 },
39820                 cls: this.groupCls,
39821                 layout: 'column',
39822                 renderTo: ct,
39823                 bufferResize: false 
39824             };
39825             var colCfg = {
39826                 xtype: 'container',
39827                 defaultType: this.defaultType,
39828                 layout: 'form',
39829                 defaults: {
39830                     hideLabel: true,
39831                     anchor: '100%'
39832                 }
39833             };
39834
39835             if(this.items[0].items){
39836
39837                 
39838
39839                 Ext.apply(panelCfg, {
39840                     layoutConfig: {columns: this.items.length},
39841                     defaults: this.defaults,
39842                     items: this.items
39843                 });
39844                 for(var i=0, len=this.items.length; i<len; i++){
39845                     Ext.applyIf(this.items[i], colCfg);
39846                 }
39847
39848             }else{
39849
39850                 
39851                 
39852
39853                 var numCols, cols = [];
39854
39855                 if(typeof this.columns == 'string'){ 
39856                     this.columns = this.items.length;
39857                 }
39858                 if(!Ext.isArray(this.columns)){
39859                     var cs = [];
39860                     for(var i=0; i<this.columns; i++){
39861                         cs.push((100/this.columns)*.01); 
39862                     }
39863                     this.columns = cs;
39864                 }
39865
39866                 numCols = this.columns.length;
39867
39868                 
39869                 for(var i=0; i<numCols; i++){
39870                     var cc = Ext.apply({items:[]}, colCfg);
39871                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
39872                     if(this.defaults){
39873                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
39874                     }
39875                     cols.push(cc);
39876                 };
39877
39878                 
39879                 if(this.vertical){
39880                     var rows = Math.ceil(this.items.length / numCols), ri = 0;
39881                     for(var i=0, len=this.items.length; i<len; i++){
39882                         if(i>0 && i%rows==0){
39883                             ri++;
39884                         }
39885                         if(this.items[i].fieldLabel){
39886                             this.items[i].hideLabel = false;
39887                         }
39888                         cols[ri].items.push(this.items[i]);
39889                     };
39890                 }else{
39891                     for(var i=0, len=this.items.length; i<len; i++){
39892                         var ci = i % numCols;
39893                         if(this.items[i].fieldLabel){
39894                             this.items[i].hideLabel = false;
39895                         }
39896                         cols[ci].items.push(this.items[i]);
39897                     };
39898                 }
39899
39900                 Ext.apply(panelCfg, {
39901                     layoutConfig: {columns: numCols},
39902                     items: cols
39903                 });
39904             }
39905
39906             this.panel = new Ext.Container(panelCfg);
39907             this.panel.ownerCt = this;
39908             this.el = this.panel.getEl();
39909
39910             if(this.forId && this.itemCls){
39911                 var l = this.el.up(this.itemCls).child('label', true);
39912                 if(l){
39913                     l.setAttribute('htmlFor', this.forId);
39914                 }
39915             }
39916
39917             var fields = this.panel.findBy(function(c){
39918                 return c.isFormField;
39919             }, this);
39920
39921             this.items = new Ext.util.MixedCollection();
39922             this.items.addAll(fields);
39923         }
39924         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
39925     },
39926
39927     initValue : function(){
39928         if(this.value){
39929             this.setValue.apply(this, this.buffered ? this.value : [this.value]);
39930             delete this.buffered;
39931             delete this.value;
39932         }
39933     },
39934
39935     afterRender : function(){
39936         Ext.form.CheckboxGroup.superclass.afterRender.call(this);
39937         this.eachItem(function(item){
39938             item.on('check', this.fireChecked, this);
39939             item.inGroup = true;
39940         });
39941     },
39942
39943     
39944     doLayout: function(){
39945         
39946         if(this.rendered){
39947             this.panel.forceLayout = this.ownerCt.forceLayout;
39948             this.panel.doLayout();
39949         }
39950     },
39951
39952     
39953     fireChecked: function(){
39954         var arr = [];
39955         this.eachItem(function(item){
39956             if(item.checked){
39957                 arr.push(item);
39958             }
39959         });
39960         this.fireEvent('change', this, arr);
39961     },
39962     
39963     
39964     getErrors: function() {
39965         var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
39966         
39967         if (!this.allowBlank) {
39968             var blank = true;
39969             
39970             this.eachItem(function(f){
39971                 if (f.checked) {
39972                     return (blank = false);
39973                 }
39974             });
39975             
39976             if (blank) errors.push(this.blankText);
39977         }
39978         
39979         return errors;
39980     },
39981
39982     
39983     isDirty: function(){
39984         
39985         if (this.disabled || !this.rendered) {
39986             return false;
39987         }
39988
39989         var dirty = false;
39990         
39991         this.eachItem(function(item){
39992             if(item.isDirty()){
39993                 dirty = true;
39994                 return false;
39995             }
39996         });
39997         
39998         return dirty;
39999     },
40000
40001     
40002     setReadOnly : function(readOnly){
40003         if(this.rendered){
40004             this.eachItem(function(item){
40005                 item.setReadOnly(readOnly);
40006             });
40007         }
40008         this.readOnly = readOnly;
40009     },
40010
40011     
40012     onDisable : function(){
40013         this.eachItem(function(item){
40014             item.disable();
40015         });
40016     },
40017
40018     
40019     onEnable : function(){
40020         this.eachItem(function(item){
40021             item.enable();
40022         });
40023     },
40024
40025     
40026     onResize : function(w, h){
40027         this.panel.setSize(w, h);
40028         this.panel.doLayout();
40029     },
40030
40031     
40032     reset : function(){
40033         if (this.originalValue) {
40034             
40035             this.eachItem(function(c){
40036                 if(c.setValue){
40037                     c.setValue(false);
40038                     c.originalValue = c.getValue();
40039                 }
40040             });
40041             
40042             
40043             this.resetOriginal = true;
40044             this.setValue(this.originalValue);
40045             delete this.resetOriginal;
40046         } else {
40047             this.eachItem(function(c){
40048                 if(c.reset){
40049                     c.reset();
40050                 }
40051             });
40052         }
40053         
40054         
40055         (function() {
40056             this.clearInvalid();
40057         }).defer(50, this);
40058     },
40059
40060     
40061     setValue: function(){
40062         if(this.rendered){
40063             this.onSetValue.apply(this, arguments);
40064         }else{
40065             this.buffered = true;
40066             this.value = arguments;
40067         }
40068         return this;
40069     },
40070
40071     
40072     onSetValue: function(id, value){
40073         if(arguments.length == 1){
40074             if(Ext.isArray(id)){
40075                 Ext.each(id, function(val, idx){
40076                     if (Ext.isObject(val) && val.setValue){ 
40077                         val.setValue(true);
40078                         if (this.resetOriginal === true) {
40079                             val.originalValue = val.getValue();
40080                         }
40081                     } else { 
40082                         var item = this.items.itemAt(idx);
40083                         if(item){
40084                             item.setValue(val);
40085                         }
40086                     }
40087                 }, this);
40088             }else if(Ext.isObject(id)){
40089                 
40090                 for(var i in id){
40091                     var f = this.getBox(i);
40092                     if(f){
40093                         f.setValue(id[i]);
40094                     }
40095                 }
40096             }else{
40097                 this.setValueForItem(id);
40098             }
40099         }else{
40100             var f = this.getBox(id);
40101             if(f){
40102                 f.setValue(value);
40103             }
40104         }
40105     },
40106
40107     
40108     beforeDestroy: function(){
40109         Ext.destroy(this.panel);
40110         Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
40111
40112     },
40113
40114     setValueForItem : function(val){
40115         val = String(val).split(',');
40116         this.eachItem(function(item){
40117             if(val.indexOf(item.inputValue)> -1){
40118                 item.setValue(true);
40119             }
40120         });
40121     },
40122
40123     
40124     getBox : function(id){
40125         var box = null;
40126         this.eachItem(function(f){
40127             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
40128                 box = f;
40129                 return false;
40130             }
40131         });
40132         return box;
40133     },
40134
40135     
40136     getValue : function(){
40137         var out = [];
40138         this.eachItem(function(item){
40139             if(item.checked){
40140                 out.push(item);
40141             }
40142         });
40143         return out;
40144     },
40145
40146     
40147     eachItem: function(fn, scope) {
40148         if(this.items && this.items.each){
40149             this.items.each(fn, scope || this);
40150         }
40151     },
40152
40153     
40154
40155     
40156     getRawValue : Ext.emptyFn,
40157
40158     
40159     setRawValue : Ext.emptyFn
40160
40161 });
40162
40163 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
40164
40165 Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
40166
40167     
40168     defaultMargins: '0 5 0 0',
40169
40170     
40171     skipLastItemMargin: true,
40172
40173     
40174     isComposite: true,
40175
40176     
40177     combineErrors: true,
40178     
40179     
40180     labelConnector: ', ',
40181
40182     
40183     
40184     initComponent: function() {
40185         var labels = [],
40186             items  = this.items,
40187             item;
40188
40189         for (var i=0, j = items.length; i < j; i++) {
40190             item = items[i];
40191
40192             labels.push(item.fieldLabel);
40193
40194             
40195             Ext.apply(item, this.defaults);
40196
40197             
40198             if (!(i == j - 1 && this.skipLastItemMargin)) {
40199                 Ext.applyIf(item, {margins: this.defaultMargins});
40200             }
40201         }
40202
40203         this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
40204
40205         
40206         this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
40207             return item.field;
40208         });
40209
40210         this.fieldErrors.on({
40211             scope  : this,
40212             add    : this.updateInvalidMark,
40213             remove : this.updateInvalidMark,
40214             replace: this.updateInvalidMark
40215         });
40216
40217         Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
40218     },
40219
40220     
40221     onRender: function(ct, position) {
40222         if (!this.el) {
40223             
40224             var innerCt = this.innerCt = new Ext.Container({
40225                 layout  : 'hbox',
40226                 renderTo: ct,
40227                 items   : this.items,
40228                 cls     : 'x-form-composite',
40229                 defaultMargins: '0 3 0 0'
40230             });
40231
40232             this.el = innerCt.getEl();
40233
40234             var fields = innerCt.findBy(function(c) {
40235                 return c.isFormField;
40236             }, this);
40237
40238             
40239             this.items = new Ext.util.MixedCollection();
40240             this.items.addAll(fields);
40241
40242             
40243             
40244             if (this.combineErrors) {
40245                 this.eachItem(function(field) {
40246                     Ext.apply(field, {
40247                         markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
40248                         clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
40249                     });
40250                 });
40251             }
40252
40253             
40254             var l = this.el.parent().parent().child('label', true);
40255             if (l) {
40256                 l.setAttribute('for', this.items.items[0].id);
40257             }
40258         }
40259
40260         Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
40261     },
40262
40263     
40264     onFieldMarkInvalid: function(field, message) {
40265         var name  = field.getName(),
40266             error = {field: name, error: message};
40267
40268         this.fieldErrors.replace(name, error);
40269
40270         field.el.addClass(field.invalidClass);
40271     },
40272
40273     
40274     onFieldClearInvalid: function(field) {
40275         this.fieldErrors.removeKey(field.getName());
40276
40277         field.el.removeClass(field.invalidClass);
40278     },
40279
40280     
40281     updateInvalidMark: function() {
40282         var ieStrict = Ext.isIE6 && Ext.isStrict;
40283
40284         if (this.fieldErrors.length == 0) {
40285             this.clearInvalid();
40286
40287             
40288             if (ieStrict) {
40289                 this.clearInvalid.defer(50, this);
40290             }
40291         } else {
40292             var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
40293
40294             this.sortErrors();
40295             this.markInvalid(message);
40296
40297             
40298             if (ieStrict) {
40299                 this.markInvalid(message);
40300             }
40301         }
40302     },
40303
40304     
40305     validateValue: function() {
40306         var valid = true;
40307
40308         this.eachItem(function(field) {
40309             if (!field.isValid()) valid = false;
40310         });
40311
40312         return valid;
40313     },
40314
40315     
40316     buildCombinedErrorMessage: function(errors) {
40317         var combined = [],
40318             error;
40319
40320         for (var i = 0, j = errors.length; i < j; i++) {
40321             error = errors[i];
40322
40323             combined.push(String.format("{0}: {1}", error.field, error.error));
40324         }
40325
40326         return combined.join("<br />");
40327     },
40328
40329     
40330     sortErrors: function() {
40331         var fields = this.items;
40332
40333         this.fieldErrors.sort("ASC", function(a, b) {
40334             var findByName = function(key) {
40335                 return function(field) {
40336                     return field.getName() == key;
40337                 };
40338             };
40339
40340             var aIndex = fields.findIndexBy(findByName(a.field)),
40341                 bIndex = fields.findIndexBy(findByName(b.field));
40342
40343             return aIndex < bIndex ? -1 : 1;
40344         });
40345     },
40346
40347     
40348     reset: function() {
40349         this.eachItem(function(item) {
40350             item.reset();
40351         });
40352
40353         
40354         
40355         (function() {
40356             this.clearInvalid();
40357         }).defer(50, this);
40358     },
40359     
40360     
40361     clearInvalidChildren: function() {
40362         this.eachItem(function(item) {
40363             item.clearInvalid();
40364         });
40365     },
40366
40367     
40368     buildLabel: function(segments) {
40369         return Ext.clean(segments).join(this.labelConnector);
40370     },
40371
40372     
40373     isDirty: function(){
40374         
40375         if (this.disabled || !this.rendered) {
40376             return false;
40377         }
40378
40379         var dirty = false;
40380         this.eachItem(function(item){
40381             if(item.isDirty()){
40382                 dirty = true;
40383                 return false;
40384             }
40385         });
40386         return dirty;
40387     },
40388
40389     
40390     eachItem: function(fn, scope) {
40391         if(this.items && this.items.each){
40392             this.items.each(fn, scope || this);
40393         }
40394     },
40395
40396     
40397     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
40398         var innerCt = this.innerCt;
40399
40400         if (this.rendered && innerCt.rendered) {
40401             innerCt.setSize(adjWidth, adjHeight);
40402         }
40403
40404         Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
40405     },
40406
40407     
40408     doLayout: function(shallow, force) {
40409         if (this.rendered) {
40410             var innerCt = this.innerCt;
40411
40412             innerCt.forceLayout = this.ownerCt.forceLayout;
40413             innerCt.doLayout(shallow, force);
40414         }
40415     },
40416
40417     
40418     beforeDestroy: function(){
40419         Ext.destroy(this.innerCt);
40420
40421         Ext.form.CompositeField.superclass.beforeDestroy.call(this);
40422     },
40423
40424     
40425     setReadOnly : function(readOnly) {
40426         readOnly = readOnly || true;
40427
40428         if(this.rendered){
40429             this.eachItem(function(item){
40430                 item.setReadOnly(readOnly);
40431             });
40432         }
40433         this.readOnly = readOnly;
40434     },
40435
40436     onShow : function() {
40437         Ext.form.CompositeField.superclass.onShow.call(this);
40438         this.doLayout();
40439     },
40440
40441     
40442     onDisable : function(){
40443         this.eachItem(function(item){
40444             item.disable();
40445         });
40446     },
40447
40448     
40449     onEnable : function(){
40450         this.eachItem(function(item){
40451             item.enable();
40452         });
40453     }
40454 });
40455
40456 Ext.reg('compositefield', Ext.form.CompositeField);
40457
40458 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
40459     inputType: 'radio',
40460
40461     
40462     markInvalid : Ext.emptyFn,
40463     
40464     clearInvalid : Ext.emptyFn,
40465
40466     
40467     getGroupValue : function(){
40468         var p = this.el.up('form') || Ext.getBody();
40469         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
40470         return c ? c.value : null;
40471     },
40472
40473     
40474     onClick : function(){
40475         if(this.el.dom.checked != this.checked){
40476                         var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
40477                         els.each(function(el){
40478                                 if(el.dom.id == this.id){
40479                                         this.setValue(true);
40480                                 }else{
40481                                         Ext.getCmp(el.dom.id).setValue(false);
40482                                 }
40483                         }, this);
40484                 }
40485     },
40486
40487     
40488     setValue : function(v){
40489         if (typeof v == 'boolean') {
40490             Ext.form.Radio.superclass.setValue.call(this, v);
40491         } else if (this.rendered) {
40492             var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
40493             if(r){
40494                 Ext.getCmp(r.id).setValue(true);
40495             }
40496         }
40497         return this;
40498     },
40499
40500     
40501     getCheckEl: function(){
40502         if(this.inGroup){
40503             return this.el.up('.x-form-radio-group')
40504         }
40505         return this.el.up('form') || Ext.getBody();
40506     }
40507 });
40508 Ext.reg('radio', Ext.form.Radio);
40509
40510 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
40511     
40512     
40513     allowBlank : true,
40514     
40515     blankText : 'You must select one item in this group',
40516     
40517     
40518     defaultType : 'radio',
40519     
40520     
40521     groupCls : 'x-form-radio-group',
40522     
40523     
40524     
40525     
40526     getValue : function(){
40527         var out = null;
40528         this.eachItem(function(item){
40529             if(item.checked){
40530                 out = item;
40531                 return false;
40532             }
40533         });
40534         return out;
40535     },
40536     
40537     
40538     onSetValue : function(id, value){
40539         if(arguments.length > 1){
40540             var f = this.getBox(id);
40541             if(f){
40542                 f.setValue(value);
40543                 if(f.checked){
40544                     this.eachItem(function(item){
40545                         if (item !== f){
40546                             item.setValue(false);
40547                         }
40548                     });
40549                 }
40550             }
40551         }else{
40552             this.setValueForItem(id);
40553         }
40554     },
40555     
40556     setValueForItem : function(val){
40557         val = String(val).split(',')[0];
40558         this.eachItem(function(item){
40559             item.setValue(val == item.inputValue);
40560         });
40561     },
40562     
40563     
40564     fireChecked : function(){
40565         if(!this.checkTask){
40566             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
40567         }
40568         this.checkTask.delay(10);
40569     },
40570     
40571     
40572     bufferChecked : function(){
40573         var out = null;
40574         this.eachItem(function(item){
40575             if(item.checked){
40576                 out = item;
40577                 return false;
40578             }
40579         });
40580         this.fireEvent('change', this, out);
40581     },
40582     
40583     onDestroy : function(){
40584         if(this.checkTask){
40585             this.checkTask.cancel();
40586             this.checkTask = null;
40587         }
40588         Ext.form.RadioGroup.superclass.onDestroy.call(this);
40589     }
40590
40591 });
40592
40593 Ext.reg('radiogroup', Ext.form.RadioGroup);
40594
40595 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
40596     
40597     inputType : 'hidden',
40598
40599     
40600     onRender : function(){
40601         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
40602     },
40603
40604     
40605     initEvents : function(){
40606         this.originalValue = this.getValue();
40607     },
40608
40609     
40610     setSize : Ext.emptyFn,
40611     setWidth : Ext.emptyFn,
40612     setHeight : Ext.emptyFn,
40613     setPosition : Ext.emptyFn,
40614     setPagePosition : Ext.emptyFn,
40615     markInvalid : Ext.emptyFn,
40616     clearInvalid : Ext.emptyFn
40617 });
40618 Ext.reg('hidden', Ext.form.Hidden);
40619 Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
40620
40621     constructor: function(el, config){
40622         Ext.apply(this, config);
40623         if(Ext.isString(this.paramOrder)){
40624             this.paramOrder = this.paramOrder.split(/[\s,|]/);
40625         }
40626         
40627         this.items = new Ext.util.MixedCollection(false, function(o){
40628             return o.getItemId();
40629         });
40630         this.addEvents(
40631             
40632             'beforeaction',
40633             
40634             'actionfailed',
40635             
40636             'actioncomplete'
40637         );
40638
40639         if(el){
40640             this.initEl(el);
40641         }
40642         Ext.form.BasicForm.superclass.constructor.call(this);
40643     },
40644
40645     
40646     
40647     
40648     
40649     
40650     
40651     
40652     timeout: 30,
40653
40654     
40655
40656     
40657     paramOrder: undefined,
40658
40659     
40660     paramsAsHash: false,
40661
40662     
40663     waitTitle: 'Please Wait...',
40664
40665     
40666     activeAction : null,
40667
40668     
40669     trackResetOnLoad : false,
40670
40671     
40672     
40673
40674     
40675     initEl : function(el){
40676         this.el = Ext.get(el);
40677         this.id = this.el.id || Ext.id();
40678         if(!this.standardSubmit){
40679             this.el.on('submit', this.onSubmit, this);
40680         }
40681         this.el.addClass('x-form');
40682     },
40683
40684     
40685     getEl: function(){
40686         return this.el;
40687     },
40688
40689     
40690     onSubmit : function(e){
40691         e.stopEvent();
40692     },
40693
40694     
40695     destroy: function(bound){
40696         if(bound !== true){
40697             this.items.each(function(f){
40698                 Ext.destroy(f);
40699             });
40700             Ext.destroy(this.el);
40701         }
40702         this.items.clear();
40703         this.purgeListeners();
40704     },
40705
40706     
40707     isValid : function(){
40708         var valid = true;
40709         this.items.each(function(f){
40710            if(!f.validate()){
40711                valid = false;
40712            }
40713         });
40714         return valid;
40715     },
40716
40717     
40718     isDirty : function(){
40719         var dirty = false;
40720         this.items.each(function(f){
40721            if(f.isDirty()){
40722                dirty = true;
40723                return false;
40724            }
40725         });
40726         return dirty;
40727     },
40728
40729     
40730     doAction : function(action, options){
40731         if(Ext.isString(action)){
40732             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
40733         }
40734         if(this.fireEvent('beforeaction', this, action) !== false){
40735             this.beforeAction(action);
40736             action.run.defer(100, action);
40737         }
40738         return this;
40739     },
40740
40741     
40742     submit : function(options){
40743         options = options || {};
40744         if(this.standardSubmit){
40745             var v = options.clientValidation === false || this.isValid();
40746             if(v){
40747                 var el = this.el.dom;
40748                 if(this.url && Ext.isEmpty(el.action)){
40749                     el.action = this.url;
40750                 }
40751                 el.submit();
40752             }
40753             return v;
40754         }
40755         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
40756         this.doAction(submitAction, options);
40757         return this;
40758     },
40759
40760     
40761     load : function(options){
40762         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
40763         this.doAction(loadAction, options);
40764         return this;
40765     },
40766
40767     
40768     updateRecord : function(record){
40769         record.beginEdit();
40770         var fs = record.fields;
40771         fs.each(function(f){
40772             var field = this.findField(f.name);
40773             if(field){
40774                 record.set(f.name, field.getValue());
40775             }
40776         }, this);
40777         record.endEdit();
40778         return this;
40779     },
40780
40781     
40782     loadRecord : function(record){
40783         this.setValues(record.data);
40784         return this;
40785     },
40786
40787     
40788     beforeAction : function(action){
40789         
40790         this.items.each(function(f){
40791             if(f.isFormField && f.syncValue){
40792                 f.syncValue();
40793             }
40794         });
40795         var o = action.options;
40796         if(o.waitMsg){
40797             if(this.waitMsgTarget === true){
40798                 this.el.mask(o.waitMsg, 'x-mask-loading');
40799             }else if(this.waitMsgTarget){
40800                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
40801                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
40802             }else{
40803                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
40804             }
40805         }
40806     },
40807
40808     
40809     afterAction : function(action, success){
40810         this.activeAction = null;
40811         var o = action.options;
40812         if(o.waitMsg){
40813             if(this.waitMsgTarget === true){
40814                 this.el.unmask();
40815             }else if(this.waitMsgTarget){
40816                 this.waitMsgTarget.unmask();
40817             }else{
40818                 Ext.MessageBox.updateProgress(1);
40819                 Ext.MessageBox.hide();
40820             }
40821         }
40822         if(success){
40823             if(o.reset){
40824                 this.reset();
40825             }
40826             Ext.callback(o.success, o.scope, [this, action]);
40827             this.fireEvent('actioncomplete', this, action);
40828         }else{
40829             Ext.callback(o.failure, o.scope, [this, action]);
40830             this.fireEvent('actionfailed', this, action);
40831         }
40832     },
40833
40834     
40835     findField : function(id) {
40836         var field = this.items.get(id);
40837
40838         if (!Ext.isObject(field)) {
40839             
40840             var findMatchingField = function(f) {
40841                 if (f.isFormField) {
40842                     if (f.dataIndex == id || f.id == id || f.getName() == id) {
40843                         field = f;
40844                         return false;
40845                     } else if (f.isComposite && f.rendered) {
40846                         return f.items.each(findMatchingField);
40847                     }
40848                 }
40849             };
40850
40851             this.items.each(findMatchingField);
40852         }
40853         return field || null;
40854     },
40855
40856
40857     
40858     markInvalid : function(errors){
40859         if (Ext.isArray(errors)) {
40860             for(var i = 0, len = errors.length; i < len; i++){
40861                 var fieldError = errors[i];
40862                 var f = this.findField(fieldError.id);
40863                 if(f){
40864                     f.markInvalid(fieldError.msg);
40865                 }
40866             }
40867         } else {
40868             var field, id;
40869             for(id in errors){
40870                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
40871                     field.markInvalid(errors[id]);
40872                 }
40873             }
40874         }
40875
40876         return this;
40877     },
40878
40879     
40880     setValues : function(values){
40881         if(Ext.isArray(values)){ 
40882             for(var i = 0, len = values.length; i < len; i++){
40883                 var v = values[i];
40884                 var f = this.findField(v.id);
40885                 if(f){
40886                     f.setValue(v.value);
40887                     if(this.trackResetOnLoad){
40888                         f.originalValue = f.getValue();
40889                     }
40890                 }
40891             }
40892         }else{ 
40893             var field, id;
40894             for(id in values){
40895                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
40896                     field.setValue(values[id]);
40897                     if(this.trackResetOnLoad){
40898                         field.originalValue = field.getValue();
40899                     }
40900                 }
40901             }
40902         }
40903         return this;
40904     },
40905
40906     
40907     getValues : function(asString){
40908         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
40909         if(asString === true){
40910             return fs;
40911         }
40912         return Ext.urlDecode(fs);
40913     },
40914
40915     
40916     getFieldValues : function(dirtyOnly){
40917         var o = {},
40918             n,
40919             key,
40920             val;
40921         this.items.each(function(f) {
40922             if (dirtyOnly !== true || f.isDirty()) {
40923                 n = f.getName();
40924                 key = o[n];
40925                 val = f.getValue();
40926
40927                 if(Ext.isDefined(key)){
40928                     if(Ext.isArray(key)){
40929                         o[n].push(val);
40930                     }else{
40931                         o[n] = [key, val];
40932                     }
40933                 }else{
40934                     o[n] = val;
40935                 }
40936             }
40937         });
40938         return o;
40939     },
40940
40941     
40942     clearInvalid : function(){
40943         this.items.each(function(f){
40944            f.clearInvalid();
40945         });
40946         return this;
40947     },
40948
40949     
40950     reset : function(){
40951         this.items.each(function(f){
40952             f.reset();
40953         });
40954         return this;
40955     },
40956
40957     
40958     add : function(){
40959         this.items.addAll(Array.prototype.slice.call(arguments, 0));
40960         return this;
40961     },
40962
40963     
40964     remove : function(field){
40965         this.items.remove(field);
40966         return this;
40967     },
40968
40969     
40970     cleanDestroyed : function() {
40971         this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
40972     },
40973
40974     
40975     render : function(){
40976         this.items.each(function(f){
40977             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
40978                 f.applyToMarkup(f.id);
40979             }
40980         });
40981         return this;
40982     },
40983
40984     
40985     applyToFields : function(o){
40986         this.items.each(function(f){
40987            Ext.apply(f, o);
40988         });
40989         return this;
40990     },
40991
40992     
40993     applyIfToFields : function(o){
40994         this.items.each(function(f){
40995            Ext.applyIf(f, o);
40996         });
40997         return this;
40998     },
40999
41000     callFieldMethod : function(fnName, args){
41001         args = args || [];
41002         this.items.each(function(f){
41003             if(Ext.isFunction(f[fnName])){
41004                 f[fnName].apply(f, args);
41005             }
41006         });
41007         return this;
41008     }
41009 });
41010
41011
41012 Ext.BasicForm = Ext.form.BasicForm;
41013
41014 Ext.FormPanel = Ext.extend(Ext.Panel, {
41015     
41016     
41017     
41018     
41019     
41020     
41021     
41022
41023
41024     
41025     minButtonWidth : 75,
41026
41027     
41028     labelAlign : 'left',
41029
41030     
41031     monitorValid : false,
41032
41033     
41034     monitorPoll : 200,
41035
41036     
41037     layout : 'form',
41038
41039     
41040     initComponent : function(){
41041         this.form = this.createForm();
41042         Ext.FormPanel.superclass.initComponent.call(this);
41043
41044         this.bodyCfg = {
41045             tag: 'form',
41046             cls: this.baseCls + '-body',
41047             method : this.method || 'POST',
41048             id : this.formId || Ext.id()
41049         };
41050         if(this.fileUpload) {
41051             this.bodyCfg.enctype = 'multipart/form-data';
41052         }
41053         this.initItems();
41054
41055         this.addEvents(
41056             
41057             'clientvalidation'
41058         );
41059
41060         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
41061     },
41062
41063     
41064     createForm : function(){
41065         var config = Ext.applyIf({listeners: {}}, this.initialConfig);
41066         return new Ext.form.BasicForm(null, config);
41067     },
41068
41069     
41070     initFields : function(){
41071         var f = this.form;
41072         var formPanel = this;
41073         var fn = function(c){
41074             if(formPanel.isField(c)){
41075                 f.add(c);
41076             }else if(c.findBy && c != formPanel){
41077                 formPanel.applySettings(c);
41078                 
41079                 if(c.items && c.items.each){
41080                     c.items.each(fn, this);
41081                 }
41082             }
41083         };
41084         this.items.each(fn, this);
41085     },
41086
41087     
41088     applySettings: function(c){
41089         var ct = c.ownerCt;
41090         Ext.applyIf(c, {
41091             labelAlign: ct.labelAlign,
41092             labelWidth: ct.labelWidth,
41093             itemCls: ct.itemCls
41094         });
41095     },
41096
41097     
41098     getLayoutTarget : function(){
41099         return this.form.el;
41100     },
41101
41102     
41103     getForm : function(){
41104         return this.form;
41105     },
41106
41107     
41108     onRender : function(ct, position){
41109         this.initFields();
41110         Ext.FormPanel.superclass.onRender.call(this, ct, position);
41111         this.form.initEl(this.body);
41112     },
41113
41114     
41115     beforeDestroy : function(){
41116         this.stopMonitoring();
41117         this.form.destroy(true);
41118         Ext.FormPanel.superclass.beforeDestroy.call(this);
41119     },
41120
41121     
41122     isField : function(c) {
41123         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
41124     },
41125
41126     
41127     initEvents : function(){
41128         Ext.FormPanel.superclass.initEvents.call(this);
41129         
41130         this.on({
41131             scope: this,
41132             add: this.onAddEvent,
41133             remove: this.onRemoveEvent
41134         });
41135         if(this.monitorValid){ 
41136             this.startMonitoring();
41137         }
41138     },
41139
41140     
41141     onAdd: function(c){
41142         Ext.FormPanel.superclass.onAdd.call(this, c);
41143         this.processAdd(c);
41144     },
41145
41146     
41147     onAddEvent: function(ct, c){
41148         if(ct !== this){
41149             this.processAdd(c);
41150         }
41151     },
41152
41153     
41154     processAdd : function(c){
41155         
41156         if(this.isField(c)){
41157             this.form.add(c);
41158         
41159         }else if(c.findBy){
41160             this.applySettings(c);
41161             this.form.add.apply(this.form, c.findBy(this.isField));
41162         }
41163     },
41164
41165     
41166     onRemove: function(c){
41167         Ext.FormPanel.superclass.onRemove.call(this, c);
41168         this.processRemove(c);
41169     },
41170
41171     onRemoveEvent: function(ct, c){
41172         if(ct !== this){
41173             this.processRemove(c);
41174         }
41175     },
41176
41177     
41178     processRemove: function(c){
41179         if(!this.destroying){
41180             
41181             if(this.isField(c)){
41182                 this.form.remove(c);
41183             
41184             }else if (c.findBy){
41185                 Ext.each(c.findBy(this.isField), this.form.remove, this.form);
41186                 if (c.isDestroyed) {
41187                     this.form.cleanDestroyed();
41188                 }
41189             }
41190         }
41191     },
41192
41193     
41194     startMonitoring : function(){
41195         if(!this.validTask){
41196             this.validTask = new Ext.util.TaskRunner();
41197             this.validTask.start({
41198                 run : this.bindHandler,
41199                 interval : this.monitorPoll || 200,
41200                 scope: this
41201             });
41202         }
41203     },
41204
41205     
41206     stopMonitoring : function(){
41207         if(this.validTask){
41208             this.validTask.stopAll();
41209             this.validTask = null;
41210         }
41211     },
41212
41213     
41214     load : function(){
41215         this.form.load.apply(this.form, arguments);
41216     },
41217
41218     
41219     onDisable : function(){
41220         Ext.FormPanel.superclass.onDisable.call(this);
41221         if(this.form){
41222             this.form.items.each(function(){
41223                  this.disable();
41224             });
41225         }
41226     },
41227
41228     
41229     onEnable : function(){
41230         Ext.FormPanel.superclass.onEnable.call(this);
41231         if(this.form){
41232             this.form.items.each(function(){
41233                  this.enable();
41234             });
41235         }
41236     },
41237
41238     
41239     bindHandler : function(){
41240         var valid = true;
41241         this.form.items.each(function(f){
41242             if(!f.isValid(true)){
41243                 valid = false;
41244                 return false;
41245             }
41246         });
41247         if(this.fbar){
41248             var fitems = this.fbar.items.items;
41249             for(var i = 0, len = fitems.length; i < len; i++){
41250                 var btn = fitems[i];
41251                 if(btn.formBind === true && btn.disabled === valid){
41252                     btn.setDisabled(!valid);
41253                 }
41254             }
41255         }
41256         this.fireEvent('clientvalidation', this, valid);
41257     }
41258 });
41259 Ext.reg('form', Ext.FormPanel);
41260
41261 Ext.form.FormPanel = Ext.FormPanel;
41262
41263 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
41264     
41265     
41266     
41267     
41268     
41269     
41270     baseCls : 'x-fieldset',
41271     
41272     layout : 'form',
41273     
41274     animCollapse : false,
41275
41276     
41277     onRender : function(ct, position){
41278         if(!this.el){
41279             this.el = document.createElement('fieldset');
41280             this.el.id = this.id;
41281             if (this.title || this.header || this.checkboxToggle) {
41282                 this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
41283             }
41284         }
41285
41286         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
41287
41288         if(this.checkboxToggle){
41289             var o = typeof this.checkboxToggle == 'object' ?
41290                     this.checkboxToggle :
41291                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
41292             this.checkbox = this.header.insertFirst(o);
41293             this.checkbox.dom.checked = !this.collapsed;
41294             this.mon(this.checkbox, 'click', this.onCheckClick, this);
41295         }
41296     },
41297
41298     
41299     onCollapse : function(doAnim, animArg){
41300         if(this.checkbox){
41301             this.checkbox.dom.checked = false;
41302         }
41303         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
41304
41305     },
41306
41307     
41308     onExpand : function(doAnim, animArg){
41309         if(this.checkbox){
41310             this.checkbox.dom.checked = true;
41311         }
41312         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
41313     },
41314
41315     
41316     onCheckClick : function(){
41317         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
41318     }
41319
41320     
41321     
41322     
41323     
41324     
41325     
41326     
41327     
41328     
41329     
41330     
41331     
41332     
41333     
41334     
41335     
41336     
41337     
41338     
41339     
41340     
41341     
41342     
41343     
41344     
41345     
41346     
41347     
41348     
41349     
41350     
41351     
41352     
41353     
41354 });
41355 Ext.reg('fieldset', Ext.form.FieldSet);
41356
41357 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
41358     
41359     enableFormat : true,
41360     
41361     enableFontSize : true,
41362     
41363     enableColors : true,
41364     
41365     enableAlignments : true,
41366     
41367     enableLists : true,
41368     
41369     enableSourceEdit : true,
41370     
41371     enableLinks : true,
41372     
41373     enableFont : true,
41374     
41375     createLinkText : 'Please enter the URL for the link:',
41376     
41377     defaultLinkValue : 'http:/'+'/',
41378     
41379     fontFamilies : [
41380         'Arial',
41381         'Courier New',
41382         'Tahoma',
41383         'Times New Roman',
41384         'Verdana'
41385     ],
41386     defaultFont: 'tahoma',
41387     
41388     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
41389
41390     
41391     actionMode: 'wrap',
41392     validationEvent : false,
41393     deferHeight: true,
41394     initialized : false,
41395     activated : false,
41396     sourceEditMode : false,
41397     onFocus : Ext.emptyFn,
41398     iframePad:3,
41399     hideMode:'offsets',
41400     defaultAutoCreate : {
41401         tag: "textarea",
41402         style:"width:500px;height:300px;",
41403         autocomplete: "off"
41404     },
41405
41406     
41407     initComponent : function(){
41408         this.addEvents(
41409             
41410             'initialize',
41411             
41412             'activate',
41413              
41414             'beforesync',
41415              
41416             'beforepush',
41417              
41418             'sync',
41419              
41420             'push',
41421              
41422             'editmodechange'
41423         );
41424     },
41425
41426     
41427     createFontOptions : function(){
41428         var buf = [], fs = this.fontFamilies, ff, lc;
41429         for(var i = 0, len = fs.length; i< len; i++){
41430             ff = fs[i];
41431             lc = ff.toLowerCase();
41432             buf.push(
41433                 '<option value="',lc,'" style="font-family:',ff,';"',
41434                     (this.defaultFont == lc ? ' selected="true">' : '>'),
41435                     ff,
41436                 '</option>'
41437             );
41438         }
41439         return buf.join('');
41440     },
41441
41442     
41443     createToolbar : function(editor){
41444         var items = [];
41445         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
41446
41447
41448         function btn(id, toggle, handler){
41449             return {
41450                 itemId : id,
41451                 cls : 'x-btn-icon',
41452                 iconCls: 'x-edit-'+id,
41453                 enableToggle:toggle !== false,
41454                 scope: editor,
41455                 handler:handler||editor.relayBtnCmd,
41456                 clickEvent:'mousedown',
41457                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
41458                 overflowText: editor.buttonTips[id].title || undefined,
41459                 tabIndex:-1
41460             };
41461         }
41462
41463
41464         if(this.enableFont && !Ext.isSafari2){
41465             var fontSelectItem = new Ext.Toolbar.Item({
41466                autoEl: {
41467                     tag:'select',
41468                     cls:'x-font-select',
41469                     html: this.createFontOptions()
41470                }
41471             });
41472
41473             items.push(
41474                 fontSelectItem,
41475                 '-'
41476             );
41477         }
41478
41479         if(this.enableFormat){
41480             items.push(
41481                 btn('bold'),
41482                 btn('italic'),
41483                 btn('underline')
41484             );
41485         }
41486
41487         if(this.enableFontSize){
41488             items.push(
41489                 '-',
41490                 btn('increasefontsize', false, this.adjustFont),
41491                 btn('decreasefontsize', false, this.adjustFont)
41492             );
41493         }
41494
41495         if(this.enableColors){
41496             items.push(
41497                 '-', {
41498                     itemId:'forecolor',
41499                     cls:'x-btn-icon',
41500                     iconCls: 'x-edit-forecolor',
41501                     clickEvent:'mousedown',
41502                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
41503                     tabIndex:-1,
41504                     menu : new Ext.menu.ColorMenu({
41505                         allowReselect: true,
41506                         focus: Ext.emptyFn,
41507                         value:'000000',
41508                         plain:true,
41509                         listeners: {
41510                             scope: this,
41511                             select: function(cp, color){
41512                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
41513                                 this.deferFocus();
41514                             }
41515                         },
41516                         clickEvent:'mousedown'
41517                     })
41518                 }, {
41519                     itemId:'backcolor',
41520                     cls:'x-btn-icon',
41521                     iconCls: 'x-edit-backcolor',
41522                     clickEvent:'mousedown',
41523                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
41524                     tabIndex:-1,
41525                     menu : new Ext.menu.ColorMenu({
41526                         focus: Ext.emptyFn,
41527                         value:'FFFFFF',
41528                         plain:true,
41529                         allowReselect: true,
41530                         listeners: {
41531                             scope: this,
41532                             select: function(cp, color){
41533                                 if(Ext.isGecko){
41534                                     this.execCmd('useCSS', false);
41535                                     this.execCmd('hilitecolor', color);
41536                                     this.execCmd('useCSS', true);
41537                                     this.deferFocus();
41538                                 }else{
41539                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
41540                                     this.deferFocus();
41541                                 }
41542                             }
41543                         },
41544                         clickEvent:'mousedown'
41545                     })
41546                 }
41547             );
41548         }
41549
41550         if(this.enableAlignments){
41551             items.push(
41552                 '-',
41553                 btn('justifyleft'),
41554                 btn('justifycenter'),
41555                 btn('justifyright')
41556             );
41557         }
41558
41559         if(!Ext.isSafari2){
41560             if(this.enableLinks){
41561                 items.push(
41562                     '-',
41563                     btn('createlink', false, this.createLink)
41564                 );
41565             }
41566
41567             if(this.enableLists){
41568                 items.push(
41569                     '-',
41570                     btn('insertorderedlist'),
41571                     btn('insertunorderedlist')
41572                 );
41573             }
41574             if(this.enableSourceEdit){
41575                 items.push(
41576                     '-',
41577                     btn('sourceedit', true, function(btn){
41578                         this.toggleSourceEdit(!this.sourceEditMode);
41579                     })
41580                 );
41581             }
41582         }
41583
41584         
41585         var tb = new Ext.Toolbar({
41586             renderTo: this.wrap.dom.firstChild,
41587             items: items
41588         });
41589
41590         if (fontSelectItem) {
41591             this.fontSelect = fontSelectItem.el;
41592
41593             this.mon(this.fontSelect, 'change', function(){
41594                 var font = this.fontSelect.dom.value;
41595                 this.relayCmd('fontname', font);
41596                 this.deferFocus();
41597             }, this);
41598         }
41599
41600         
41601         this.mon(tb.el, 'click', function(e){
41602             e.preventDefault();
41603         });
41604
41605         this.tb = tb;
41606         this.tb.doLayout();
41607     },
41608
41609     onDisable: function(){
41610         this.wrap.mask();
41611         Ext.form.HtmlEditor.superclass.onDisable.call(this);
41612     },
41613
41614     onEnable: function(){
41615         this.wrap.unmask();
41616         Ext.form.HtmlEditor.superclass.onEnable.call(this);
41617     },
41618
41619     setReadOnly: function(readOnly){
41620
41621         Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
41622         if(this.initialized){
41623             if(Ext.isIE){
41624                 this.getEditorBody().contentEditable = !readOnly;
41625             }else{
41626                 this.setDesignMode(!readOnly);
41627             }
41628             var bd = this.getEditorBody();
41629             if(bd){
41630                 bd.style.cursor = this.readOnly ? 'default' : 'text';
41631             }
41632             this.disableItems(readOnly);
41633         }
41634     },
41635
41636     
41637     getDocMarkup : function(){
41638         var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
41639         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);
41640     },
41641
41642     
41643     getEditorBody : function(){
41644         var doc = this.getDoc();
41645         return doc.body || doc.documentElement;
41646     },
41647
41648     
41649     getDoc : function(){
41650         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
41651     },
41652
41653     
41654     getWin : function(){
41655         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
41656     },
41657
41658     
41659     onRender : function(ct, position){
41660         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
41661         this.el.dom.style.border = '0 none';
41662         this.el.dom.setAttribute('tabIndex', -1);
41663         this.el.addClass('x-hidden');
41664         if(Ext.isIE){ 
41665             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
41666         }
41667         this.wrap = this.el.wrap({
41668             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
41669         });
41670
41671         this.createToolbar(this);
41672
41673         this.disableItems(true);
41674
41675         this.tb.doLayout();
41676
41677         this.createIFrame();
41678
41679         if(!this.width){
41680             var sz = this.el.getSize();
41681             this.setSize(sz.width, this.height || sz.height);
41682         }
41683         this.resizeEl = this.positionEl = this.wrap;
41684     },
41685
41686     createIFrame: function(){
41687         var iframe = document.createElement('iframe');
41688         iframe.name = Ext.id();
41689         iframe.frameBorder = '0';
41690         iframe.style.overflow = 'auto';
41691
41692         this.wrap.dom.appendChild(iframe);
41693         this.iframe = iframe;
41694
41695         this.monitorTask = Ext.TaskMgr.start({
41696             run: this.checkDesignMode,
41697             scope: this,
41698             interval:100
41699         });
41700     },
41701
41702     initFrame : function(){
41703         Ext.TaskMgr.stop(this.monitorTask);
41704         var doc = this.getDoc();
41705         this.win = this.getWin();
41706
41707         doc.open();
41708         doc.write(this.getDocMarkup());
41709         doc.close();
41710
41711         var task = { 
41712             run : function(){
41713                 var doc = this.getDoc();
41714                 if(doc.body || doc.readyState == 'complete'){
41715                     Ext.TaskMgr.stop(task);
41716                     this.setDesignMode(true);
41717                     this.initEditor.defer(10, this);
41718                 }
41719             },
41720             interval : 10,
41721             duration:10000,
41722             scope: this
41723         };
41724         Ext.TaskMgr.start(task);
41725     },
41726
41727
41728     checkDesignMode : function(){
41729         if(this.wrap && this.wrap.dom.offsetWidth){
41730             var doc = this.getDoc();
41731             if(!doc){
41732                 return;
41733             }
41734             if(!doc.editorInitialized || this.getDesignMode() != 'on'){
41735                 this.initFrame();
41736             }
41737         }
41738     },
41739
41740     
41741     setDesignMode : function(mode){
41742         var doc ;
41743         if(doc = this.getDoc()){
41744             if(this.readOnly){
41745                 mode = false;
41746             }
41747             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
41748         }
41749
41750     },
41751
41752     
41753     getDesignMode : function(){
41754         var doc = this.getDoc();
41755         if(!doc){ return ''; }
41756         return String(doc.designMode).toLowerCase();
41757
41758     },
41759
41760     disableItems: function(disabled){
41761         if(this.fontSelect){
41762             this.fontSelect.dom.disabled = disabled;
41763         }
41764         this.tb.items.each(function(item){
41765             if(item.getItemId() != 'sourceedit'){
41766                 item.setDisabled(disabled);
41767             }
41768         });
41769     },
41770
41771     
41772     onResize : function(w, h){
41773         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
41774         if(this.el && this.iframe){
41775             if(Ext.isNumber(w)){
41776                 var aw = w - this.wrap.getFrameWidth('lr');
41777                 this.el.setWidth(aw);
41778                 this.tb.setWidth(aw);
41779                 this.iframe.style.width = Math.max(aw, 0) + 'px';
41780             }
41781             if(Ext.isNumber(h)){
41782                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
41783                 this.el.setHeight(ah);
41784                 this.iframe.style.height = Math.max(ah, 0) + 'px';
41785                 var bd = this.getEditorBody();
41786                 if(bd){
41787                     bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
41788                 }
41789             }
41790         }
41791     },
41792
41793     
41794     toggleSourceEdit : function(sourceEditMode){
41795         var iframeHeight,
41796             elHeight;
41797
41798         if (sourceEditMode === undefined) {
41799             sourceEditMode = !this.sourceEditMode;
41800         }
41801         this.sourceEditMode = sourceEditMode === true;
41802         var btn = this.tb.getComponent('sourceedit');
41803
41804         if (btn.pressed !== this.sourceEditMode) {
41805             btn.toggle(this.sourceEditMode);
41806             if (!btn.xtbHidden) {
41807                 return;
41808             }
41809         }
41810         if (this.sourceEditMode) {
41811             
41812             this.previousSize = this.getSize();
41813
41814             iframeHeight = Ext.get(this.iframe).getHeight();
41815
41816             this.disableItems(true);
41817             this.syncValue();
41818             this.iframe.className = 'x-hidden';
41819             this.el.removeClass('x-hidden');
41820             this.el.dom.removeAttribute('tabIndex');
41821             this.el.focus();
41822             this.el.dom.style.height = iframeHeight + 'px';
41823         }
41824         else {
41825             elHeight = parseInt(this.el.dom.style.height, 10);
41826             if (this.initialized) {
41827                 this.disableItems(this.readOnly);
41828             }
41829             this.pushValue();
41830             this.iframe.className = '';
41831             this.el.addClass('x-hidden');
41832             this.el.dom.setAttribute('tabIndex', -1);
41833             this.deferFocus();
41834
41835             this.setSize(this.previousSize);
41836             delete this.previousSize;
41837             this.iframe.style.height = elHeight + 'px';
41838         }
41839         this.fireEvent('editmodechange', this, this.sourceEditMode);
41840     },
41841
41842     
41843     createLink : function() {
41844         var url = prompt(this.createLinkText, this.defaultLinkValue);
41845         if(url && url != 'http:/'+'/'){
41846             this.relayCmd('createlink', url);
41847         }
41848     },
41849
41850     
41851     initEvents : function(){
41852         this.originalValue = this.getValue();
41853     },
41854
41855     
41856     markInvalid : Ext.emptyFn,
41857
41858     
41859     clearInvalid : Ext.emptyFn,
41860
41861     
41862     setValue : function(v){
41863         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
41864         this.pushValue();
41865         return this;
41866     },
41867
41868     
41869     cleanHtml: function(html) {
41870         html = String(html);
41871         if(Ext.isWebKit){ 
41872             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
41873         }
41874
41875         
41876         if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
41877             html = html.substring(1);
41878         }
41879         return html;
41880     },
41881
41882     
41883     syncValue : function(){
41884         if(this.initialized){
41885             var bd = this.getEditorBody();
41886             var html = bd.innerHTML;
41887             if(Ext.isWebKit){
41888                 var bs = bd.getAttribute('style'); 
41889                 var m = bs.match(/text-align:(.*?);/i);
41890                 if(m && m[1]){
41891                     html = '<div style="'+m[0]+'">' + html + '</div>';
41892                 }
41893             }
41894             html = this.cleanHtml(html);
41895             if(this.fireEvent('beforesync', this, html) !== false){
41896                 this.el.dom.value = html;
41897                 this.fireEvent('sync', this, html);
41898             }
41899         }
41900     },
41901
41902     
41903     getValue : function() {
41904         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
41905         return Ext.form.HtmlEditor.superclass.getValue.call(this);
41906     },
41907
41908     
41909     pushValue : function(){
41910         if(this.initialized){
41911             var v = this.el.dom.value;
41912             if(!this.activated && v.length < 1){
41913                 v = this.defaultValue;
41914             }
41915             if(this.fireEvent('beforepush', this, v) !== false){
41916                 this.getEditorBody().innerHTML = v;
41917                 if(Ext.isGecko){
41918                     
41919                     this.setDesignMode(false);  
41920                     this.setDesignMode(true);
41921                 }
41922                 this.fireEvent('push', this, v);
41923             }
41924
41925         }
41926     },
41927
41928     
41929     deferFocus : function(){
41930         this.focus.defer(10, this);
41931     },
41932
41933     
41934     focus : function(){
41935         if(this.win && !this.sourceEditMode){
41936             this.win.focus();
41937         }else{
41938             this.el.focus();
41939         }
41940     },
41941
41942     
41943     initEditor : function(){
41944         
41945         try{
41946             var dbody = this.getEditorBody(),
41947                 ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
41948                 doc,
41949                 fn;
41950
41951             ss['background-attachment'] = 'fixed'; 
41952             dbody.bgProperties = 'fixed'; 
41953
41954             Ext.DomHelper.applyStyles(dbody, ss);
41955
41956             doc = this.getDoc();
41957
41958             if(doc){
41959                 try{
41960                     Ext.EventManager.removeAll(doc);
41961                 }catch(e){}
41962             }
41963
41964             
41965             fn = this.onEditorEvent.createDelegate(this);
41966             Ext.EventManager.on(doc, {
41967                 mousedown: fn,
41968                 dblclick: fn,
41969                 click: fn,
41970                 keyup: fn,
41971                 buffer:100
41972             });
41973
41974             if(Ext.isGecko){
41975                 Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
41976             }
41977             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
41978                 Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
41979             }
41980             doc.editorInitialized = true;
41981             this.initialized = true;
41982             this.pushValue();
41983             this.setReadOnly(this.readOnly);
41984             this.fireEvent('initialize', this);
41985         }catch(e){}
41986     },
41987
41988     
41989     onDestroy : function(){
41990         if(this.monitorTask){
41991             Ext.TaskMgr.stop(this.monitorTask);
41992         }
41993         if(this.rendered){
41994             Ext.destroy(this.tb);
41995             var doc = this.getDoc();
41996             if(doc){
41997                 try{
41998                     Ext.EventManager.removeAll(doc);
41999                     for (var prop in doc){
42000                         delete doc[prop];
42001                     }
42002                 }catch(e){}
42003             }
42004             if(this.wrap){
42005                 this.wrap.dom.innerHTML = '';
42006                 this.wrap.remove();
42007             }
42008         }
42009
42010         if(this.el){
42011             this.el.removeAllListeners();
42012             this.el.remove();
42013         }
42014         this.purgeListeners();
42015     },
42016
42017     
42018     onFirstFocus : function(){
42019         this.activated = true;
42020         this.disableItems(this.readOnly);
42021         if(Ext.isGecko){ 
42022             this.win.focus();
42023             var s = this.win.getSelection();
42024             if(!s.focusNode || s.focusNode.nodeType != 3){
42025                 var r = s.getRangeAt(0);
42026                 r.selectNodeContents(this.getEditorBody());
42027                 r.collapse(true);
42028                 this.deferFocus();
42029             }
42030             try{
42031                 this.execCmd('useCSS', true);
42032                 this.execCmd('styleWithCSS', false);
42033             }catch(e){}
42034         }
42035         this.fireEvent('activate', this);
42036     },
42037
42038     
42039     adjustFont: function(btn){
42040         var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
42041             doc = this.getDoc(),
42042             v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
42043         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
42044             
42045             
42046             if(v <= 10){
42047                 v = 1 + adjust;
42048             }else if(v <= 13){
42049                 v = 2 + adjust;
42050             }else if(v <= 16){
42051                 v = 3 + adjust;
42052             }else if(v <= 18){
42053                 v = 4 + adjust;
42054             }else if(v <= 24){
42055                 v = 5 + adjust;
42056             }else {
42057                 v = 6 + adjust;
42058             }
42059             v = v.constrain(1, 6);
42060         }else{
42061             if(Ext.isSafari){ 
42062                 adjust *= 2;
42063             }
42064             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
42065         }
42066         this.execCmd('FontSize', v);
42067     },
42068
42069     
42070     onEditorEvent : function(e){
42071         this.updateToolbar();
42072     },
42073
42074
42075     
42076     updateToolbar: function(){
42077
42078         if(this.readOnly){
42079             return;
42080         }
42081
42082         if(!this.activated){
42083             this.onFirstFocus();
42084             return;
42085         }
42086
42087         var btns = this.tb.items.map,
42088             doc = this.getDoc();
42089
42090         if(this.enableFont && !Ext.isSafari2){
42091             var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
42092             if(name != this.fontSelect.dom.value){
42093                 this.fontSelect.dom.value = name;
42094             }
42095         }
42096         if(this.enableFormat){
42097             btns.bold.toggle(doc.queryCommandState('bold'));
42098             btns.italic.toggle(doc.queryCommandState('italic'));
42099             btns.underline.toggle(doc.queryCommandState('underline'));
42100         }
42101         if(this.enableAlignments){
42102             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
42103             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
42104             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
42105         }
42106         if(!Ext.isSafari2 && this.enableLists){
42107             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
42108             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
42109         }
42110
42111         Ext.menu.MenuMgr.hideAll();
42112
42113         this.syncValue();
42114     },
42115
42116     
42117     relayBtnCmd : function(btn){
42118         this.relayCmd(btn.getItemId());
42119     },
42120
42121     
42122     relayCmd : function(cmd, value){
42123         (function(){
42124             this.focus();
42125             this.execCmd(cmd, value);
42126             this.updateToolbar();
42127         }).defer(10, this);
42128     },
42129
42130     
42131     execCmd : function(cmd, value){
42132         var doc = this.getDoc();
42133         doc.execCommand(cmd, false, value === undefined ? null : value);
42134         this.syncValue();
42135     },
42136
42137     
42138     applyCommand : function(e){
42139         if(e.ctrlKey){
42140             var c = e.getCharCode(), cmd;
42141             if(c > 0){
42142                 c = String.fromCharCode(c);
42143                 switch(c){
42144                     case 'b':
42145                         cmd = 'bold';
42146                     break;
42147                     case 'i':
42148                         cmd = 'italic';
42149                     break;
42150                     case 'u':
42151                         cmd = 'underline';
42152                     break;
42153                 }
42154                 if(cmd){
42155                     this.win.focus();
42156                     this.execCmd(cmd);
42157                     this.deferFocus();
42158                     e.preventDefault();
42159                 }
42160             }
42161         }
42162     },
42163
42164     
42165     insertAtCursor : function(text){
42166         if(!this.activated){
42167             return;
42168         }
42169         if(Ext.isIE){
42170             this.win.focus();
42171             var doc = this.getDoc(),
42172                 r = doc.selection.createRange();
42173             if(r){
42174                 r.pasteHTML(text);
42175                 this.syncValue();
42176                 this.deferFocus();
42177             }
42178         }else{
42179             this.win.focus();
42180             this.execCmd('InsertHTML', text);
42181             this.deferFocus();
42182         }
42183     },
42184
42185     
42186     fixKeys : function(){ 
42187         if(Ext.isIE){
42188             return function(e){
42189                 var k = e.getKey(),
42190                     doc = this.getDoc(),
42191                         r;
42192                 if(k == e.TAB){
42193                     e.stopEvent();
42194                     r = doc.selection.createRange();
42195                     if(r){
42196                         r.collapse(true);
42197                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
42198                         this.deferFocus();
42199                     }
42200                 }else if(k == e.ENTER){
42201                     r = doc.selection.createRange();
42202                     if(r){
42203                         var target = r.parentElement();
42204                         if(!target || target.tagName.toLowerCase() != 'li'){
42205                             e.stopEvent();
42206                             r.pasteHTML('<br />');
42207                             r.collapse(false);
42208                             r.select();
42209                         }
42210                     }
42211                 }
42212             };
42213         }else if(Ext.isOpera){
42214             return function(e){
42215                 var k = e.getKey();
42216                 if(k == e.TAB){
42217                     e.stopEvent();
42218                     this.win.focus();
42219                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
42220                     this.deferFocus();
42221                 }
42222             };
42223         }else if(Ext.isWebKit){
42224             return function(e){
42225                 var k = e.getKey();
42226                 if(k == e.TAB){
42227                     e.stopEvent();
42228                     this.execCmd('InsertText','\t');
42229                     this.deferFocus();
42230                 }else if(k == e.ENTER){
42231                     e.stopEvent();
42232                     this.execCmd('InsertHtml','<br /><br />');
42233                     this.deferFocus();
42234                 }
42235              };
42236         }
42237     }(),
42238
42239     
42240     getToolbar : function(){
42241         return this.tb;
42242     },
42243
42244     
42245     buttonTips : {
42246         bold : {
42247             title: 'Bold (Ctrl+B)',
42248             text: 'Make the selected text bold.',
42249             cls: 'x-html-editor-tip'
42250         },
42251         italic : {
42252             title: 'Italic (Ctrl+I)',
42253             text: 'Make the selected text italic.',
42254             cls: 'x-html-editor-tip'
42255         },
42256         underline : {
42257             title: 'Underline (Ctrl+U)',
42258             text: 'Underline the selected text.',
42259             cls: 'x-html-editor-tip'
42260         },
42261         increasefontsize : {
42262             title: 'Grow Text',
42263             text: 'Increase the font size.',
42264             cls: 'x-html-editor-tip'
42265         },
42266         decreasefontsize : {
42267             title: 'Shrink Text',
42268             text: 'Decrease the font size.',
42269             cls: 'x-html-editor-tip'
42270         },
42271         backcolor : {
42272             title: 'Text Highlight Color',
42273             text: 'Change the background color of the selected text.',
42274             cls: 'x-html-editor-tip'
42275         },
42276         forecolor : {
42277             title: 'Font Color',
42278             text: 'Change the color of the selected text.',
42279             cls: 'x-html-editor-tip'
42280         },
42281         justifyleft : {
42282             title: 'Align Text Left',
42283             text: 'Align text to the left.',
42284             cls: 'x-html-editor-tip'
42285         },
42286         justifycenter : {
42287             title: 'Center Text',
42288             text: 'Center text in the editor.',
42289             cls: 'x-html-editor-tip'
42290         },
42291         justifyright : {
42292             title: 'Align Text Right',
42293             text: 'Align text to the right.',
42294             cls: 'x-html-editor-tip'
42295         },
42296         insertunorderedlist : {
42297             title: 'Bullet List',
42298             text: 'Start a bulleted list.',
42299             cls: 'x-html-editor-tip'
42300         },
42301         insertorderedlist : {
42302             title: 'Numbered List',
42303             text: 'Start a numbered list.',
42304             cls: 'x-html-editor-tip'
42305         },
42306         createlink : {
42307             title: 'Hyperlink',
42308             text: 'Make the selected text a hyperlink.',
42309             cls: 'x-html-editor-tip'
42310         },
42311         sourceedit : {
42312             title: 'Source Edit',
42313             text: 'Switch to source editing mode.',
42314             cls: 'x-html-editor-tip'
42315         }
42316     }
42317
42318     
42319     
42320     
42321     
42322     
42323     
42324     
42325     
42326     
42327     
42328     
42329     
42330     
42331     
42332     
42333     
42334     
42335     
42336     
42337     
42338     
42339     
42340     
42341     
42342     
42343     
42344     
42345     
42346     
42347     
42348     
42349     
42350     
42351     
42352 });
42353 Ext.reg('htmleditor', Ext.form.HtmlEditor);
42354
42355 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
42356     
42357     minValue : undefined,
42358     
42359     maxValue : undefined,
42360     
42361     minText : "The time in this field must be equal to or after {0}",
42362     
42363     maxText : "The time in this field must be equal to or before {0}",
42364     
42365     invalidText : "{0} is not a valid time",
42366     
42367     format : "g:i A",
42368     
42369     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",
42370     
42371     increment: 15,
42372
42373     
42374     mode: 'local',
42375     
42376     triggerAction: 'all',
42377     
42378     typeAhead: false,
42379
42380     
42381     
42382     
42383     initDate: '1/1/2008',
42384
42385     initDateFormat: 'j/n/Y',
42386
42387     
42388     initComponent : function(){
42389         if(Ext.isDefined(this.minValue)){
42390             this.setMinValue(this.minValue, true);
42391         }
42392         if(Ext.isDefined(this.maxValue)){
42393             this.setMaxValue(this.maxValue, true);
42394         }
42395         if(!this.store){
42396             this.generateStore(true);
42397         }
42398         Ext.form.TimeField.superclass.initComponent.call(this);
42399     },
42400
42401     
42402     setMinValue: function(value,  initial){
42403         this.setLimit(value, true, initial);
42404         return this;
42405     },
42406
42407     
42408     setMaxValue: function(value,  initial){
42409         this.setLimit(value, false, initial);
42410         return this;
42411     },
42412
42413     
42414     generateStore: function(initial){
42415         var min = this.minValue || new Date(this.initDate).clearTime(),
42416             max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
42417             times = [];
42418
42419         while(min <= max){
42420             times.push(min.dateFormat(this.format));
42421             min = min.add('mi', this.increment);
42422         }
42423         this.bindStore(times, initial);
42424     },
42425
42426     
42427     setLimit: function(value, isMin, initial){
42428         var d;
42429         if(Ext.isString(value)){
42430             d = this.parseDate(value);
42431         }else if(Ext.isDate(value)){
42432             d = value;
42433         }
42434         if(d){
42435             var val = new Date(this.initDate).clearTime();
42436             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
42437             this[isMin ? 'minValue' : 'maxValue'] = val;
42438             if(!initial){
42439                 this.generateStore();
42440             }
42441         }
42442     },
42443
42444     
42445     getValue : function(){
42446         var v = Ext.form.TimeField.superclass.getValue.call(this);
42447         return this.formatDate(this.parseDate(v)) || '';
42448     },
42449
42450     
42451     setValue : function(value){
42452         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
42453     },
42454
42455     
42456     validateValue : Ext.form.DateField.prototype.validateValue,
42457
42458     formatDate : Ext.form.DateField.prototype.formatDate,
42459
42460     parseDate: function(value) {
42461         if (!value || Ext.isDate(value)) {
42462             return value;
42463         }
42464
42465         var id = this.initDate + ' ',
42466             idf = this.initDateFormat + ' ',
42467             v = Date.parseDate(id + value, idf + this.format), 
42468             af = this.altFormats;
42469
42470         if (!v && af) {
42471             if (!this.altFormatsArray) {
42472                 this.altFormatsArray = af.split("|");
42473             }
42474             for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
42475                 v = Date.parseDate(id + value, idf + afa[i]);
42476             }
42477         }
42478
42479         return v;
42480     }
42481 });
42482 Ext.reg('timefield', Ext.form.TimeField);
42483 Ext.form.SliderField = Ext.extend(Ext.form.Field, {
42484     
42485     
42486     useTips : true,
42487     
42488     
42489     tipText : null,
42490     
42491     
42492     actionMode: 'wrap',
42493     
42494     
42495     initComponent : function() {
42496         var cfg = Ext.copyTo({
42497             id: this.id + '-slider'
42498         }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
42499         
42500         
42501         if (this.useTips) {
42502             var plug = this.tipText ? {getText: this.tipText} : {};
42503             cfg.plugins = [new Ext.slider.Tip(plug)];
42504         }
42505         this.slider = new Ext.Slider(cfg);
42506         Ext.form.SliderField.superclass.initComponent.call(this);
42507     },    
42508     
42509     
42510     onRender : function(ct, position){
42511         this.autoCreate = {
42512             id: this.id,
42513             name: this.name,
42514             type: 'hidden',
42515             tag: 'input'    
42516         };
42517         Ext.form.SliderField.superclass.onRender.call(this, ct, position);
42518         this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
42519         this.resizeEl = this.positionEl = this.wrap;
42520         this.slider.render(this.wrap);
42521     },
42522     
42523     
42524     onResize : function(w, h, aw, ah){
42525         Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
42526         this.slider.setSize(w, h);    
42527     },
42528     
42529     
42530     initEvents : function(){
42531         Ext.form.SliderField.superclass.initEvents.call(this);
42532         this.slider.on('change', this.onChange, this);   
42533     },
42534     
42535     
42536     onChange : function(slider, v){
42537         this.setValue(v, undefined, true);
42538     },
42539     
42540     
42541     onEnable : function(){
42542         Ext.form.SliderField.superclass.onEnable.call(this);
42543         this.slider.enable();
42544     },
42545     
42546     
42547     onDisable : function(){
42548         Ext.form.SliderField.superclass.onDisable.call(this);
42549         this.slider.disable();    
42550     },
42551     
42552     
42553     beforeDestroy : function(){
42554         Ext.destroy(this.slider);
42555         Ext.form.SliderField.superclass.beforeDestroy.call(this);
42556     },
42557     
42558     
42559     alignErrorIcon : function(){
42560         this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
42561     },
42562     
42563     
42564     setMinValue : function(v){
42565         this.slider.setMinValue(v);
42566         return this;    
42567     },
42568     
42569     
42570     setMaxValue : function(v){
42571         this.slider.setMaxValue(v);
42572         return this;    
42573     },
42574     
42575     
42576     setValue : function(v, animate,  silent){
42577         
42578         
42579         if(!silent){
42580             this.slider.setValue(v, animate);
42581         }
42582         return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
42583     },
42584     
42585     
42586     getValue : function(){
42587         return this.slider.getValue();    
42588     }
42589 });
42590
42591 Ext.reg('sliderfield', Ext.form.SliderField);
42592 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
42593     
42594     
42595     
42596
42597     
42598     onRender : function(ct, position){
42599         if(!this.el){
42600             this.el = document.createElement('label');
42601             this.el.id = this.getId();
42602             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
42603             if(this.forId){
42604                 this.el.setAttribute('for', this.forId);
42605             }
42606         }
42607         Ext.form.Label.superclass.onRender.call(this, ct, position);
42608     },
42609
42610     
42611     setText : function(t, encode){
42612         var e = encode === false;
42613         this[!e ? 'text' : 'html'] = t;
42614         delete this[e ? 'text' : 'html'];
42615         if(this.rendered){
42616             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
42617         }
42618         return this;
42619     }
42620 });
42621
42622 Ext.reg('label', Ext.form.Label);
42623 Ext.form.Action = function(form, options){
42624     this.form = form;
42625     this.options = options || {};
42626 };
42627
42628
42629 Ext.form.Action.CLIENT_INVALID = 'client';
42630
42631 Ext.form.Action.SERVER_INVALID = 'server';
42632
42633 Ext.form.Action.CONNECT_FAILURE = 'connect';
42634
42635 Ext.form.Action.LOAD_FAILURE = 'load';
42636
42637 Ext.form.Action.prototype = {
42638
42639
42640
42641
42642
42643
42644
42645
42646
42647
42648
42649
42650
42651
42652     type : 'default',
42653
42654  
42655  
42656
42657     
42658     run : function(options){
42659
42660     },
42661
42662     
42663     success : function(response){
42664
42665     },
42666
42667     
42668     handleResponse : function(response){
42669
42670     },
42671
42672     
42673     failure : function(response){
42674         this.response = response;
42675         this.failureType = Ext.form.Action.CONNECT_FAILURE;
42676         this.form.afterAction(this, false);
42677     },
42678
42679     
42680     
42681     
42682     processResponse : function(response){
42683         this.response = response;
42684         if(!response.responseText && !response.responseXML){
42685             return true;
42686         }
42687         this.result = this.handleResponse(response);
42688         return this.result;
42689     },
42690
42691     
42692     getUrl : function(appendParams){
42693         var url = this.options.url || this.form.url || this.form.el.dom.action;
42694         if(appendParams){
42695             var p = this.getParams();
42696             if(p){
42697                 url = Ext.urlAppend(url, p);
42698             }
42699         }
42700         return url;
42701     },
42702
42703     
42704     getMethod : function(){
42705         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
42706     },
42707
42708     
42709     getParams : function(){
42710         var bp = this.form.baseParams;
42711         var p = this.options.params;
42712         if(p){
42713             if(typeof p == "object"){
42714                 p = Ext.urlEncode(Ext.applyIf(p, bp));
42715             }else if(typeof p == 'string' && bp){
42716                 p += '&' + Ext.urlEncode(bp);
42717             }
42718         }else if(bp){
42719             p = Ext.urlEncode(bp);
42720         }
42721         return p;
42722     },
42723
42724     
42725     createCallback : function(opts){
42726         var opts = opts || {};
42727         return {
42728             success: this.success,
42729             failure: this.failure,
42730             scope: this,
42731             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
42732             upload: this.form.fileUpload ? this.success : undefined
42733         };
42734     }
42735 };
42736
42737
42738 Ext.form.Action.Submit = function(form, options){
42739     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
42740 };
42741
42742 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
42743     
42744     
42745     type : 'submit',
42746
42747     
42748     run : function(){
42749         var o = this.options,
42750             method = this.getMethod(),
42751             isGet = method == 'GET';
42752         if(o.clientValidation === false || this.form.isValid()){
42753             if (o.submitEmptyText === false) {
42754                 var fields = this.form.items,
42755                     emptyFields = [];
42756                 fields.each(function(f) {
42757                     if (f.el.getValue() == f.emptyText) {
42758                         emptyFields.push(f);
42759                         f.el.dom.value = "";
42760                     }
42761                 });
42762             }
42763             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
42764                 form:this.form.el.dom,
42765                 url:this.getUrl(isGet),
42766                 method: method,
42767                 headers: o.headers,
42768                 params:!isGet ? this.getParams() : null,
42769                 isUpload: this.form.fileUpload
42770             }));
42771             if (o.submitEmptyText === false) {
42772                 Ext.each(emptyFields, function(f) {
42773                     if (f.applyEmptyText) {
42774                         f.applyEmptyText();
42775                     }
42776                 });
42777             }
42778         }else if (o.clientValidation !== false){ 
42779             this.failureType = Ext.form.Action.CLIENT_INVALID;
42780             this.form.afterAction(this, false);
42781         }
42782     },
42783
42784     
42785     success : function(response){
42786         var result = this.processResponse(response);
42787         if(result === true || result.success){
42788             this.form.afterAction(this, true);
42789             return;
42790         }
42791         if(result.errors){
42792             this.form.markInvalid(result.errors);
42793         }
42794         this.failureType = Ext.form.Action.SERVER_INVALID;
42795         this.form.afterAction(this, false);
42796     },
42797
42798     
42799     handleResponse : function(response){
42800         if(this.form.errorReader){
42801             var rs = this.form.errorReader.read(response);
42802             var errors = [];
42803             if(rs.records){
42804                 for(var i = 0, len = rs.records.length; i < len; i++) {
42805                     var r = rs.records[i];
42806                     errors[i] = r.data;
42807                 }
42808             }
42809             if(errors.length < 1){
42810                 errors = null;
42811             }
42812             return {
42813                 success : rs.success,
42814                 errors : errors
42815             };
42816         }
42817         return Ext.decode(response.responseText);
42818     }
42819 });
42820
42821
42822
42823 Ext.form.Action.Load = function(form, options){
42824     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
42825     this.reader = this.form.reader;
42826 };
42827
42828 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
42829     
42830     type : 'load',
42831
42832     
42833     run : function(){
42834         Ext.Ajax.request(Ext.apply(
42835                 this.createCallback(this.options), {
42836                     method:this.getMethod(),
42837                     url:this.getUrl(false),
42838                     headers: this.options.headers,
42839                     params:this.getParams()
42840         }));
42841     },
42842
42843     
42844     success : function(response){
42845         var result = this.processResponse(response);
42846         if(result === true || !result.success || !result.data){
42847             this.failureType = Ext.form.Action.LOAD_FAILURE;
42848             this.form.afterAction(this, false);
42849             return;
42850         }
42851         this.form.clearInvalid();
42852         this.form.setValues(result.data);
42853         this.form.afterAction(this, true);
42854     },
42855
42856     
42857     handleResponse : function(response){
42858         if(this.form.reader){
42859             var rs = this.form.reader.read(response);
42860             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
42861             return {
42862                 success : rs.success,
42863                 data : data
42864             };
42865         }
42866         return Ext.decode(response.responseText);
42867     }
42868 });
42869
42870
42871
42872
42873 Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
42874     constructor: function(form, opts) {
42875         Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
42876     },
42877     type : 'directload',
42878
42879     run : function(){
42880         var args = this.getParams();
42881         args.push(this.success, this);
42882         this.form.api.load.apply(window, args);
42883     },
42884
42885     getParams : function() {
42886         var buf = [], o = {};
42887         var bp = this.form.baseParams;
42888         var p = this.options.params;
42889         Ext.apply(o, p, bp);
42890         var paramOrder = this.form.paramOrder;
42891         if(paramOrder){
42892             for(var i = 0, len = paramOrder.length; i < len; i++){
42893                 buf.push(o[paramOrder[i]]);
42894             }
42895         }else if(this.form.paramsAsHash){
42896             buf.push(o);
42897         }
42898         return buf;
42899     },
42900     
42901     
42902     
42903     processResponse : function(result) {
42904         this.result = result;
42905         return result;
42906     },
42907
42908     success : function(response, trans){
42909         if(trans.type == Ext.Direct.exceptions.SERVER){
42910             response = {};
42911         }
42912         Ext.form.Action.DirectLoad.superclass.success.call(this, response);
42913     }
42914 });
42915
42916
42917 Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
42918     constructor : function(form, opts) {
42919         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
42920     },
42921     type : 'directsubmit',
42922     
42923     run : function(){
42924         var o = this.options;
42925         if(o.clientValidation === false || this.form.isValid()){
42926             
42927             
42928             this.success.params = this.getParams();
42929             this.form.api.submit(this.form.el.dom, this.success, this);
42930         }else if (o.clientValidation !== false){ 
42931             this.failureType = Ext.form.Action.CLIENT_INVALID;
42932             this.form.afterAction(this, false);
42933         }
42934     },
42935
42936     getParams : function() {
42937         var o = {};
42938         var bp = this.form.baseParams;
42939         var p = this.options.params;
42940         Ext.apply(o, p, bp);
42941         return o;
42942     },
42943     
42944     
42945     
42946     processResponse : function(result) {
42947         this.result = result;
42948         return result;
42949     },
42950
42951     success : function(response, trans){
42952         if(trans.type == Ext.Direct.exceptions.SERVER){
42953             response = {};
42954         }
42955         Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
42956     }
42957 });
42958
42959 Ext.form.Action.ACTION_TYPES = {
42960     'load' : Ext.form.Action.Load,
42961     'submit' : Ext.form.Action.Submit,
42962     'directload' : Ext.form.Action.DirectLoad,
42963     'directsubmit' : Ext.form.Action.DirectSubmit
42964 };
42965
42966 Ext.form.VTypes = function(){
42967     
42968     var alpha = /^[a-zA-Z_]+$/,
42969         alphanum = /^[a-zA-Z0-9_]+$/,
42970         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
42971         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
42972
42973     
42974     return {
42975         
42976         'email' : function(v){
42977             return email.test(v);
42978         },
42979         
42980         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
42981         
42982         'emailMask' : /[a-z0-9_\.\-@\+]/i,
42983
42984         
42985         'url' : function(v){
42986             return url.test(v);
42987         },
42988         
42989         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
42990
42991         
42992         'alpha' : function(v){
42993             return alpha.test(v);
42994         },
42995         
42996         'alphaText' : 'This field should only contain letters and _',
42997         
42998         'alphaMask' : /[a-z_]/i,
42999
43000         
43001         'alphanum' : function(v){
43002             return alphanum.test(v);
43003         },
43004         
43005         'alphanumText' : 'This field should only contain letters, numbers and _',
43006         
43007         'alphanumMask' : /[a-z0-9_]/i
43008     };
43009 }();
43010
43011 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
43012     
43013     autoExpandColumn : false,
43014     
43015     autoExpandMax : 1000,
43016     
43017     autoExpandMin : 50,
43018     
43019     columnLines : false,
43020     
43021     
43022     
43023     
43024     
43025     ddText : '{0} selected row{1}',
43026     
43027     deferRowRender : true,
43028     
43029     
43030     
43031     enableColumnHide : true,
43032     
43033     enableColumnMove : true,
43034     
43035     enableDragDrop : false,
43036     
43037     enableHdMenu : true,
43038     
43039     
43040     loadMask : false,
43041     
43042     
43043     minColumnWidth : 25,
43044     
43045     
43046     
43047     
43048     stripeRows : false,
43049     
43050     trackMouseOver : true,
43051     
43052     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
43053     
43054     view : null,
43055
43056     
43057     bubbleEvents: [],
43058
43059     
43060
43061     
43062     rendered : false,
43063     
43064     viewReady : false,
43065
43066     
43067     initComponent : function(){
43068         Ext.grid.GridPanel.superclass.initComponent.call(this);
43069
43070         if(this.columnLines){
43071             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
43072         }
43073         
43074         
43075         this.autoScroll = false;
43076         this.autoWidth = false;
43077
43078         if(Ext.isArray(this.columns)){
43079             this.colModel = new Ext.grid.ColumnModel(this.columns);
43080             delete this.columns;
43081         }
43082
43083         
43084         if(this.ds){
43085             this.store = this.ds;
43086             delete this.ds;
43087         }
43088         if(this.cm){
43089             this.colModel = this.cm;
43090             delete this.cm;
43091         }
43092         if(this.sm){
43093             this.selModel = this.sm;
43094             delete this.sm;
43095         }
43096         this.store = Ext.StoreMgr.lookup(this.store);
43097
43098         this.addEvents(
43099             
43100             
43101             'click',
43102             
43103             'dblclick',
43104             
43105             'contextmenu',
43106             
43107             'mousedown',
43108             
43109             'mouseup',
43110             
43111             'mouseover',
43112             
43113             'mouseout',
43114             
43115             'keypress',
43116             
43117             'keydown',
43118
43119             
43120             
43121             'cellmousedown',
43122             
43123             'rowmousedown',
43124             
43125             'headermousedown',
43126
43127             
43128             'groupmousedown',
43129
43130             
43131             'rowbodymousedown',
43132
43133             
43134             'containermousedown',
43135
43136             
43137             'cellclick',
43138             
43139             'celldblclick',
43140             
43141             'rowclick',
43142             
43143             'rowdblclick',
43144             
43145             'headerclick',
43146             
43147             'headerdblclick',
43148             
43149             'groupclick',
43150             
43151             'groupdblclick',
43152             
43153             'containerclick',
43154             
43155             'containerdblclick',
43156
43157             
43158             'rowbodyclick',
43159             
43160             'rowbodydblclick',
43161
43162             
43163             'rowcontextmenu',
43164             
43165             'cellcontextmenu',
43166             
43167             'headercontextmenu',
43168             
43169             'groupcontextmenu',
43170             
43171             'containercontextmenu',
43172             
43173             'rowbodycontextmenu',
43174             
43175             'bodyscroll',
43176             
43177             'columnresize',
43178             
43179             'columnmove',
43180             
43181             'sortchange',
43182             
43183             'groupchange',
43184             
43185             'reconfigure',
43186             
43187             'viewready'
43188         );
43189     },
43190
43191     
43192     onRender : function(ct, position){
43193         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
43194
43195         var c = this.getGridEl();
43196
43197         this.el.addClass('x-grid-panel');
43198
43199         this.mon(c, {
43200             scope: this,
43201             mousedown: this.onMouseDown,
43202             click: this.onClick,
43203             dblclick: this.onDblClick,
43204             contextmenu: this.onContextMenu
43205         });
43206
43207         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
43208
43209         var view = this.getView();
43210         view.init(this);
43211         view.render();
43212         this.getSelectionModel().init(this);
43213     },
43214
43215     
43216     initEvents : function(){
43217         Ext.grid.GridPanel.superclass.initEvents.call(this);
43218
43219         if(this.loadMask){
43220             this.loadMask = new Ext.LoadMask(this.bwrap,
43221                     Ext.apply({store:this.store}, this.loadMask));
43222         }
43223     },
43224
43225     initStateEvents : function(){
43226         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
43227         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
43228     },
43229
43230     applyState : function(state){
43231         var cm = this.colModel,
43232             cs = state.columns,
43233             store = this.store,
43234             s,
43235             c,
43236             oldIndex;
43237
43238         if(cs){
43239             for(var i = 0, len = cs.length; i < len; i++){
43240                 s = cs[i];
43241                 c = cm.getColumnById(s.id);
43242                 if(c){
43243                     cm.setState(i, {
43244                         hidden: s.hidden,
43245                         width: s.width    
43246                     });
43247                     oldIndex = cm.getIndexById(s.id);
43248                     if(oldIndex != i){
43249                         cm.moveColumn(oldIndex, i);
43250                     }
43251                 }
43252             }
43253         }
43254         if(store){
43255             s = state.sort;
43256             if(s){
43257                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
43258             }
43259             s = state.group;
43260             if(store.groupBy){
43261                 if(s){
43262                     store.groupBy(s);
43263                 }else{
43264                     store.clearGrouping();
43265                 }
43266             }
43267
43268         }
43269         var o = Ext.apply({}, state);
43270         delete o.columns;
43271         delete o.sort;
43272         Ext.grid.GridPanel.superclass.applyState.call(this, o);
43273     },
43274
43275     getState : function(){
43276         var o = {columns: []},
43277             store = this.store,
43278             ss,
43279             gs;
43280
43281         for(var i = 0, c; (c = this.colModel.config[i]); i++){
43282             o.columns[i] = {
43283                 id: c.id,
43284                 width: c.width
43285             };
43286             if(c.hidden){
43287                 o.columns[i].hidden = true;
43288             }
43289         }
43290         if(store){
43291             ss = store.getSortState();
43292             if(ss){
43293                 o.sort = ss;
43294             }
43295             if(store.getGroupState){
43296                 gs = store.getGroupState();
43297                 if(gs){
43298                     o.group = gs;
43299                 }
43300             }
43301         }
43302         return o;
43303     },
43304
43305     
43306     afterRender : function(){
43307         Ext.grid.GridPanel.superclass.afterRender.call(this);
43308         var v = this.view;
43309         this.on('bodyresize', v.layout, v);
43310         v.layout();
43311         if(this.deferRowRender){
43312             if (!this.deferRowRenderTask){
43313                 this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
43314             }
43315             this.deferRowRenderTask.delay(10);
43316         }else{
43317             v.afterRender();
43318         }
43319         this.viewReady = true;
43320     },
43321
43322     
43323     reconfigure : function(store, colModel){
43324         var rendered = this.rendered;
43325         if(rendered){
43326             if(this.loadMask){
43327                 this.loadMask.destroy();
43328                 this.loadMask = new Ext.LoadMask(this.bwrap,
43329                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
43330             }
43331         }
43332         if(this.view){
43333             this.view.initData(store, colModel);
43334         }
43335         this.store = store;
43336         this.colModel = colModel;
43337         if(rendered){
43338             this.view.refresh(true);
43339         }
43340         this.fireEvent('reconfigure', this, store, colModel);
43341     },
43342
43343     
43344     onDestroy : function(){
43345         if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
43346             this.deferRowRenderTask.cancel();
43347         }
43348         if(this.rendered){
43349             Ext.destroy(this.view, this.loadMask);
43350         }else if(this.store && this.store.autoDestroy){
43351             this.store.destroy();
43352         }
43353         Ext.destroy(this.colModel, this.selModel);
43354         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
43355         Ext.grid.GridPanel.superclass.onDestroy.call(this);
43356     },
43357
43358     
43359     processEvent : function(name, e){
43360         this.view.processEvent(name, e);
43361     },
43362
43363     
43364     onClick : function(e){
43365         this.processEvent('click', e);
43366     },
43367
43368     
43369     onMouseDown : function(e){
43370         this.processEvent('mousedown', e);
43371     },
43372
43373     
43374     onContextMenu : function(e, t){
43375         this.processEvent('contextmenu', e);
43376     },
43377
43378     
43379     onDblClick : function(e){
43380         this.processEvent('dblclick', e);
43381     },
43382
43383     
43384     walkCells : function(row, col, step, fn, scope){
43385         var cm    = this.colModel,
43386             clen  = cm.getColumnCount(),
43387             ds    = this.store,
43388             rlen  = ds.getCount(),
43389             first = true;
43390
43391         if(step < 0){
43392             if(col < 0){
43393                 row--;
43394                 first = false;
43395             }
43396             while(row >= 0){
43397                 if(!first){
43398                     col = clen-1;
43399                 }
43400                 first = false;
43401                 while(col >= 0){
43402                     if(fn.call(scope || this, row, col, cm) === true){
43403                         return [row, col];
43404                     }
43405                     col--;
43406                 }
43407                 row--;
43408             }
43409         } else {
43410             if(col >= clen){
43411                 row++;
43412                 first = false;
43413             }
43414             while(row < rlen){
43415                 if(!first){
43416                     col = 0;
43417                 }
43418                 first = false;
43419                 while(col < clen){
43420                     if(fn.call(scope || this, row, col, cm) === true){
43421                         return [row, col];
43422                     }
43423                     col++;
43424                 }
43425                 row++;
43426             }
43427         }
43428         return null;
43429     },
43430
43431     
43432     getGridEl : function(){
43433         return this.body;
43434     },
43435
43436     
43437     stopEditing : Ext.emptyFn,
43438
43439     
43440     getSelectionModel : function(){
43441         if(!this.selModel){
43442             this.selModel = new Ext.grid.RowSelectionModel(
43443                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
43444         }
43445         return this.selModel;
43446     },
43447
43448     
43449     getStore : function(){
43450         return this.store;
43451     },
43452
43453     
43454     getColumnModel : function(){
43455         return this.colModel;
43456     },
43457
43458     
43459     getView : function(){
43460         if(!this.view){
43461             this.view = new Ext.grid.GridView(this.viewConfig);
43462         }
43463         return this.view;
43464     },
43465     
43466     getDragDropText : function(){
43467         var count = this.selModel.getCount();
43468         return String.format(this.ddText, count, count == 1 ? '' : 's');
43469     }
43470
43471     
43472     
43473     
43474     
43475     
43476     
43477     
43478     
43479     
43480     
43481     
43482     
43483     
43484     
43485     
43486     
43487     
43488     
43489     
43490     
43491     
43492     
43493     
43494     
43495     
43496     
43497     
43498     
43499     
43500     
43501     
43502
43503
43504
43505     
43506     
43507     
43508     
43509     
43510     
43511     
43512     
43513     
43514     
43515     
43516     
43517     
43518     
43519     
43520     
43521 });
43522 Ext.reg('grid', Ext.grid.GridPanel);
43523 Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
43524     
43525
43526     
43527
43528     
43529
43530     
43531
43532     
43533
43534     
43535     deferEmptyText : true,
43536
43537     
43538     scrollOffset : undefined,
43539
43540     
43541     autoFill : false,
43542
43543     
43544     forceFit : false,
43545
43546     
43547     sortClasses : ['sort-asc', 'sort-desc'],
43548
43549     
43550     sortAscText : 'Sort Ascending',
43551
43552     
43553     sortDescText : 'Sort Descending',
43554
43555     
43556     columnsText : 'Columns',
43557
43558     
43559     selectedRowClass : 'x-grid3-row-selected',
43560
43561     
43562     borderWidth : 2,
43563     tdClass : 'x-grid3-cell',
43564     hdCls : 'x-grid3-hd',
43565     markDirty : true,
43566
43567     
43568     cellSelectorDepth : 4,
43569     
43570     rowSelectorDepth : 10,
43571
43572     
43573     rowBodySelectorDepth : 10,
43574
43575     
43576     cellSelector : 'td.x-grid3-cell',
43577     
43578     rowSelector : 'div.x-grid3-row',
43579
43580     
43581     rowBodySelector : 'div.x-grid3-row-body',
43582
43583     
43584     firstRowCls: 'x-grid3-row-first',
43585     lastRowCls: 'x-grid3-row-last',
43586     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
43587
43588     constructor : function(config){
43589         Ext.apply(this, config);
43590         
43591         this.addEvents(
43592             
43593             'beforerowremoved',
43594             
43595             'beforerowsinserted',
43596             
43597             'beforerefresh',
43598             
43599             'rowremoved',
43600             
43601             'rowsinserted',
43602             
43603             'rowupdated',
43604             
43605             'refresh'
43606         );
43607         Ext.grid.GridView.superclass.constructor.call(this);
43608     },
43609
43610     
43611
43612     
43613     initTemplates : function(){
43614         var ts = this.templates || {};
43615         if(!ts.master){
43616             ts.master = new Ext.Template(
43617                 '<div class="x-grid3" hidefocus="true">',
43618                     '<div class="x-grid3-viewport">',
43619                         '<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>',
43620                         '<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
43621                     '</div>',
43622                     '<div class="x-grid3-resize-marker">&#160;</div>',
43623                     '<div class="x-grid3-resize-proxy">&#160;</div>',
43624                 '</div>'
43625             );
43626         }
43627
43628         if(!ts.header){
43629             ts.header = new Ext.Template(
43630                 '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
43631                 '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
43632                 '</table>'
43633             );
43634         }
43635
43636         if(!ts.hcell){
43637             ts.hcell = new Ext.Template(
43638                 '<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>' : '',
43639                 '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
43640                 '</div></td>'
43641             );
43642         }
43643
43644         if(!ts.body){
43645             ts.body = new Ext.Template('{rows}');
43646         }
43647
43648         if(!ts.row){
43649             ts.row = new Ext.Template(
43650                 '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
43651                 '<tbody><tr>{cells}</tr>',
43652                 (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>' : ''),
43653                 '</tbody></table></div>'
43654             );
43655         }
43656
43657         if(!ts.cell){
43658             ts.cell = new Ext.Template(
43659                     '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
43660                     '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
43661                     '</td>'
43662                     );
43663         }
43664
43665         for(var k in ts){
43666             var t = ts[k];
43667             if(t && Ext.isFunction(t.compile) && !t.compiled){
43668                 t.disableFormats = true;
43669                 t.compile();
43670             }
43671         }
43672
43673         this.templates = ts;
43674         this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
43675     },
43676
43677     
43678     fly : function(el){
43679         if(!this._flyweight){
43680             this._flyweight = new Ext.Element.Flyweight(document.body);
43681         }
43682         this._flyweight.dom = el;
43683         return this._flyweight;
43684     },
43685
43686     
43687     getEditorParent : function(){
43688         return this.scroller.dom;
43689     },
43690
43691     
43692     initElements : function(){
43693         var E = Ext.Element;
43694
43695         var el = this.grid.getGridEl().dom.firstChild;
43696         var cs = el.childNodes;
43697
43698         this.el = new E(el);
43699
43700         this.mainWrap = new E(cs[0]);
43701         this.mainHd = new E(this.mainWrap.dom.firstChild);
43702
43703         if(this.grid.hideHeaders){
43704             this.mainHd.setDisplayed(false);
43705         }
43706
43707         this.innerHd = this.mainHd.dom.firstChild;
43708         this.scroller = new E(this.mainWrap.dom.childNodes[1]);
43709         if(this.forceFit){
43710             this.scroller.setStyle('overflow-x', 'hidden');
43711         }
43712         
43713         this.mainBody = new E(this.scroller.dom.firstChild);
43714
43715         this.focusEl = new E(this.scroller.dom.childNodes[1]);
43716         this.focusEl.swallowEvent('click', true);
43717
43718         this.resizeMarker = new E(cs[1]);
43719         this.resizeProxy = new E(cs[2]);
43720     },
43721
43722     
43723     getRows : function(){
43724         return this.hasRows() ? this.mainBody.dom.childNodes : [];
43725     },
43726
43727     
43728
43729     
43730     findCell : function(el){
43731         if(!el){
43732             return false;
43733         }
43734         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
43735     },
43736
43737     
43738     findCellIndex : function(el, requiredCls){
43739         var cell = this.findCell(el);
43740         if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
43741             return this.getCellIndex(cell);
43742         }
43743         return false;
43744     },
43745
43746     
43747     getCellIndex : function(el){
43748         if(el){
43749             var m = el.className.match(this.colRe);
43750             if(m && m[1]){
43751                 return this.cm.getIndexById(m[1]);
43752             }
43753         }
43754         return false;
43755     },
43756
43757     
43758     findHeaderCell : function(el){
43759         var cell = this.findCell(el);
43760         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
43761     },
43762
43763     
43764     findHeaderIndex : function(el){
43765         return this.findCellIndex(el, this.hdCls);
43766     },
43767
43768     
43769     findRow : function(el){
43770         if(!el){
43771             return false;
43772         }
43773         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
43774     },
43775
43776     
43777     findRowIndex : function(el){
43778         var r = this.findRow(el);
43779         return r ? r.rowIndex : false;
43780     },
43781
43782     
43783     findRowBody : function(el){
43784         if(!el){
43785             return false;
43786         }
43787         return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
43788     },
43789
43790     
43791
43792     
43793     getRow : function(row){
43794         return this.getRows()[row];
43795     },
43796
43797     
43798     getCell : function(row, col){
43799         return this.getRow(row).getElementsByTagName('td')[col];
43800     },
43801
43802     
43803     getHeaderCell : function(index){
43804         return this.mainHd.dom.getElementsByTagName('td')[index];
43805     },
43806
43807     
43808
43809     
43810     addRowClass : function(row, cls){
43811         var r = this.getRow(row);
43812         if(r){
43813             this.fly(r).addClass(cls);
43814         }
43815     },
43816
43817     
43818     removeRowClass : function(row, cls){
43819         var r = this.getRow(row);
43820         if(r){
43821             this.fly(r).removeClass(cls);
43822         }
43823     },
43824
43825     
43826     removeRow : function(row){
43827         Ext.removeNode(this.getRow(row));
43828         this.syncFocusEl(row);
43829     },
43830
43831     
43832     removeRows : function(firstRow, lastRow){
43833         var bd = this.mainBody.dom;
43834         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
43835             Ext.removeNode(bd.childNodes[firstRow]);
43836         }
43837         this.syncFocusEl(firstRow);
43838     },
43839
43840     
43841
43842     
43843     getScrollState : function(){
43844         var sb = this.scroller.dom;
43845         return {left: sb.scrollLeft, top: sb.scrollTop};
43846     },
43847
43848     
43849     restoreScroll : function(state){
43850         var sb = this.scroller.dom;
43851         sb.scrollLeft = state.left;
43852         sb.scrollTop = state.top;
43853     },
43854
43855     
43856     scrollToTop : function(){
43857         this.scroller.dom.scrollTop = 0;
43858         this.scroller.dom.scrollLeft = 0;
43859     },
43860
43861     
43862     syncScroll : function(){
43863         this.syncHeaderScroll();
43864         var mb = this.scroller.dom;
43865         this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
43866     },
43867
43868     
43869     syncHeaderScroll : function(){
43870         var mb = this.scroller.dom;
43871         this.innerHd.scrollLeft = mb.scrollLeft;
43872         this.innerHd.scrollLeft = mb.scrollLeft; 
43873     },
43874
43875     
43876     updateSortIcon : function(col, dir){
43877         var sc = this.sortClasses;
43878         var hds = this.mainHd.select('td').removeClass(sc);
43879         hds.item(col).addClass(sc[dir == 'DESC' ? 1 : 0]);
43880     },
43881
43882     
43883     updateAllColumnWidths : function(){
43884         var tw   = this.getTotalWidth(),
43885             clen = this.cm.getColumnCount(),
43886             ws   = [],
43887             len,
43888             i;
43889
43890         for(i = 0; i < clen; i++){
43891             ws[i] = this.getColumnWidth(i);
43892         }
43893
43894         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43895         this.innerHd.firstChild.firstChild.style.width = tw;
43896         this.mainBody.dom.style.width = tw;
43897
43898         for(i = 0; i < clen; i++){
43899             var hd = this.getHeaderCell(i);
43900             hd.style.width = ws[i];
43901         }
43902
43903         var ns = this.getRows(), row, trow;
43904         for(i = 0, len = ns.length; i < len; i++){
43905             row = ns[i];
43906             row.style.width = tw;
43907             if(row.firstChild){
43908                 row.firstChild.style.width = tw;
43909                 trow = row.firstChild.rows[0];
43910                 for (var j = 0; j < clen; j++) {
43911                    trow.childNodes[j].style.width = ws[j];
43912                 }
43913             }
43914         }
43915
43916         this.onAllColumnWidthsUpdated(ws, tw);
43917     },
43918
43919     
43920     updateColumnWidth : function(col, width){
43921         var w = this.getColumnWidth(col);
43922         var tw = this.getTotalWidth();
43923         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43924         this.innerHd.firstChild.firstChild.style.width = tw;
43925         this.mainBody.dom.style.width = tw;
43926         var hd = this.getHeaderCell(col);
43927         hd.style.width = w;
43928
43929         var ns = this.getRows(), row;
43930         for(var i = 0, len = ns.length; i < len; i++){
43931             row = ns[i];
43932             row.style.width = tw;
43933             if(row.firstChild){
43934                 row.firstChild.style.width = tw;
43935                 row.firstChild.rows[0].childNodes[col].style.width = w;
43936             }
43937         }
43938
43939         this.onColumnWidthUpdated(col, w, tw);
43940     },
43941
43942     
43943     updateColumnHidden : function(col, hidden){
43944         var tw = this.getTotalWidth();
43945         this.innerHd.firstChild.style.width = this.getOffsetWidth();
43946         this.innerHd.firstChild.firstChild.style.width = tw;
43947         this.mainBody.dom.style.width = tw;
43948         var display = hidden ? 'none' : '';
43949
43950         var hd = this.getHeaderCell(col);
43951         hd.style.display = display;
43952
43953         var ns = this.getRows(), row;
43954         for(var i = 0, len = ns.length; i < len; i++){
43955             row = ns[i];
43956             row.style.width = tw;
43957             if(row.firstChild){
43958                 row.firstChild.style.width = tw;
43959                 row.firstChild.rows[0].childNodes[col].style.display = display;
43960             }
43961         }
43962
43963         this.onColumnHiddenUpdated(col, hidden, tw);
43964         delete this.lastViewWidth; 
43965         this.layout();
43966     },
43967
43968     
43969     doRender : function(columns, records, store, startRow, colCount, stripe) {
43970         var templates    = this.templates,
43971             cellTemplate = templates.cell,
43972             rowTemplate  = templates.row,
43973             last         = colCount - 1;
43974
43975         var tstyle = 'width:' + this.getTotalWidth() + ';';
43976
43977         
43978         var rowBuffer = [],
43979             colBuffer = [],
43980             rowParams = {tstyle: tstyle},
43981             meta      = {},
43982             column,
43983             record;
43984
43985         
43986         for (var j = 0, len = records.length; j < len; j++) {
43987             record    = records[j];
43988             colBuffer = [];
43989
43990             var rowIndex = j + startRow;
43991
43992             
43993             for (var i = 0; i < colCount; i++) {
43994                 column = columns[i];
43995
43996                 meta.id    = column.id;
43997                 meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
43998                 meta.attr  = meta.cellAttr = '';
43999                 meta.style = column.style;
44000                 meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
44001
44002                 if (Ext.isEmpty(meta.value)) {
44003                     meta.value = '&#160;';
44004                 }
44005
44006                 if (this.markDirty && record.dirty && Ext.isDefined(record.modified[column.name])) {
44007                     meta.css += ' x-grid3-dirty-cell';
44008                 }
44009
44010                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
44011             }
44012
44013             
44014             var alt = [];
44015
44016             if (stripe && ((rowIndex + 1) % 2 === 0)) {
44017                 alt[0] = 'x-grid3-row-alt';
44018             }
44019
44020             if (record.dirty) {
44021                 alt[1] = ' x-grid3-dirty-row';
44022             }
44023
44024             rowParams.cols = colCount;
44025
44026             if (this.getRowClass) {
44027                 alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
44028             }
44029
44030             rowParams.alt   = alt.join(' ');
44031             rowParams.cells = colBuffer.join('');
44032
44033             rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
44034         }
44035
44036         return rowBuffer.join('');
44037     },
44038
44039     
44040     processRows : function(startRow, skipStripe) {
44041         if (!this.ds || this.ds.getCount() < 1) {
44042             return;
44043         }
44044
44045         var rows = this.getRows(),
44046             len  = rows.length,
44047             i, r;
44048
44049         skipStripe = skipStripe || !this.grid.stripeRows;
44050         startRow   = startRow   || 0;
44051
44052         for (i = 0; i<len; i++) {
44053             r = rows[i];
44054             if (r) {
44055                 r.rowIndex = i;
44056                 if (!skipStripe) {
44057                     r.className = r.className.replace(this.rowClsRe, ' ');
44058                     if ((i + 1) % 2 === 0){
44059                         r.className += ' x-grid3-row-alt';
44060                     }
44061                 }
44062             }
44063         }
44064
44065         
44066         if (startRow === 0) {
44067             Ext.fly(rows[0]).addClass(this.firstRowCls);
44068         }
44069
44070         Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
44071     },
44072
44073     afterRender : function(){
44074         if(!this.ds || !this.cm){
44075             return;
44076         }
44077         this.mainBody.dom.innerHTML = this.renderRows() || '&#160;';
44078         this.processRows(0, true);
44079
44080         if(this.deferEmptyText !== true){
44081             this.applyEmptyText();
44082         }
44083         this.grid.fireEvent('viewready', this.grid);
44084     },
44085
44086     
44087     renderUI : function() {
44088         var templates = this.templates,
44089             header    = this.renderHeaders(),
44090             body      = templates.body.apply({rows:'&#160;'});
44091
44092         var html = templates.master.apply({
44093             body  : body,
44094             header: header,
44095             ostyle: 'width:' + this.getOffsetWidth() + ';',
44096             bstyle: 'width:' + this.getTotalWidth()  + ';'
44097         });
44098
44099         var g = this.grid;
44100
44101         g.getGridEl().dom.innerHTML = html;
44102
44103         this.initElements();
44104
44105         
44106         Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
44107
44108         this.mainHd.on({
44109             scope    : this,
44110             mouseover: this.handleHdOver,
44111             mouseout : this.handleHdOut,
44112             mousemove: this.handleHdMove
44113         });
44114
44115         this.scroller.on('scroll', this.syncScroll,  this);
44116         if (g.enableColumnResize !== false) {
44117             this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
44118         }
44119
44120         if (g.enableColumnMove) {
44121             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
44122             this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
44123         }
44124
44125         if (g.enableHdMenu !== false) {
44126             this.hmenu = new Ext.menu.Menu({id: g.id + '-hctx'});
44127             this.hmenu.add(
44128                 {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
44129                 {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
44130             );
44131
44132             if (g.enableColumnHide !== false) {
44133                 this.colMenu = new Ext.menu.Menu({id:g.id + '-hcols-menu'});
44134                 this.colMenu.on({
44135                     scope     : this,
44136                     beforeshow: this.beforeColMenuShow,
44137                     itemclick : this.handleHdMenuClick
44138                 });
44139                 this.hmenu.add('-', {
44140                     itemId:'columns',
44141                     hideOnClick: false,
44142                     text: this.columnsText,
44143                     menu: this.colMenu,
44144                     iconCls: 'x-cols-icon'
44145                 });
44146             }
44147
44148             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
44149         }
44150
44151         if (g.trackMouseOver) {
44152             this.mainBody.on({
44153                 scope    : this,
44154                 mouseover: this.onRowOver,
44155                 mouseout : this.onRowOut
44156             });
44157         }
44158
44159         if (g.enableDragDrop || g.enableDrag) {
44160             this.dragZone = new Ext.grid.GridDragZone(g, {
44161                 ddGroup : g.ddGroup || 'GridDD'
44162             });
44163         }
44164
44165         this.updateHeaderSortState();
44166     },
44167
44168     
44169     processEvent : function(name, e) {
44170         var t = e.getTarget(),
44171             g = this.grid,
44172             header = this.findHeaderIndex(t);
44173         g.fireEvent(name, e);
44174         if (header !== false) {
44175             g.fireEvent('header' + name, g, header, e);
44176         } else {
44177             var row = this.findRowIndex(t),
44178                 cell,
44179                 body;
44180             if (row !== false) {
44181                 g.fireEvent('row' + name, g, row, e);
44182                 cell = this.findCellIndex(t);
44183                 if (cell !== false) {
44184                     g.fireEvent('cell' + name, g, row, cell, e);
44185                 } else {
44186                     body = this.findRowBody(t);
44187                     if (body) {
44188                         g.fireEvent('rowbody' + name, g, row, e);
44189                     }
44190                 }
44191             } else {
44192                 g.fireEvent('container' + name, g, e);
44193             }
44194         }
44195     },
44196
44197     
44198     layout : function() {
44199         if(!this.mainBody){
44200             return; 
44201         }
44202         var g = this.grid;
44203         var c = g.getGridEl();
44204         var csize = c.getSize(true);
44205         var vw = csize.width;
44206
44207         if(!g.hideHeaders && (vw < 20 || csize.height < 20)){ 
44208             return;
44209         }
44210
44211         if(g.autoHeight){
44212             this.scroller.dom.style.overflow = 'visible';
44213             if(Ext.isWebKit){
44214                 this.scroller.dom.style.position = 'static';
44215             }
44216         }else{
44217             this.el.setSize(csize.width, csize.height);
44218
44219             var hdHeight = this.mainHd.getHeight();
44220             var vh = csize.height - (hdHeight);
44221
44222             this.scroller.setSize(vw, vh);
44223             if(this.innerHd){
44224                 this.innerHd.style.width = (vw)+'px';
44225             }
44226         }
44227         if(this.forceFit){
44228             if(this.lastViewWidth != vw){
44229                 this.fitColumns(false, false);
44230                 this.lastViewWidth = vw;
44231             }
44232         }else {
44233             this.autoExpand();
44234             this.syncHeaderScroll();
44235         }
44236         this.onLayout(vw, vh);
44237     },
44238
44239     
44240     
44241     onLayout : function(vw, vh){
44242         
44243     },
44244
44245     onColumnWidthUpdated : function(col, w, tw){
44246         
44247     },
44248
44249     onAllColumnWidthsUpdated : function(ws, tw){
44250         
44251     },
44252
44253     onColumnHiddenUpdated : function(col, hidden, tw){
44254         
44255     },
44256
44257     updateColumnText : function(col, text){
44258         
44259     },
44260
44261     afterMove : function(colIndex){
44262         
44263     },
44264
44265     
44266     
44267     init : function(grid){
44268         this.grid = grid;
44269
44270         this.initTemplates();
44271         this.initData(grid.store, grid.colModel);
44272         this.initUI(grid);
44273     },
44274
44275     
44276     getColumnId : function(index){
44277       return this.cm.getColumnId(index);
44278     },
44279
44280     
44281     getOffsetWidth : function() {
44282         return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
44283     },
44284
44285     getScrollOffset: function(){
44286         return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
44287     },
44288
44289     
44290     renderHeaders : function() {
44291         var cm   = this.cm,
44292             ts   = this.templates,
44293             ct   = ts.hcell,
44294             cb   = [],
44295             p    = {},
44296             len  = cm.getColumnCount(),
44297             last = len - 1;
44298
44299         for (var i = 0; i < len; i++) {
44300             p.id = cm.getColumnId(i);
44301             p.value = cm.getColumnHeader(i) || '';
44302             p.style = this.getColumnStyle(i, true);
44303             p.tooltip = this.getColumnTooltip(i);
44304             p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
44305
44306             if (cm.config[i].align == 'right') {
44307                 p.istyle = 'padding-right:16px';
44308             } else {
44309                 delete p.istyle;
44310             }
44311             cb[cb.length] = ct.apply(p);
44312         }
44313         return ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'});
44314     },
44315
44316     
44317     getColumnTooltip : function(i){
44318         var tt = this.cm.getColumnTooltip(i);
44319         if(tt){
44320             if(Ext.QuickTips.isEnabled()){
44321                 return 'ext:qtip="'+tt+'"';
44322             }else{
44323                 return 'title="'+tt+'"';
44324             }
44325         }
44326         return '';
44327     },
44328
44329     
44330     beforeUpdate : function(){
44331         this.grid.stopEditing(true);
44332     },
44333
44334     
44335     updateHeaders : function(){
44336         this.innerHd.firstChild.innerHTML = this.renderHeaders();
44337         this.innerHd.firstChild.style.width = this.getOffsetWidth();
44338         this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
44339     },
44340
44341     
44342     focusRow : function(row){
44343         this.focusCell(row, 0, false);
44344     },
44345
44346     
44347     focusCell : function(row, col, hscroll){
44348         this.syncFocusEl(this.ensureVisible(row, col, hscroll));
44349         if(Ext.isGecko){
44350             this.focusEl.focus();
44351         }else{
44352             this.focusEl.focus.defer(1, this.focusEl);
44353         }
44354     },
44355
44356     resolveCell : function(row, col, hscroll){
44357         if(!Ext.isNumber(row)){
44358             row = row.rowIndex;
44359         }
44360         if(!this.ds){
44361             return null;
44362         }
44363         if(row < 0 || row >= this.ds.getCount()){
44364             return null;
44365         }
44366         col = (col !== undefined ? col : 0);
44367
44368         var rowEl = this.getRow(row),
44369             cm = this.cm,
44370             colCount = cm.getColumnCount(),
44371             cellEl;
44372         if(!(hscroll === false && col === 0)){
44373             while(col < colCount && cm.isHidden(col)){
44374                 col++;
44375             }
44376             cellEl = this.getCell(row, col);
44377         }
44378
44379         return {row: rowEl, cell: cellEl};
44380     },
44381
44382     getResolvedXY : function(resolved){
44383         if(!resolved){
44384             return null;
44385         }
44386         var s = this.scroller.dom, c = resolved.cell, r = resolved.row;
44387         return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];
44388     },
44389
44390     syncFocusEl : function(row, col, hscroll){
44391         var xy = row;
44392         if(!Ext.isArray(xy)){
44393             row = Math.min(row, Math.max(0, this.getRows().length-1));
44394             if (isNaN(row)) {
44395                 return;
44396             }
44397             xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
44398         }
44399         this.focusEl.setXY(xy||this.scroller.getXY());
44400     },
44401
44402     ensureVisible : function(row, col, hscroll){
44403         var resolved = this.resolveCell(row, col, hscroll);
44404         if(!resolved || !resolved.row){
44405             return;
44406         }
44407
44408         var rowEl = resolved.row,
44409             cellEl = resolved.cell,
44410             c = this.scroller.dom,
44411             ctop = 0,
44412             p = rowEl,
44413             stop = this.el.dom;
44414
44415         while(p && p != stop){
44416             ctop += p.offsetTop;
44417             p = p.offsetParent;
44418         }
44419
44420         ctop -= this.mainHd.dom.offsetHeight;
44421         stop = parseInt(c.scrollTop, 10);
44422
44423         var cbot = ctop + rowEl.offsetHeight,
44424             ch = c.clientHeight,
44425             sbot = stop + ch;
44426
44427
44428         if(ctop < stop){
44429           c.scrollTop = ctop;
44430         }else if(cbot > sbot){
44431             c.scrollTop = cbot-ch;
44432         }
44433
44434         if(hscroll !== false){
44435             var cleft = parseInt(cellEl.offsetLeft, 10);
44436             var cright = cleft + cellEl.offsetWidth;
44437
44438             var sleft = parseInt(c.scrollLeft, 10);
44439             var sright = sleft + c.clientWidth;
44440             if(cleft < sleft){
44441                 c.scrollLeft = cleft;
44442             }else if(cright > sright){
44443                 c.scrollLeft = cright-c.clientWidth;
44444             }
44445         }
44446         return this.getResolvedXY(resolved);
44447     },
44448
44449     
44450     insertRows : function(dm, firstRow, lastRow, isUpdate) {
44451         var last = dm.getCount() - 1;
44452         if( !isUpdate && firstRow === 0 && lastRow >= last) {
44453             this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
44454                 this.refresh();
44455             this.fireEvent('rowsinserted', this, firstRow, lastRow);
44456         } else {
44457             if (!isUpdate) {
44458                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
44459             }
44460             var html = this.renderRows(firstRow, lastRow),
44461                 before = this.getRow(firstRow);
44462             if (before) {
44463                 if(firstRow === 0){
44464                     Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
44465                 }
44466                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
44467             } else {
44468                 var r = this.getRow(last - 1);
44469                 if(r){
44470                     Ext.fly(r).removeClass(this.lastRowCls);
44471                 }
44472                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
44473             }
44474             if (!isUpdate) {
44475                 this.fireEvent('rowsinserted', this, firstRow, lastRow);
44476                 this.processRows(firstRow);
44477             } else if (firstRow === 0 || firstRow >= last) {
44478                 
44479                 Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
44480             }
44481         }
44482         this.syncFocusEl(firstRow);
44483     },
44484
44485     
44486     deleteRows : function(dm, firstRow, lastRow){
44487         if(dm.getRowCount()<1){
44488             this.refresh();
44489         }else{
44490             this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
44491
44492             this.removeRows(firstRow, lastRow);
44493
44494             this.processRows(firstRow);
44495             this.fireEvent('rowsdeleted', this, firstRow, lastRow);
44496         }
44497     },
44498
44499     
44500     getColumnStyle : function(col, isHeader){
44501         var style = !isHeader ? (this.cm.config[col].css || '') : '';
44502         style += 'width:'+this.getColumnWidth(col)+';';
44503         if(this.cm.isHidden(col)){
44504             style += 'display:none;';
44505         }
44506         var align = this.cm.config[col].align;
44507         if(align){
44508             style += 'text-align:'+align+';';
44509         }
44510         return style;
44511     },
44512
44513     
44514     getColumnWidth : function(col){
44515         var w = this.cm.getColumnWidth(col);
44516         if(Ext.isNumber(w)){
44517             return (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? w : (w - this.borderWidth > 0 ? w - this.borderWidth : 0)) + 'px';
44518         }
44519         return w;
44520     },
44521
44522     
44523     getTotalWidth : function(){
44524         return this.cm.getTotalWidth()+'px';
44525     },
44526
44527     
44528     fitColumns : function(preventRefresh, onlyExpand, omitColumn){
44529         var cm = this.cm, i;
44530         var tw = cm.getTotalWidth(false);
44531         var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
44532
44533         if(aw < 20){ 
44534             return;
44535         }
44536         var extra = aw - tw;
44537
44538         if(extra === 0){
44539             return false;
44540         }
44541
44542         var vc = cm.getColumnCount(true);
44543         var ac = vc-(Ext.isNumber(omitColumn) ? 1 : 0);
44544         if(ac === 0){
44545             ac = 1;
44546             omitColumn = undefined;
44547         }
44548         var colCount = cm.getColumnCount();
44549         var cols = [];
44550         var extraCol = 0;
44551         var width = 0;
44552         var w;
44553         for (i = 0; i < colCount; i++){
44554             if(!cm.isFixed(i) && i !== omitColumn){
44555                 w = cm.getColumnWidth(i);
44556                 cols.push(i, w);
44557                 if(!cm.isHidden(i)){
44558                     extraCol = i;
44559                     width += w;
44560                 }
44561             }
44562         }
44563         var frac = (aw - cm.getTotalWidth())/width;
44564         while (cols.length){
44565             w = cols.pop();
44566             i = cols.pop();
44567             cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
44568         }
44569
44570         if((tw = cm.getTotalWidth(false)) > aw){
44571             var adjustCol = ac != vc ? omitColumn : extraCol;
44572              cm.setColumnWidth(adjustCol, Math.max(1,
44573                      cm.getColumnWidth(adjustCol)- (tw-aw)), true);
44574         }
44575
44576         if(preventRefresh !== true){
44577             this.updateAllColumnWidths();
44578         }
44579
44580
44581         return true;
44582     },
44583
44584     
44585     autoExpand : function(preventUpdate){
44586         var g = this.grid, cm = this.cm;
44587         if(!this.userResized && g.autoExpandColumn){
44588             var tw = cm.getTotalWidth(false);
44589             var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
44590             if(tw != aw){
44591                 var ci = cm.getIndexById(g.autoExpandColumn);
44592                 var currentWidth = cm.getColumnWidth(ci);
44593                 var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
44594                 if(cw != currentWidth){
44595                     cm.setColumnWidth(ci, cw, true);
44596                     if(preventUpdate !== true){
44597                         this.updateColumnWidth(ci, cw);
44598                     }
44599                 }
44600             }
44601         }
44602     },
44603
44604     
44605     getColumnData : function(){
44606         
44607         var cs       = [],
44608             cm       = this.cm,
44609             colCount = cm.getColumnCount();
44610
44611         for (var i = 0; i < colCount; i++) {
44612             var name = cm.getDataIndex(i);
44613
44614             cs[i] = {
44615                 name    : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
44616                 renderer: cm.getRenderer(i),
44617                 scope   : cm.getRendererScope(i),
44618                 id      : cm.getColumnId(i),
44619                 style   : this.getColumnStyle(i)
44620             };
44621         }
44622
44623         return cs;
44624     },
44625
44626     
44627     renderRows : function(startRow, endRow){
44628         
44629         var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
44630         var colCount = cm.getColumnCount();
44631
44632         if(ds.getCount() < 1){
44633             return '';
44634         }
44635
44636         var cs = this.getColumnData();
44637
44638         startRow = startRow || 0;
44639         endRow = !Ext.isDefined(endRow) ? ds.getCount()-1 : endRow;
44640
44641         
44642         var rs = ds.getRange(startRow, endRow);
44643
44644         return this.doRender(cs, rs, ds, startRow, colCount, stripe);
44645     },
44646
44647     
44648     renderBody : function(){
44649         var markup = this.renderRows() || '&#160;';
44650         return this.templates.body.apply({rows: markup});
44651     },
44652
44653     
44654     refreshRow : function(record){
44655         var ds = this.ds, index;
44656         if(Ext.isNumber(record)){
44657             index = record;
44658             record = ds.getAt(index);
44659             if(!record){
44660                 return;
44661             }
44662         }else{
44663             index = ds.indexOf(record);
44664             if(index < 0){
44665                 return;
44666             }
44667         }
44668         this.insertRows(ds, index, index, true);
44669         this.getRow(index).rowIndex = index;
44670         this.onRemove(ds, record, index+1, true);
44671         this.fireEvent('rowupdated', this, index, record);
44672     },
44673
44674     
44675     refresh : function(headersToo){
44676         this.fireEvent('beforerefresh', this);
44677         this.grid.stopEditing(true);
44678
44679         var result = this.renderBody();
44680         this.mainBody.update(result).setWidth(this.getTotalWidth());
44681         if(headersToo === true){
44682             this.updateHeaders();
44683             this.updateHeaderSortState();
44684         }
44685         this.processRows(0, true);
44686         this.layout();
44687         this.applyEmptyText();
44688         this.fireEvent('refresh', this);
44689     },
44690
44691     
44692     applyEmptyText : function(){
44693         if(this.emptyText && !this.hasRows()){
44694             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
44695         }
44696     },
44697
44698     
44699     updateHeaderSortState : function(){
44700         var state = this.ds.getSortState();
44701         if (!state) {
44702             return;
44703         }
44704
44705         if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
44706             this.grid.fireEvent('sortchange', this.grid, state);
44707         }
44708
44709         this.sortState = state;
44710
44711         var sortColumn = this.cm.findColumnIndex(state.field);
44712         if (sortColumn != -1){
44713             var sortDir = state.direction;
44714             this.updateSortIcon(sortColumn, sortDir);
44715         }
44716     },
44717
44718     
44719     clearHeaderSortState : function(){
44720         if (!this.sortState) {
44721             return;
44722         }
44723         this.grid.fireEvent('sortchange', this.grid, null);
44724         this.mainHd.select('td').removeClass(this.sortClasses);
44725         delete this.sortState;
44726     },
44727
44728     
44729     destroy : function(){
44730         if (this.scrollToTopTask && this.scrollToTopTask.cancel){
44731             this.scrollToTopTask.cancel();
44732         }
44733         if(this.colMenu){
44734             Ext.menu.MenuMgr.unregister(this.colMenu);
44735             this.colMenu.destroy();
44736             delete this.colMenu;
44737         }
44738         if(this.hmenu){
44739             Ext.menu.MenuMgr.unregister(this.hmenu);
44740             this.hmenu.destroy();
44741             delete this.hmenu;
44742         }
44743
44744         this.initData(null, null);
44745         this.purgeListeners();
44746         Ext.fly(this.innerHd).un("click", this.handleHdDown, this);
44747
44748         if(this.grid.enableColumnMove){
44749             Ext.destroy(
44750                 this.columnDrag.el,
44751                 this.columnDrag.proxy.ghost,
44752                 this.columnDrag.proxy.el,
44753                 this.columnDrop.el,
44754                 this.columnDrop.proxyTop,
44755                 this.columnDrop.proxyBottom,
44756                 this.columnDrag.dragData.ddel,
44757                 this.columnDrag.dragData.header
44758             );
44759             if (this.columnDrag.proxy.anim) {
44760                 Ext.destroy(this.columnDrag.proxy.anim);
44761             }
44762             delete this.columnDrag.proxy.ghost;
44763             delete this.columnDrag.dragData.ddel;
44764             delete this.columnDrag.dragData.header;
44765             this.columnDrag.destroy();
44766             delete Ext.dd.DDM.locationCache[this.columnDrag.id];
44767             delete this.columnDrag._domRef;
44768
44769             delete this.columnDrop.proxyTop;
44770             delete this.columnDrop.proxyBottom;
44771             this.columnDrop.destroy();
44772             delete Ext.dd.DDM.locationCache["gridHeader" + this.grid.getGridEl().id];
44773             delete this.columnDrop._domRef;
44774             delete Ext.dd.DDM.ids[this.columnDrop.ddGroup];
44775         }
44776
44777         if (this.splitZone){ 
44778             this.splitZone.destroy();
44779             delete this.splitZone._domRef;
44780             delete Ext.dd.DDM.ids["gridSplitters" + this.grid.getGridEl().id];
44781         }
44782
44783         Ext.fly(this.innerHd).removeAllListeners();
44784         Ext.removeNode(this.innerHd);
44785         delete this.innerHd;
44786
44787         Ext.destroy(
44788             this.el,
44789             this.mainWrap,
44790             this.mainHd,
44791             this.scroller,
44792             this.mainBody,
44793             this.focusEl,
44794             this.resizeMarker,
44795             this.resizeProxy,
44796             this.activeHdBtn,
44797             this.dragZone,
44798             this.splitZone,
44799             this._flyweight
44800         );
44801
44802         delete this.grid.container;
44803
44804         if(this.dragZone){
44805             this.dragZone.destroy();
44806         }
44807
44808         Ext.dd.DDM.currentTarget = null;
44809         delete Ext.dd.DDM.locationCache[this.grid.getGridEl().id];
44810
44811         Ext.EventManager.removeResizeListener(this.onWindowResize, this);
44812     },
44813
44814     
44815     onDenyColumnHide : function(){
44816
44817     },
44818
44819     
44820     render : function(){
44821         if(this.autoFill){
44822             var ct = this.grid.ownerCt;
44823             if (ct && ct.getLayout()){
44824                 ct.on('afterlayout', function(){
44825                     this.fitColumns(true, true);
44826                     this.updateHeaders();
44827                 }, this, {single: true});
44828             }else{
44829                 this.fitColumns(true, true);
44830             }
44831         }else if(this.forceFit){
44832             this.fitColumns(true, false);
44833         }else if(this.grid.autoExpandColumn){
44834             this.autoExpand(true);
44835         }
44836
44837         this.renderUI();
44838     },
44839
44840     
44841     
44842     initData : function(ds, cm){
44843         if(this.ds){
44844             this.ds.un('load', this.onLoad, this);
44845             this.ds.un('datachanged', this.onDataChange, this);
44846             this.ds.un('add', this.onAdd, this);
44847             this.ds.un('remove', this.onRemove, this);
44848             this.ds.un('update', this.onUpdate, this);
44849             this.ds.un('clear', this.onClear, this);
44850             if(this.ds !== ds && this.ds.autoDestroy){
44851                 this.ds.destroy();
44852             }
44853         }
44854         if(ds){
44855             ds.on({
44856                 scope: this,
44857                 load: this.onLoad,
44858                 datachanged: this.onDataChange,
44859                 add: this.onAdd,
44860                 remove: this.onRemove,
44861                 update: this.onUpdate,
44862                 clear: this.onClear
44863             });
44864         }
44865         this.ds = ds;
44866
44867         if(this.cm){
44868             this.cm.un('configchange', this.onColConfigChange, this);
44869             this.cm.un('widthchange', this.onColWidthChange, this);
44870             this.cm.un('headerchange', this.onHeaderChange, this);
44871             this.cm.un('hiddenchange', this.onHiddenChange, this);
44872             this.cm.un('columnmoved', this.onColumnMove, this);
44873         }
44874         if(cm){
44875             delete this.lastViewWidth;
44876             cm.on({
44877                 scope: this,
44878                 configchange: this.onColConfigChange,
44879                 widthchange: this.onColWidthChange,
44880                 headerchange: this.onHeaderChange,
44881                 hiddenchange: this.onHiddenChange,
44882                 columnmoved: this.onColumnMove
44883             });
44884         }
44885         this.cm = cm;
44886     },
44887
44888     
44889     onDataChange : function(){
44890         this.refresh();
44891         this.updateHeaderSortState();
44892         this.syncFocusEl(0);
44893     },
44894
44895     
44896     onClear : function(){
44897         this.refresh();
44898         this.syncFocusEl(0);
44899     },
44900
44901     
44902     onUpdate : function(ds, record){
44903         this.refreshRow(record);
44904     },
44905
44906     
44907     onAdd : function(ds, records, index){
44908         this.insertRows(ds, index, index + (records.length-1));
44909     },
44910
44911     
44912     onRemove : function(ds, record, index, isUpdate){
44913         if(isUpdate !== true){
44914             this.fireEvent('beforerowremoved', this, index, record);
44915         }
44916         this.removeRow(index);
44917         if(isUpdate !== true){
44918             this.processRows(index);
44919             this.applyEmptyText();
44920             this.fireEvent('rowremoved', this, index, record);
44921         }
44922     },
44923
44924     
44925     onLoad : function(){
44926         if (Ext.isGecko){
44927             if (!this.scrollToTopTask) {
44928                 this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
44929             }
44930             this.scrollToTopTask.delay(1);
44931         }else{
44932             this.scrollToTop();
44933         }
44934     },
44935
44936     
44937     onColWidthChange : function(cm, col, width){
44938         this.updateColumnWidth(col, width);
44939     },
44940
44941     
44942     onHeaderChange : function(cm, col, text){
44943         this.updateHeaders();
44944     },
44945
44946     
44947     onHiddenChange : function(cm, col, hidden){
44948         this.updateColumnHidden(col, hidden);
44949     },
44950
44951     
44952     onColumnMove : function(cm, oldIndex, newIndex){
44953         this.indexMap = null;
44954         var s = this.getScrollState();
44955         this.refresh(true);
44956         this.restoreScroll(s);
44957         this.afterMove(newIndex);
44958         this.grid.fireEvent('columnmove', oldIndex, newIndex);
44959     },
44960
44961     
44962     onColConfigChange : function(){
44963         delete this.lastViewWidth;
44964         this.indexMap = null;
44965         this.refresh(true);
44966     },
44967
44968     
44969     
44970     initUI : function(grid){
44971         grid.on('headerclick', this.onHeaderClick, this);
44972     },
44973
44974     
44975     initEvents : function(){
44976     },
44977
44978     
44979     onHeaderClick : function(g, index){
44980         if(this.headersDisabled || !this.cm.isSortable(index)){
44981             return;
44982         }
44983         g.stopEditing(true);
44984         g.store.sort(this.cm.getDataIndex(index));
44985     },
44986
44987     
44988     onRowOver : function(e, t){
44989         var row;
44990         if((row = this.findRowIndex(t)) !== false){
44991             this.addRowClass(row, 'x-grid3-row-over');
44992         }
44993     },
44994
44995     
44996     onRowOut : function(e, t){
44997         var row;
44998         if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
44999             this.removeRowClass(row, 'x-grid3-row-over');
45000         }
45001     },
45002
45003     
45004     handleWheel : function(e){
45005         e.stopPropagation();
45006     },
45007
45008     
45009     onRowSelect : function(row){
45010         this.addRowClass(row, this.selectedRowClass);
45011     },
45012
45013     
45014     onRowDeselect : function(row){
45015         this.removeRowClass(row, this.selectedRowClass);
45016     },
45017
45018     
45019     onCellSelect : function(row, col){
45020         var cell = this.getCell(row, col);
45021         if(cell){
45022             this.fly(cell).addClass('x-grid3-cell-selected');
45023         }
45024     },
45025
45026     
45027     onCellDeselect : function(row, col){
45028         var cell = this.getCell(row, col);
45029         if(cell){
45030             this.fly(cell).removeClass('x-grid3-cell-selected');
45031         }
45032     },
45033
45034     
45035     onColumnSplitterMoved : function(i, w){
45036         this.userResized = true;
45037         var cm = this.grid.colModel;
45038         cm.setColumnWidth(i, w, true);
45039
45040         if(this.forceFit){
45041             this.fitColumns(true, false, i);
45042             this.updateAllColumnWidths();
45043         }else{
45044             this.updateColumnWidth(i, w);
45045             this.syncHeaderScroll();
45046         }
45047
45048         this.grid.fireEvent('columnresize', i, w);
45049     },
45050
45051     
45052     handleHdMenuClick : function(item){
45053         var index = this.hdCtxIndex,
45054             cm = this.cm,
45055             ds = this.ds,
45056             id = item.getItemId();
45057         switch(id){
45058             case 'asc':
45059                 ds.sort(cm.getDataIndex(index), 'ASC');
45060                 break;
45061             case 'desc':
45062                 ds.sort(cm.getDataIndex(index), 'DESC');
45063                 break;
45064             default:
45065                 index = cm.getIndexById(id.substr(4));
45066                 if(index != -1){
45067                     if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
45068                         this.onDenyColumnHide();
45069                         return false;
45070                     }
45071                     cm.setHidden(index, item.checked);
45072                 }
45073         }
45074         return true;
45075     },
45076
45077     
45078     isHideableColumn : function(c){
45079         return !c.hidden;
45080     },
45081
45082     
45083     beforeColMenuShow : function(){
45084         var cm = this.cm,  colCount = cm.getColumnCount();
45085         this.colMenu.removeAll();
45086         for(var i = 0; i < colCount; i++){
45087             if(cm.config[i].hideable !== false){
45088                 this.colMenu.add(new Ext.menu.CheckItem({
45089                     itemId: 'col-'+cm.getColumnId(i),
45090                     text: cm.getColumnHeader(i),
45091                     checked: !cm.isHidden(i),
45092                     hideOnClick:false,
45093                     disabled: cm.config[i].hideable === false
45094                 }));
45095             }
45096         }
45097     },
45098
45099     
45100     handleHdDown : function(e, t){
45101         if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
45102             e.stopEvent();
45103             var hd = this.findHeaderCell(t);
45104             Ext.fly(hd).addClass('x-grid3-hd-menu-open');
45105             var index = this.getCellIndex(hd);
45106             this.hdCtxIndex = index;
45107             var ms = this.hmenu.items, cm = this.cm;
45108             ms.get('asc').setDisabled(!cm.isSortable(index));
45109             ms.get('desc').setDisabled(!cm.isSortable(index));
45110             this.hmenu.on('hide', function(){
45111                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
45112             }, this, {single:true});
45113             this.hmenu.show(t, 'tl-bl?');
45114         }
45115     },
45116
45117     
45118     handleHdOver : function(e, t){
45119         var hd = this.findHeaderCell(t);
45120         if(hd && !this.headersDisabled){
45121             this.activeHdRef = t;
45122             this.activeHdIndex = this.getCellIndex(hd);
45123             var fly = this.fly(hd);
45124             this.activeHdRegion = fly.getRegion();
45125             if(!this.cm.isMenuDisabled(this.activeHdIndex)){
45126                 fly.addClass('x-grid3-hd-over');
45127                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
45128                 if(this.activeHdBtn){
45129                     this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
45130                 }
45131             }
45132         }
45133     },
45134
45135     
45136     handleHdMove : function(e, t){
45137         var hd = this.findHeaderCell(this.activeHdRef);
45138         if(hd && !this.headersDisabled){
45139             var hw = this.splitHandleWidth || 5,
45140                 r = this.activeHdRegion,
45141                 x = e.getPageX(),
45142                 ss = hd.style,
45143                 cur = '';
45144             if(this.grid.enableColumnResize !== false){
45145                 if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
45146                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
45147                 }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
45148                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
45149                 }
45150             }
45151             ss.cursor = cur;
45152         }
45153     },
45154
45155     
45156     handleHdOut : function(e, t){
45157         var hd = this.findHeaderCell(t);
45158         if(hd && (!Ext.isIE || !e.within(hd, true))){
45159             this.activeHdRef = null;
45160             this.fly(hd).removeClass('x-grid3-hd-over');
45161             hd.style.cursor = '';
45162         }
45163     },
45164
45165     
45166     hasRows : function(){
45167         var fc = this.mainBody.dom.firstChild;
45168         return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
45169     },
45170
45171     
45172     bind : function(d, c){
45173         this.initData(d, c);
45174     }
45175 });
45176
45177
45178
45179
45180 Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
45181     
45182     constructor: function(grid, hd){
45183         this.grid = grid;
45184         this.view = grid.getView();
45185         this.marker = this.view.resizeMarker;
45186         this.proxy = this.view.resizeProxy;
45187         Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
45188             'gridSplitters' + this.grid.getGridEl().id, {
45189             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
45190         });
45191         this.scroll = false;
45192         this.hw = this.view.splitHandleWidth || 5;
45193     },
45194
45195     b4StartDrag : function(x, y){
45196         this.dragHeadersDisabled = this.view.headersDisabled;
45197         this.view.headersDisabled = true;
45198         var h = this.view.mainWrap.getHeight();
45199         this.marker.setHeight(h);
45200         this.marker.show();
45201         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
45202         this.proxy.setHeight(h);
45203         var w = this.cm.getColumnWidth(this.cellIndex),
45204             minw = Math.max(w-this.grid.minColumnWidth, 0);
45205         this.resetConstraints();
45206         this.setXConstraint(minw, 1000);
45207         this.setYConstraint(0, 0);
45208         this.minX = x - minw;
45209         this.maxX = x + 1000;
45210         this.startPos = x;
45211         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
45212     },
45213
45214     allowHeaderDrag : function(e){
45215         return true;
45216     },
45217
45218     handleMouseDown : function(e){
45219         var t = this.view.findHeaderCell(e.getTarget());
45220         if(t && this.allowHeaderDrag(e)){
45221             var xy = this.view.fly(t).getXY(), 
45222                 x = xy[0], 
45223                 y = xy[1],
45224                 exy = e.getXY(), ex = exy[0],
45225                 w = t.offsetWidth, adjust = false;
45226                 
45227             if((ex - x) <= this.hw){
45228                 adjust = -1;
45229             }else if((x+w) - ex <= this.hw){
45230                 adjust = 0;
45231             }
45232             if(adjust !== false){
45233                 this.cm = this.grid.colModel;
45234                 var ci = this.view.getCellIndex(t);
45235                 if(adjust == -1){
45236                   if (ci + adjust < 0) {
45237                     return;
45238                   }
45239                     while(this.cm.isHidden(ci+adjust)){
45240                         --adjust;
45241                         if(ci+adjust < 0){
45242                             return;
45243                         }
45244                     }
45245                 }
45246                 this.cellIndex = ci+adjust;
45247                 this.split = t.dom;
45248                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
45249                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
45250                 }
45251             }else if(this.view.columnDrag){
45252                 this.view.columnDrag.callHandleMouseDown(e);
45253             }
45254         }
45255     },
45256
45257     endDrag : function(e){
45258         this.marker.hide();
45259         var v = this.view,
45260             endX = Math.max(this.minX, e.getPageX()),
45261             diff = endX - this.startPos,
45262             disabled = this.dragHeadersDisabled;
45263             
45264         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
45265         setTimeout(function(){
45266             v.headersDisabled = disabled;
45267         }, 50);
45268     },
45269
45270     autoOffset : function(){
45271         this.setDelta(0,0);
45272     }
45273 });
45274
45275
45276 Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
45277     maxDragWidth: 120,
45278     
45279     constructor : function(grid, hd, hd2){
45280         this.grid = grid;
45281         this.view = grid.getView();
45282         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
45283         Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
45284         if(hd2){
45285             this.setHandleElId(Ext.id(hd));
45286             this.setOuterHandleElId(Ext.id(hd2));
45287         }
45288         this.scroll = false;
45289     },
45290     
45291     getDragData : function(e){
45292         var t = Ext.lib.Event.getTarget(e),
45293             h = this.view.findHeaderCell(t);
45294         if(h){
45295             return {ddel: h.firstChild, header:h};
45296         }
45297         return false;
45298     },
45299
45300     onInitDrag : function(e){
45301         
45302         this.dragHeadersDisabled = this.view.headersDisabled;
45303         this.view.headersDisabled = true;
45304         var clone = this.dragData.ddel.cloneNode(true);
45305         clone.id = Ext.id();
45306         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
45307         this.proxy.update(clone);
45308         return true;
45309     },
45310
45311     afterValidDrop : function(){
45312         this.completeDrop();
45313     },
45314
45315     afterInvalidDrop : function(){
45316         this.completeDrop();
45317     },
45318     
45319     completeDrop: function(){
45320         var v = this.view,
45321             disabled = this.dragHeadersDisabled;
45322         setTimeout(function(){
45323             v.headersDisabled = disabled;
45324         }, 50);
45325     }
45326 });
45327
45328
45329
45330 Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
45331     proxyOffsets : [-4, -9],
45332     fly: Ext.Element.fly,
45333     
45334     constructor : function(grid, hd, hd2){
45335         this.grid = grid;
45336         this.view = grid.getView();
45337         
45338         this.proxyTop = Ext.DomHelper.append(document.body, {
45339             cls:"col-move-top", html:"&#160;"
45340         }, true);
45341         this.proxyBottom = Ext.DomHelper.append(document.body, {
45342             cls:"col-move-bottom", html:"&#160;"
45343         }, true);
45344         this.proxyTop.hide = this.proxyBottom.hide = function(){
45345             this.setLeftTop(-100,-100);
45346             this.setStyle("visibility", "hidden");
45347         };
45348         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
45349         
45350         
45351         Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
45352     },
45353
45354     getTargetFromEvent : function(e){
45355         var t = Ext.lib.Event.getTarget(e),
45356             cindex = this.view.findCellIndex(t);
45357         if(cindex !== false){
45358             return this.view.getHeaderCell(cindex);
45359         }
45360     },
45361
45362     nextVisible : function(h){
45363         var v = this.view, cm = this.grid.colModel;
45364         h = h.nextSibling;
45365         while(h){
45366             if(!cm.isHidden(v.getCellIndex(h))){
45367                 return h;
45368             }
45369             h = h.nextSibling;
45370         }
45371         return null;
45372     },
45373
45374     prevVisible : function(h){
45375         var v = this.view, cm = this.grid.colModel;
45376         h = h.prevSibling;
45377         while(h){
45378             if(!cm.isHidden(v.getCellIndex(h))){
45379                 return h;
45380             }
45381             h = h.prevSibling;
45382         }
45383         return null;
45384     },
45385
45386     positionIndicator : function(h, n, e){
45387         var x = Ext.lib.Event.getPageX(e),
45388             r = Ext.lib.Dom.getRegion(n.firstChild),
45389             px, 
45390             pt, 
45391             py = r.top + this.proxyOffsets[1];
45392         if((r.right - x) <= (r.right-r.left)/2){
45393             px = r.right+this.view.borderWidth;
45394             pt = "after";
45395         }else{
45396             px = r.left;
45397             pt = "before";
45398         }
45399
45400         if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
45401             return false;
45402         }
45403
45404         px +=  this.proxyOffsets[0];
45405         this.proxyTop.setLeftTop(px, py);
45406         this.proxyTop.show();
45407         if(!this.bottomOffset){
45408             this.bottomOffset = this.view.mainHd.getHeight();
45409         }
45410         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
45411         this.proxyBottom.show();
45412         return pt;
45413     },
45414
45415     onNodeEnter : function(n, dd, e, data){
45416         if(data.header != n){
45417             this.positionIndicator(data.header, n, e);
45418         }
45419     },
45420
45421     onNodeOver : function(n, dd, e, data){
45422         var result = false;
45423         if(data.header != n){
45424             result = this.positionIndicator(data.header, n, e);
45425         }
45426         if(!result){
45427             this.proxyTop.hide();
45428             this.proxyBottom.hide();
45429         }
45430         return result ? this.dropAllowed : this.dropNotAllowed;
45431     },
45432
45433     onNodeOut : function(n, dd, e, data){
45434         this.proxyTop.hide();
45435         this.proxyBottom.hide();
45436     },
45437
45438     onNodeDrop : function(n, dd, e, data){
45439         var h = data.header;
45440         if(h != n){
45441             var cm = this.grid.colModel,
45442                 x = Ext.lib.Event.getPageX(e),
45443                 r = Ext.lib.Dom.getRegion(n.firstChild),
45444                 pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
45445                 oldIndex = this.view.getCellIndex(h),
45446                 newIndex = this.view.getCellIndex(n);
45447             if(pt == "after"){
45448                 newIndex++;
45449             }
45450             if(oldIndex < newIndex){
45451                 newIndex--;
45452             }
45453             cm.moveColumn(oldIndex, newIndex);
45454             return true;
45455         }
45456         return false;
45457     }
45458 });
45459
45460 Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
45461     
45462     constructor : function(grid, hd){
45463         Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
45464         this.proxy.el.addClass('x-grid3-col-dd');
45465     },
45466     
45467     handleMouseDown : function(e){
45468     },
45469
45470     callHandleMouseDown : function(e){
45471         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
45472     }
45473 });
45474
45475 Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
45476     fly: Ext.Element.fly,
45477     
45478     constructor : function(grid, hd, hd2){
45479         this.grid = grid;
45480         this.view = grid.getView();
45481         this.proxy = this.view.resizeProxy;
45482         Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
45483             "gridSplitters" + this.grid.getGridEl().id, {
45484             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
45485         });
45486         this.setHandleElId(Ext.id(hd));
45487         this.setOuterHandleElId(Ext.id(hd2));
45488         this.scroll = false;
45489     },
45490
45491     b4StartDrag : function(x, y){
45492         this.view.headersDisabled = true;
45493         this.proxy.setHeight(this.view.mainWrap.getHeight());
45494         var w = this.cm.getColumnWidth(this.cellIndex);
45495         var minw = Math.max(w-this.grid.minColumnWidth, 0);
45496         this.resetConstraints();
45497         this.setXConstraint(minw, 1000);
45498         this.setYConstraint(0, 0);
45499         this.minX = x - minw;
45500         this.maxX = x + 1000;
45501         this.startPos = x;
45502         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
45503     },
45504
45505
45506     handleMouseDown : function(e){
45507         var ev = Ext.EventObject.setEvent(e);
45508         var t = this.fly(ev.getTarget());
45509         if(t.hasClass("x-grid-split")){
45510             this.cellIndex = this.view.getCellIndex(t.dom);
45511             this.split = t.dom;
45512             this.cm = this.grid.colModel;
45513             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
45514                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
45515             }
45516         }
45517     },
45518
45519     endDrag : function(e){
45520         this.view.headersDisabled = false;
45521         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
45522         var diff = endX - this.startPos;
45523         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
45524     },
45525
45526     autoOffset : function(){
45527         this.setDelta(0,0);
45528     }
45529 });
45530 Ext.grid.GridDragZone = function(grid, config){
45531     this.view = grid.getView();
45532     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
45533     this.scroll = false;
45534     this.grid = grid;
45535     this.ddel = document.createElement('div');
45536     this.ddel.className = 'x-grid-dd-wrap';
45537 };
45538
45539 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
45540     ddGroup : "GridDD",
45541
45542     
45543     getDragData : function(e){
45544         var t = Ext.lib.Event.getTarget(e);
45545         var rowIndex = this.view.findRowIndex(t);
45546         if(rowIndex !== false){
45547             var sm = this.grid.selModel;
45548             if(!sm.isSelected(rowIndex) || e.hasModifier()){
45549                 sm.handleMouseDown(this.grid, rowIndex, e);
45550             }
45551             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
45552         }
45553         return false;
45554     },
45555
45556     
45557     onInitDrag : function(e){
45558         var data = this.dragData;
45559         this.ddel.innerHTML = this.grid.getDragDropText();
45560         this.proxy.update(this.ddel);
45561         
45562     },
45563
45564     
45565     afterRepair : function(){
45566         this.dragging = false;
45567     },
45568
45569     
45570     getRepairXY : function(e, data){
45571         return false;
45572     },
45573
45574     onEndDrag : function(data, e){
45575         
45576     },
45577
45578     onValidDrop : function(dd, e, id){
45579         
45580         this.hideProxy();
45581     },
45582
45583     beforeInvalidDrop : function(e, id){
45584
45585     }
45586 });
45587
45588 Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
45589     
45590     defaultWidth: 100,
45591     
45592     defaultSortable: false,
45593     
45594     
45595
45596     constructor : function(config){
45597         
45598             if(config.columns){
45599                 Ext.apply(this, config);
45600                 this.setConfig(config.columns, true);
45601             }else{
45602                 this.setConfig(config, true);
45603             }
45604             this.addEvents(
45605                 
45606                 "widthchange",
45607                 
45608                 "headerchange",
45609                 
45610                 "hiddenchange",
45611                 
45612                 "columnmoved",
45613                 
45614                 "configchange"
45615             );
45616             Ext.grid.ColumnModel.superclass.constructor.call(this);
45617     },
45618
45619     
45620     getColumnId : function(index){
45621         return this.config[index].id;
45622     },
45623
45624     getColumnAt : function(index){
45625         return this.config[index];
45626     },
45627
45628     
45629     setConfig : function(config, initial){
45630         var i, c, len;
45631         if(!initial){ 
45632             delete this.totalWidth;
45633             for(i = 0, len = this.config.length; i < len; i++){
45634                 c = this.config[i];
45635                 if(c.setEditor){
45636                     
45637                     c.setEditor(null);
45638                 }
45639             }
45640         }
45641
45642         
45643         this.defaults = Ext.apply({
45644             width: this.defaultWidth,
45645             sortable: this.defaultSortable
45646         }, this.defaults);
45647
45648         this.config = config;
45649         this.lookup = {};
45650
45651         for(i = 0, len = config.length; i < len; i++){
45652             c = Ext.applyIf(config[i], this.defaults);
45653             
45654             if(Ext.isEmpty(c.id)){
45655                 c.id = i;
45656             }
45657             if(!c.isColumn){
45658                 var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
45659                 c = new Cls(c);
45660                 config[i] = c;
45661             }
45662             this.lookup[c.id] = c;
45663         }
45664         if(!initial){
45665             this.fireEvent('configchange', this);
45666         }
45667     },
45668
45669     
45670     getColumnById : function(id){
45671         return this.lookup[id];
45672     },
45673
45674     
45675     getIndexById : function(id){
45676         for(var i = 0, len = this.config.length; i < len; i++){
45677             if(this.config[i].id == id){
45678                 return i;
45679             }
45680         }
45681         return -1;
45682     },
45683
45684     
45685     moveColumn : function(oldIndex, newIndex){
45686         var c = this.config[oldIndex];
45687         this.config.splice(oldIndex, 1);
45688         this.config.splice(newIndex, 0, c);
45689         this.dataMap = null;
45690         this.fireEvent("columnmoved", this, oldIndex, newIndex);
45691     },
45692
45693     
45694     getColumnCount : function(visibleOnly){
45695         if(visibleOnly === true){
45696             var c = 0;
45697             for(var i = 0, len = this.config.length; i < len; i++){
45698                 if(!this.isHidden(i)){
45699                     c++;
45700                 }
45701             }
45702             return c;
45703         }
45704         return this.config.length;
45705     },
45706
45707     
45708     getColumnsBy : function(fn, scope){
45709         var r = [];
45710         for(var i = 0, len = this.config.length; i < len; i++){
45711             var c = this.config[i];
45712             if(fn.call(scope||this, c, i) === true){
45713                 r[r.length] = c;
45714             }
45715         }
45716         return r;
45717     },
45718
45719     
45720     isSortable : function(col){
45721         return !!this.config[col].sortable;
45722     },
45723
45724     
45725     isMenuDisabled : function(col){
45726         return !!this.config[col].menuDisabled;
45727     },
45728
45729     
45730     getRenderer : function(col){
45731         if(!this.config[col].renderer){
45732             return Ext.grid.ColumnModel.defaultRenderer;
45733         }
45734         return this.config[col].renderer;
45735     },
45736
45737     getRendererScope : function(col){
45738         return this.config[col].scope;
45739     },
45740
45741     
45742     setRenderer : function(col, fn){
45743         this.config[col].renderer = fn;
45744     },
45745
45746     
45747     getColumnWidth : function(col){
45748         return this.config[col].width;
45749     },
45750
45751     
45752     setColumnWidth : function(col, width, suppressEvent){
45753         this.config[col].width = width;
45754         this.totalWidth = null;
45755         if(!suppressEvent){
45756              this.fireEvent("widthchange", this, col, width);
45757         }
45758     },
45759
45760     
45761     getTotalWidth : function(includeHidden){
45762         if(!this.totalWidth){
45763             this.totalWidth = 0;
45764             for(var i = 0, len = this.config.length; i < len; i++){
45765                 if(includeHidden || !this.isHidden(i)){
45766                     this.totalWidth += this.getColumnWidth(i);
45767                 }
45768             }
45769         }
45770         return this.totalWidth;
45771     },
45772
45773     
45774     getColumnHeader : function(col){
45775         return this.config[col].header;
45776     },
45777
45778     
45779     setColumnHeader : function(col, header){
45780         this.config[col].header = header;
45781         this.fireEvent("headerchange", this, col, header);
45782     },
45783
45784     
45785     getColumnTooltip : function(col){
45786             return this.config[col].tooltip;
45787     },
45788     
45789     setColumnTooltip : function(col, tooltip){
45790             this.config[col].tooltip = tooltip;
45791     },
45792
45793     
45794     getDataIndex : function(col){
45795         return this.config[col].dataIndex;
45796     },
45797
45798     
45799     setDataIndex : function(col, dataIndex){
45800         this.config[col].dataIndex = dataIndex;
45801     },
45802
45803     
45804     findColumnIndex : function(dataIndex){
45805         var c = this.config;
45806         for(var i = 0, len = c.length; i < len; i++){
45807             if(c[i].dataIndex == dataIndex){
45808                 return i;
45809             }
45810         }
45811         return -1;
45812     },
45813
45814     
45815     isCellEditable : function(colIndex, rowIndex){
45816         var c = this.config[colIndex],
45817             ed = c.editable;
45818
45819         
45820         return !!(ed || (!Ext.isDefined(ed) && c.editor));
45821     },
45822
45823     
45824     getCellEditor : function(colIndex, rowIndex){
45825         return this.config[colIndex].getCellEditor(rowIndex);
45826     },
45827
45828     
45829     setEditable : function(col, editable){
45830         this.config[col].editable = editable;
45831     },
45832
45833     
45834     isHidden : function(colIndex){
45835         return !!this.config[colIndex].hidden; 
45836     },
45837
45838     
45839     isFixed : function(colIndex){
45840         return !!this.config[colIndex].fixed;
45841     },
45842
45843     
45844     isResizable : function(colIndex){
45845         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
45846     },
45847     
45848     setHidden : function(colIndex, hidden){
45849         var c = this.config[colIndex];
45850         if(c.hidden !== hidden){
45851             c.hidden = hidden;
45852             this.totalWidth = null;
45853             this.fireEvent("hiddenchange", this, colIndex, hidden);
45854         }
45855     },
45856
45857     
45858     setEditor : function(col, editor){
45859         this.config[col].setEditor(editor);
45860     },
45861
45862     
45863     destroy : function(){
45864         var c;
45865         for(var i = 0, len = this.config.length; i < len; i++){
45866             c = this.config[i];
45867             if(c.setEditor){
45868                 c.setEditor(null);
45869             }
45870         }
45871         this.purgeListeners();
45872     },
45873     
45874     
45875     setState : function(col, state){
45876         Ext.applyIf(this.config[col], state);
45877     }
45878 });
45879
45880
45881 Ext.grid.ColumnModel.defaultRenderer = function(value){
45882     if(typeof value == "string" && value.length < 1){
45883         return "&#160;";
45884     }
45885     return value;
45886 };
45887 Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
45888     
45889
45890     constructor : function(){
45891         this.locked = false;
45892         Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
45893     },
45894
45895     
45896     init : function(grid){
45897         this.grid = grid;
45898         if(this.lockOnInit){
45899             delete this.lockOnInit;
45900             this.locked = false;
45901             this.lock();
45902         }
45903         this.initEvents();
45904     },
45905
45906     
45907     lock : function(){
45908         if(!this.locked){
45909             this.locked = true;
45910             
45911             var g = this.grid;
45912             if(g){
45913                 g.getView().on({
45914                     scope: this,
45915                     beforerefresh: this.sortUnLock,
45916                     refresh: this.sortLock
45917                 });
45918             }else{
45919                 this.lockOnInit = true;
45920             }
45921         }
45922     },
45923
45924     
45925     sortLock : function() {
45926         this.locked = true;
45927     },
45928
45929     
45930     sortUnLock : function() {
45931         this.locked = false;
45932     },
45933
45934     
45935     unlock : function(){
45936         if(this.locked){
45937             this.locked = false;
45938             var g = this.grid,
45939                 gv;
45940                 
45941             
45942             if(g){
45943                 gv = g.getView();
45944                 gv.un('beforerefresh', this.sortUnLock, this);
45945                 gv.un('refresh', this.sortLock, this);    
45946             }else{
45947                 delete this.lockOnInit;
45948             }
45949         }
45950     },
45951
45952     
45953     isLocked : function(){
45954         return this.locked;
45955     },
45956
45957     destroy: function(){
45958         this.unlock();
45959         this.purgeListeners();
45960     }
45961 });
45962 Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
45963     
45964     singleSelect : false,
45965     
45966     constructor : function(config){
45967         Ext.apply(this, config);
45968         this.selections = new Ext.util.MixedCollection(false, function(o){
45969             return o.id;
45970         });
45971
45972         this.last = false;
45973         this.lastActive = false;
45974
45975         this.addEvents(
45976                 
45977                 'selectionchange',
45978                 
45979                 'beforerowselect',
45980                 
45981                 'rowselect',
45982                 
45983                 'rowdeselect'
45984         );
45985         Ext.grid.RowSelectionModel.superclass.constructor.call(this);
45986     },
45987
45988     
45989     
45990     initEvents : function(){
45991
45992         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
45993             this.grid.on('rowmousedown', this.handleMouseDown, this);
45994         }
45995
45996         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
45997             'up' : function(e){
45998                 if(!e.shiftKey || this.singleSelect){
45999                     this.selectPrevious(false);
46000                 }else if(this.last !== false && this.lastActive !== false){
46001                     var last = this.last;
46002                     this.selectRange(this.last,  this.lastActive-1);
46003                     this.grid.getView().focusRow(this.lastActive);
46004                     if(last !== false){
46005                         this.last = last;
46006                     }
46007                 }else{
46008                     this.selectFirstRow();
46009                 }
46010             },
46011             'down' : function(e){
46012                 if(!e.shiftKey || this.singleSelect){
46013                     this.selectNext(false);
46014                 }else if(this.last !== false && this.lastActive !== false){
46015                     var last = this.last;
46016                     this.selectRange(this.last,  this.lastActive+1);
46017                     this.grid.getView().focusRow(this.lastActive);
46018                     if(last !== false){
46019                         this.last = last;
46020                     }
46021                 }else{
46022                     this.selectFirstRow();
46023                 }
46024             },
46025             scope: this
46026         });
46027
46028         this.grid.getView().on({
46029             scope: this,
46030             refresh: this.onRefresh,
46031             rowupdated: this.onRowUpdated,
46032             rowremoved: this.onRemove
46033         });
46034     },
46035
46036     
46037     onRefresh : function(){
46038         var ds = this.grid.store, index;
46039         var s = this.getSelections();
46040         this.clearSelections(true);
46041         for(var i = 0, len = s.length; i < len; i++){
46042             var r = s[i];
46043             if((index = ds.indexOfId(r.id)) != -1){
46044                 this.selectRow(index, true);
46045             }
46046         }
46047         if(s.length != this.selections.getCount()){
46048             this.fireEvent('selectionchange', this);
46049         }
46050     },
46051
46052     
46053     onRemove : function(v, index, r){
46054         if(this.selections.remove(r) !== false){
46055             this.fireEvent('selectionchange', this);
46056         }
46057     },
46058
46059     
46060     onRowUpdated : function(v, index, r){
46061         if(this.isSelected(r)){
46062             v.onRowSelect(index);
46063         }
46064     },
46065
46066     
46067     selectRecords : function(records, keepExisting){
46068         if(!keepExisting){
46069             this.clearSelections();
46070         }
46071         var ds = this.grid.store;
46072         for(var i = 0, len = records.length; i < len; i++){
46073             this.selectRow(ds.indexOf(records[i]), true);
46074         }
46075     },
46076
46077     
46078     getCount : function(){
46079         return this.selections.length;
46080     },
46081
46082     
46083     selectFirstRow : function(){
46084         this.selectRow(0);
46085     },
46086
46087     
46088     selectLastRow : function(keepExisting){
46089         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
46090     },
46091
46092     
46093     selectNext : function(keepExisting){
46094         if(this.hasNext()){
46095             this.selectRow(this.last+1, keepExisting);
46096             this.grid.getView().focusRow(this.last);
46097             return true;
46098         }
46099         return false;
46100     },
46101
46102     
46103     selectPrevious : function(keepExisting){
46104         if(this.hasPrevious()){
46105             this.selectRow(this.last-1, keepExisting);
46106             this.grid.getView().focusRow(this.last);
46107             return true;
46108         }
46109         return false;
46110     },
46111
46112     
46113     hasNext : function(){
46114         return this.last !== false && (this.last+1) < this.grid.store.getCount();
46115     },
46116
46117     
46118     hasPrevious : function(){
46119         return !!this.last;
46120     },
46121
46122
46123     
46124     getSelections : function(){
46125         return [].concat(this.selections.items);
46126     },
46127
46128     
46129     getSelected : function(){
46130         return this.selections.itemAt(0);
46131     },
46132
46133     
46134     each : function(fn, scope){
46135         var s = this.getSelections();
46136         for(var i = 0, len = s.length; i < len; i++){
46137             if(fn.call(scope || this, s[i], i) === false){
46138                 return false;
46139             }
46140         }
46141         return true;
46142     },
46143
46144     
46145     clearSelections : function(fast){
46146         if(this.isLocked()){
46147             return;
46148         }
46149         if(fast !== true){
46150             var ds = this.grid.store;
46151             var s = this.selections;
46152             s.each(function(r){
46153                 this.deselectRow(ds.indexOfId(r.id));
46154             }, this);
46155             s.clear();
46156         }else{
46157             this.selections.clear();
46158         }
46159         this.last = false;
46160     },
46161
46162
46163     
46164     selectAll : function(){
46165         if(this.isLocked()){
46166             return;
46167         }
46168         this.selections.clear();
46169         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
46170             this.selectRow(i, true);
46171         }
46172     },
46173
46174     
46175     hasSelection : function(){
46176         return this.selections.length > 0;
46177     },
46178
46179     
46180     isSelected : function(index){
46181         var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
46182         return (r && this.selections.key(r.id) ? true : false);
46183     },
46184
46185     
46186     isIdSelected : function(id){
46187         return (this.selections.key(id) ? true : false);
46188     },
46189
46190     
46191     handleMouseDown : function(g, rowIndex, e){
46192         if(e.button !== 0 || this.isLocked()){
46193             return;
46194         }
46195         var view = this.grid.getView();
46196         if(e.shiftKey && !this.singleSelect && this.last !== false){
46197             var last = this.last;
46198             this.selectRange(last, rowIndex, e.ctrlKey);
46199             this.last = last; 
46200             view.focusRow(rowIndex);
46201         }else{
46202             var isSelected = this.isSelected(rowIndex);
46203             if(e.ctrlKey && isSelected){
46204                 this.deselectRow(rowIndex);
46205             }else if(!isSelected || this.getCount() > 1){
46206                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
46207                 view.focusRow(rowIndex);
46208             }
46209         }
46210     },
46211
46212     
46213     selectRows : function(rows, keepExisting){
46214         if(!keepExisting){
46215             this.clearSelections();
46216         }
46217         for(var i = 0, len = rows.length; i < len; i++){
46218             this.selectRow(rows[i], true);
46219         }
46220     },
46221
46222     
46223     selectRange : function(startRow, endRow, keepExisting){
46224         var i;
46225         if(this.isLocked()){
46226             return;
46227         }
46228         if(!keepExisting){
46229             this.clearSelections();
46230         }
46231         if(startRow <= endRow){
46232             for(i = startRow; i <= endRow; i++){
46233                 this.selectRow(i, true);
46234             }
46235         }else{
46236             for(i = startRow; i >= endRow; i--){
46237                 this.selectRow(i, true);
46238             }
46239         }
46240     },
46241
46242     
46243     deselectRange : function(startRow, endRow, preventViewNotify){
46244         if(this.isLocked()){
46245             return;
46246         }
46247         for(var i = startRow; i <= endRow; i++){
46248             this.deselectRow(i, preventViewNotify);
46249         }
46250     },
46251
46252     
46253     selectRow : function(index, keepExisting, preventViewNotify){
46254         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
46255             return;
46256         }
46257         var r = this.grid.store.getAt(index);
46258         if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
46259             if(!keepExisting || this.singleSelect){
46260                 this.clearSelections();
46261             }
46262             this.selections.add(r);
46263             this.last = this.lastActive = index;
46264             if(!preventViewNotify){
46265                 this.grid.getView().onRowSelect(index);
46266             }
46267             this.fireEvent('rowselect', this, index, r);
46268             this.fireEvent('selectionchange', this);
46269         }
46270     },
46271
46272     
46273     deselectRow : function(index, preventViewNotify){
46274         if(this.isLocked()){
46275             return;
46276         }
46277         if(this.last == index){
46278             this.last = false;
46279         }
46280         if(this.lastActive == index){
46281             this.lastActive = false;
46282         }
46283         var r = this.grid.store.getAt(index);
46284         if(r){
46285             this.selections.remove(r);
46286             if(!preventViewNotify){
46287                 this.grid.getView().onRowDeselect(index);
46288             }
46289             this.fireEvent('rowdeselect', this, index, r);
46290             this.fireEvent('selectionchange', this);
46291         }
46292     },
46293
46294     
46295     restoreLast : function(){
46296         if(this._last){
46297             this.last = this._last;
46298         }
46299     },
46300
46301     
46302     acceptsNav : function(row, col, cm){
46303         return !cm.isHidden(col) && cm.isCellEditable(col, row);
46304     },
46305
46306     
46307     onEditorKey : function(field, e){
46308         var k = e.getKey(), 
46309             newCell, 
46310             g = this.grid, 
46311             last = g.lastEdit,
46312             ed = g.activeEditor,
46313             ae, last, r, c;
46314         var shift = e.shiftKey;
46315         if(k == e.TAB){
46316             e.stopEvent();
46317             ed.completeEdit();
46318             if(shift){
46319                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
46320             }else{
46321                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
46322             }
46323         }else if(k == e.ENTER){
46324             if(this.moveEditorOnEnter !== false){
46325                 if(shift){
46326                     newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
46327                 }else{
46328                     newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
46329                 }
46330             }
46331         }
46332         if(newCell){
46333             r = newCell[0];
46334             c = newCell[1];
46335
46336             if(last.row != r){
46337                 this.selectRow(r); 
46338             }
46339
46340             if(g.isEditor && g.editing){ 
46341                 ae = g.activeEditor;
46342                 if(ae && ae.field.triggerBlur){
46343                     
46344                     ae.field.triggerBlur();
46345                 }
46346             }
46347             g.startEditing(r, c);
46348         }
46349     },
46350     
46351     destroy : function(){
46352         if(this.rowNav){
46353             this.rowNav.disable();
46354             this.rowNav = null;
46355         }
46356         Ext.grid.RowSelectionModel.superclass.destroy.call(this);
46357     }
46358 });
46359 Ext.grid.Column = Ext.extend(Object, {
46360     
46361     
46362     
46363     
46364     
46365     
46366     
46367     
46368     
46369     
46370     
46371     
46372     
46373     
46374     
46375     
46376     
46377     
46378     
46379     
46380     
46381     
46382
46383     
46384     isColumn : true,
46385
46386     constructor : function(config){
46387         Ext.apply(this, config);
46388
46389         if(Ext.isString(this.renderer)){
46390             this.renderer = Ext.util.Format[this.renderer];
46391         }else if(Ext.isObject(this.renderer)){
46392             this.scope = this.renderer.scope;
46393             this.renderer = this.renderer.fn;
46394         }
46395         if(!this.scope){
46396             this.scope = this;
46397         }
46398
46399         var ed = this.editor;
46400         delete this.editor;
46401         this.setEditor(ed);
46402     },
46403
46404     
46405     renderer : function(value){
46406         if(Ext.isString(value) && value.length < 1){
46407             return '&#160;';
46408         }
46409         return value;
46410     },
46411
46412     
46413     getEditor: function(rowIndex){
46414         return this.editable !== false ? this.editor : null;
46415     },
46416
46417     
46418     setEditor : function(editor){
46419         var ed = this.editor;
46420         if(ed){
46421             if(ed.gridEditor){
46422                 ed.gridEditor.destroy();
46423                 delete ed.gridEditor;
46424             }else{
46425                 ed.destroy();
46426             }
46427         }
46428         this.editor = null;
46429         if(editor){
46430             
46431             if(!editor.isXType){
46432                 editor = Ext.create(editor, 'textfield');
46433             }
46434             this.editor = editor;
46435         }
46436     },
46437
46438     
46439     getCellEditor: function(rowIndex){
46440         var ed = this.getEditor(rowIndex);
46441         if(ed){
46442             if(!ed.startEdit){
46443                 if(!ed.gridEditor){
46444                     ed.gridEditor = new Ext.grid.GridEditor(ed);
46445                 }
46446                 ed = ed.gridEditor;
46447             }
46448         }
46449         return ed;
46450     }
46451 });
46452
46453
46454 Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
46455     
46456     trueText: 'true',
46457     
46458     falseText: 'false',
46459     
46460     undefinedText: '&#160;',
46461
46462     constructor: function(cfg){
46463         Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
46464         var t = this.trueText, f = this.falseText, u = this.undefinedText;
46465         this.renderer = function(v){
46466             if(v === undefined){
46467                 return u;
46468             }
46469             if(!v || v === 'false'){
46470                 return f;
46471             }
46472             return t;
46473         };
46474     }
46475 });
46476
46477
46478 Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
46479     
46480     format : '0,000.00',
46481     constructor: function(cfg){
46482         Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
46483         this.renderer = Ext.util.Format.numberRenderer(this.format);
46484     }
46485 });
46486
46487
46488 Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
46489     
46490     format : 'm/d/Y',
46491     constructor: function(cfg){
46492         Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
46493         this.renderer = Ext.util.Format.dateRenderer(this.format);
46494     }
46495 });
46496
46497
46498 Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
46499     
46500     constructor: function(cfg){
46501         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
46502         var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
46503         this.renderer = function(value, p, r){
46504             return tpl.apply(r.data);
46505         };
46506         this.tpl = tpl;
46507     }
46508 });
46509
46510
46511 Ext.grid.Column.types = {
46512     gridcolumn : Ext.grid.Column,
46513     booleancolumn: Ext.grid.BooleanColumn,
46514     numbercolumn: Ext.grid.NumberColumn,
46515     datecolumn: Ext.grid.DateColumn,
46516     templatecolumn: Ext.grid.TemplateColumn
46517 };
46518 Ext.grid.RowNumberer = Ext.extend(Object, {
46519     
46520     header: "",
46521     
46522     width: 23,
46523     
46524     sortable: false,
46525     
46526     constructor : function(config){
46527         Ext.apply(this, config);
46528         if(this.rowspan){
46529             this.renderer = this.renderer.createDelegate(this);
46530         }
46531     },
46532
46533     
46534     fixed:true,
46535     hideable: false,
46536     menuDisabled:true,
46537     dataIndex: '',
46538     id: 'numberer',
46539     rowspan: undefined,
46540
46541     
46542     renderer : function(v, p, record, rowIndex){
46543         if(this.rowspan){
46544             p.cellAttr = 'rowspan="'+this.rowspan+'"';
46545         }
46546         return rowIndex+1;
46547     }
46548 });
46549 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
46550
46551     
46552     
46553     header : '<div class="x-grid3-hd-checker">&#160;</div>',
46554     
46555     width : 20,
46556     
46557     sortable : false,
46558
46559     
46560     menuDisabled : true,
46561     fixed : true,
46562     hideable: false,
46563     dataIndex : '',
46564     id : 'checker',
46565
46566     constructor : function(){
46567         Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
46568
46569         if(this.checkOnly){
46570             this.handleMouseDown = Ext.emptyFn;
46571         }
46572     },
46573
46574     
46575     initEvents : function(){
46576         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
46577         this.grid.on('render', function(){
46578             var view = this.grid.getView();
46579             view.mainBody.on('mousedown', this.onMouseDown, this);
46580             Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
46581
46582         }, this);
46583     },
46584
46585     
46586     
46587     handleMouseDown : function() {
46588         Ext.grid.CheckboxSelectionModel.superclass.handleMouseDown.apply(this, arguments);
46589         this.mouseHandled = true;
46590     },
46591
46592     
46593     onMouseDown : function(e, t){
46594         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
46595             e.stopEvent();
46596             var row = e.getTarget('.x-grid3-row');
46597
46598             
46599             if(!this.mouseHandled && row){
46600                 var index = row.rowIndex;
46601                 if(this.isSelected(index)){
46602                     this.deselectRow(index);
46603                 }else{
46604                     this.selectRow(index, true);
46605                     this.grid.getView().focusRow(index);
46606                 }
46607             }
46608         }
46609         this.mouseHandled = false;
46610     },
46611
46612     
46613     onHdMouseDown : function(e, t){
46614         if(t.className == 'x-grid3-hd-checker'){
46615             e.stopEvent();
46616             var hd = Ext.fly(t.parentNode);
46617             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
46618             if(isChecked){
46619                 hd.removeClass('x-grid3-hd-checker-on');
46620                 this.clearSelections();
46621             }else{
46622                 hd.addClass('x-grid3-hd-checker-on');
46623                 this.selectAll();
46624             }
46625         }
46626     },
46627
46628     
46629     renderer : function(v, p, record){
46630         return '<div class="x-grid3-row-checker">&#160;</div>';
46631     }
46632 });
46633 Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
46634     
46635     constructor : function(config){
46636         Ext.apply(this, config);
46637
46638             this.selection = null;
46639         
46640             this.addEvents(
46641                 
46642                 "beforecellselect",
46643                 
46644                 "cellselect",
46645                 
46646                 "selectionchange"
46647             );
46648         
46649             Ext.grid.CellSelectionModel.superclass.constructor.call(this);
46650     },
46651
46652     
46653     initEvents : function(){
46654         this.grid.on('cellmousedown', this.handleMouseDown, this);
46655         this.grid.on(Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.handleKeyDown, this);
46656         this.grid.getView().on({
46657             scope: this,
46658             refresh: this.onViewChange,
46659             rowupdated: this.onRowUpdated,
46660             beforerowremoved: this.clearSelections,
46661             beforerowsinserted: this.clearSelections
46662         });
46663         if(this.grid.isEditor){
46664             this.grid.on('beforeedit', this.beforeEdit,  this);
46665         }
46666     },
46667
46668         
46669     beforeEdit : function(e){
46670         this.select(e.row, e.column, false, true, e.record);
46671     },
46672
46673         
46674     onRowUpdated : function(v, index, r){
46675         if(this.selection && this.selection.record == r){
46676             v.onCellSelect(index, this.selection.cell[1]);
46677         }
46678     },
46679
46680         
46681     onViewChange : function(){
46682         this.clearSelections(true);
46683     },
46684
46685         
46686     getSelectedCell : function(){
46687         return this.selection ? this.selection.cell : null;
46688     },
46689
46690     
46691     clearSelections : function(preventNotify){
46692         var s = this.selection;
46693         if(s){
46694             if(preventNotify !== true){
46695                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
46696             }
46697             this.selection = null;
46698             this.fireEvent("selectionchange", this, null);
46699         }
46700     },
46701
46702     
46703     hasSelection : function(){
46704         return this.selection ? true : false;
46705     },
46706
46707     
46708     handleMouseDown : function(g, row, cell, e){
46709         if(e.button !== 0 || this.isLocked()){
46710             return;
46711         }
46712         this.select(row, cell);
46713     },
46714
46715     
46716     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
46717         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
46718             this.clearSelections();
46719             r = r || this.grid.store.getAt(rowIndex);
46720             this.selection = {
46721                 record : r,
46722                 cell : [rowIndex, colIndex]
46723             };
46724             if(!preventViewNotify){
46725                 var v = this.grid.getView();
46726                 v.onCellSelect(rowIndex, colIndex);
46727                 if(preventFocus !== true){
46728                     v.focusCell(rowIndex, colIndex);
46729                 }
46730             }
46731             this.fireEvent("cellselect", this, rowIndex, colIndex);
46732             this.fireEvent("selectionchange", this, this.selection);
46733         }
46734     },
46735
46736         
46737     isSelectable : function(rowIndex, colIndex, cm){
46738         return !cm.isHidden(colIndex);
46739     },
46740     
46741     
46742     onEditorKey: function(field, e){
46743         if(e.getKey() == e.TAB){
46744             this.handleKeyDown(e);
46745         }
46746     },
46747
46748     
46749     handleKeyDown : function(e){
46750         if(!e.isNavKeyPress()){
46751             return;
46752         }
46753         
46754         var k = e.getKey(),
46755             g = this.grid,
46756             s = this.selection,
46757             sm = this,
46758             walk = function(row, col, step){
46759                 return g.walkCells(
46760                     row,
46761                     col,
46762                     step,
46763                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
46764                     sm
46765                 );
46766             },
46767             cell, newCell, r, c, ae;
46768
46769         switch(k){
46770             case e.ESC:
46771             case e.PAGE_UP:
46772             case e.PAGE_DOWN:
46773                 
46774                 break;
46775             default:
46776                 
46777                 e.stopEvent();
46778                 break;
46779         }
46780
46781         if(!s){
46782             cell = walk(0, 0, 1); 
46783             if(cell){
46784                 this.select(cell[0], cell[1]);
46785             }
46786             return;
46787         }
46788
46789         cell = s.cell;  
46790         r = cell[0];    
46791         c = cell[1];    
46792         
46793         switch(k){
46794             case e.TAB:
46795                 if(e.shiftKey){
46796                     newCell = walk(r, c - 1, -1);
46797                 }else{
46798                     newCell = walk(r, c + 1, 1);
46799                 }
46800                 break;
46801             case e.DOWN:
46802                 newCell = walk(r + 1, c, 1);
46803                 break;
46804             case e.UP:
46805                 newCell = walk(r - 1, c, -1);
46806                 break;
46807             case e.RIGHT:
46808                 newCell = walk(r, c + 1, 1);
46809                 break;
46810             case e.LEFT:
46811                 newCell = walk(r, c - 1, -1);
46812                 break;
46813             case e.ENTER:
46814                 if (g.isEditor && !g.editing) {
46815                     g.startEditing(r, c);
46816                     return;
46817                 }
46818                 break;
46819         }
46820
46821         if(newCell){
46822             
46823             r = newCell[0];
46824             c = newCell[1];
46825
46826             this.select(r, c); 
46827
46828             if(g.isEditor && g.editing){ 
46829                 ae = g.activeEditor;
46830                 if(ae && ae.field.triggerBlur){
46831                     
46832                     ae.field.triggerBlur();
46833                 }
46834                 g.startEditing(r, c);
46835             }
46836         }
46837     },
46838
46839     acceptsNav : function(row, col, cm){
46840         return !cm.isHidden(col) && cm.isCellEditable(col, row);
46841     }
46842 });
46843 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
46844     
46845     clicksToEdit: 2,
46846
46847     
46848     forceValidation: false,
46849
46850     
46851     isEditor : true,
46852     
46853     detectEdit: false,
46854
46855     
46856     autoEncode : false,
46857
46858     
46859     
46860     trackMouseOver: false, 
46861
46862     
46863     initComponent : function(){
46864         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
46865
46866         if(!this.selModel){
46867             
46868             this.selModel = new Ext.grid.CellSelectionModel();
46869         }
46870
46871         this.activeEditor = null;
46872
46873         this.addEvents(
46874             
46875             "beforeedit",
46876             
46877             "afteredit",
46878             
46879             "validateedit"
46880         );
46881     },
46882
46883     
46884     initEvents : function(){
46885         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
46886
46887         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
46888         this.on('columnresize', this.stopEditing, this, [true]);
46889
46890         if(this.clicksToEdit == 1){
46891             this.on("cellclick", this.onCellDblClick, this);
46892         }else {
46893             var view = this.getView();
46894             if(this.clicksToEdit == 'auto' && view.mainBody){
46895                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
46896             }
46897             this.on('celldblclick', this.onCellDblClick, this);
46898         }
46899     },
46900
46901     onResize : function(){
46902         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
46903         var ae = this.activeEditor;
46904         if(this.editing && ae){
46905             ae.realign(true);
46906         }
46907     },
46908
46909     
46910     onCellDblClick : function(g, row, col){
46911         this.startEditing(row, col);
46912     },
46913
46914     
46915     onAutoEditClick : function(e, t){
46916         if(e.button !== 0){
46917             return;
46918         }
46919         var row = this.view.findRowIndex(t),
46920             col = this.view.findCellIndex(t);
46921         if(row !== false && col !== false){
46922             this.stopEditing();
46923             if(this.selModel.getSelectedCell){ 
46924                 var sc = this.selModel.getSelectedCell();
46925                 if(sc && sc[0] === row && sc[1] === col){
46926                     this.startEditing(row, col);
46927                 }
46928             }else{
46929                 if(this.selModel.isSelected(row)){
46930                     this.startEditing(row, col);
46931                 }
46932             }
46933         }
46934     },
46935
46936     
46937     onEditComplete : function(ed, value, startValue){
46938         this.editing = false;
46939         this.lastActiveEditor = this.activeEditor;
46940         this.activeEditor = null;
46941
46942         var r = ed.record,
46943             field = this.colModel.getDataIndex(ed.col);
46944         value = this.postEditValue(value, startValue, r, field);
46945         if(this.forceValidation === true || String(value) !== String(startValue)){
46946             var e = {
46947                 grid: this,
46948                 record: r,
46949                 field: field,
46950                 originalValue: startValue,
46951                 value: value,
46952                 row: ed.row,
46953                 column: ed.col,
46954                 cancel:false
46955             };
46956             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
46957                 r.set(field, e.value);
46958                 delete e.cancel;
46959                 this.fireEvent("afteredit", e);
46960             }
46961         }
46962         this.view.focusCell(ed.row, ed.col);
46963     },
46964
46965     
46966     startEditing : function(row, col){
46967         this.stopEditing();
46968         if(this.colModel.isCellEditable(col, row)){
46969             this.view.ensureVisible(row, col, true);
46970             var r = this.store.getAt(row),
46971                 field = this.colModel.getDataIndex(col),
46972                 e = {
46973                     grid: this,
46974                     record: r,
46975                     field: field,
46976                     value: r.data[field],
46977                     row: row,
46978                     column: col,
46979                     cancel:false
46980                 };
46981             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
46982                 this.editing = true;
46983                 var ed = this.colModel.getCellEditor(col, row);
46984                 if(!ed){
46985                     return;
46986                 }
46987                 if(!ed.rendered){
46988                     ed.parentEl = this.view.getEditorParent(ed);
46989                     ed.on({
46990                         scope: this,
46991                         render: {
46992                             fn: function(c){
46993                                 c.field.focus(false, true);
46994                             },
46995                             single: true,
46996                             scope: this
46997                         },
46998                         specialkey: function(field, e){
46999                             this.getSelectionModel().onEditorKey(field, e);
47000                         },
47001                         complete: this.onEditComplete,
47002                         canceledit: this.stopEditing.createDelegate(this, [true])
47003                     });
47004                 }
47005                 Ext.apply(ed, {
47006                     row     : row,
47007                     col     : col,
47008                     record  : r
47009                 });
47010                 this.lastEdit = {
47011                     row: row,
47012                     col: col
47013                 };
47014                 this.activeEditor = ed;
47015                 
47016                 
47017                 ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
47018                 var v = this.preEditValue(r, field);
47019                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
47020
47021                 
47022                 (function(){
47023                     delete ed.selectSameEditor;
47024                 }).defer(50);
47025             }
47026         }
47027     },
47028
47029     
47030     preEditValue : function(r, field){
47031         var value = r.data[field];
47032         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
47033     },
47034
47035     
47036     postEditValue : function(value, originalValue, r, field){
47037         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
47038     },
47039
47040     
47041     stopEditing : function(cancel){
47042         if(this.editing){
47043             
47044             var ae = this.lastActiveEditor = this.activeEditor;
47045             if(ae){
47046                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
47047                 this.view.focusCell(ae.row, ae.col);
47048             }
47049             this.activeEditor = null;
47050         }
47051         this.editing = false;
47052     }
47053 });
47054 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
47055
47056 Ext.grid.GridEditor = function(field, config){
47057     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
47058     field.monitorTab = false;
47059 };
47060
47061 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
47062     alignment: "tl-tl",
47063     autoSize: "width",
47064     hideEl : false,
47065     cls: "x-small-editor x-grid-editor",
47066     shim:false,
47067     shadow:false
47068 });
47069 Ext.grid.PropertyRecord = Ext.data.Record.create([
47070     {name:'name',type:'string'}, 'value'
47071 ]);
47072
47073
47074 Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
47075     
47076     constructor : function(grid, source){
47077         this.grid = grid;
47078         this.store = new Ext.data.Store({
47079             recordType : Ext.grid.PropertyRecord
47080         });
47081         this.store.on('update', this.onUpdate,  this);
47082         if(source){
47083             this.setSource(source);
47084         }
47085         Ext.grid.PropertyStore.superclass.constructor.call(this);    
47086     },
47087     
47088     
47089     setSource : function(o){
47090         this.source = o;
47091         this.store.removeAll();
47092         var data = [];
47093         for(var k in o){
47094             if(this.isEditableValue(o[k])){
47095                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
47096             }
47097         }
47098         this.store.loadRecords({records: data}, {}, true);
47099     },
47100
47101     
47102     onUpdate : function(ds, record, type){
47103         if(type == Ext.data.Record.EDIT){
47104             var v = record.data.value;
47105             var oldValue = record.modified.value;
47106             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
47107                 this.source[record.id] = v;
47108                 record.commit();
47109                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
47110             }else{
47111                 record.reject();
47112             }
47113         }
47114     },
47115
47116     
47117     getProperty : function(row){
47118        return this.store.getAt(row);
47119     },
47120
47121     
47122     isEditableValue: function(val){
47123         return Ext.isPrimitive(val) || Ext.isDate(val);
47124     },
47125
47126     
47127     setValue : function(prop, value, create){
47128         var r = this.getRec(prop);
47129         if(r){
47130             r.set('value', value);
47131             this.source[prop] = value;
47132         }else if(create){
47133             
47134             this.source[prop] = value;
47135             r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
47136             this.store.add(r);
47137
47138         }
47139     },
47140     
47141     
47142     remove : function(prop){
47143         var r = this.getRec(prop);
47144         if(r){
47145             this.store.remove(r);
47146             delete this.source[prop];
47147         }
47148     },
47149     
47150     
47151     getRec : function(prop){
47152         return this.store.getById(prop);
47153     },
47154
47155     
47156     getSource : function(){
47157         return this.source;
47158     }
47159 });
47160
47161
47162 Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
47163     
47164     nameText : 'Name',
47165     valueText : 'Value',
47166     dateFormat : 'm/j/Y',
47167     trueText: 'true',
47168     falseText: 'false',
47169     
47170     constructor : function(grid, store){
47171         var g = Ext.grid,
47172                 f = Ext.form;
47173                 
47174             this.grid = grid;
47175             g.PropertyColumnModel.superclass.constructor.call(this, [
47176                 {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
47177                 {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
47178             ]);
47179             this.store = store;
47180         
47181             var bfield = new f.Field({
47182                 autoCreate: {tag: 'select', children: [
47183                     {tag: 'option', value: 'true', html: this.trueText},
47184                     {tag: 'option', value: 'false', html: this.falseText}
47185                 ]},
47186                 getValue : function(){
47187                     return this.el.dom.value == 'true';
47188                 }
47189             });
47190             this.editors = {
47191                 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
47192                 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
47193                 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
47194                 'boolean' : new g.GridEditor(bfield, {
47195                     autoSize: 'both'
47196                 })
47197             };
47198             this.renderCellDelegate = this.renderCell.createDelegate(this);
47199             this.renderPropDelegate = this.renderProp.createDelegate(this);
47200     },
47201
47202     
47203     renderDate : function(dateVal){
47204         return dateVal.dateFormat(this.dateFormat);
47205     },
47206
47207     
47208     renderBool : function(bVal){
47209         return this[bVal ? 'trueText' : 'falseText'];
47210     },
47211
47212     
47213     isCellEditable : function(colIndex, rowIndex){
47214         return colIndex == 1;
47215     },
47216
47217     
47218     getRenderer : function(col){
47219         return col == 1 ?
47220             this.renderCellDelegate : this.renderPropDelegate;
47221     },
47222
47223     
47224     renderProp : function(v){
47225         return this.getPropertyName(v);
47226     },
47227
47228     
47229     renderCell : function(val, meta, rec){
47230         var renderer = this.grid.customRenderers[rec.get('name')];
47231         if(renderer){
47232             return renderer.apply(this, arguments);
47233         }
47234         var rv = val;
47235         if(Ext.isDate(val)){
47236             rv = this.renderDate(val);
47237         }else if(typeof val == 'boolean'){
47238             rv = this.renderBool(val);
47239         }
47240         return Ext.util.Format.htmlEncode(rv);
47241     },
47242
47243     
47244     getPropertyName : function(name){
47245         var pn = this.grid.propertyNames;
47246         return pn && pn[name] ? pn[name] : name;
47247     },
47248
47249     
47250     getCellEditor : function(colIndex, rowIndex){
47251         var p = this.store.getProperty(rowIndex),
47252             n = p.data.name, 
47253             val = p.data.value;
47254         if(this.grid.customEditors[n]){
47255             return this.grid.customEditors[n];
47256         }
47257         if(Ext.isDate(val)){
47258             return this.editors.date;
47259         }else if(typeof val == 'number'){
47260             return this.editors.number;
47261         }else if(typeof val == 'boolean'){
47262             return this.editors['boolean'];
47263         }else{
47264             return this.editors.string;
47265         }
47266     },
47267
47268     
47269     destroy : function(){
47270         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
47271         for(var ed in this.editors){
47272             Ext.destroy(this.editors[ed]);
47273         }
47274     }
47275 });
47276
47277
47278 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
47279     
47280     
47281     
47282     
47283     
47284
47285     
47286     enableColumnMove:false,
47287     stripeRows:false,
47288     trackMouseOver: false,
47289     clicksToEdit:1,
47290     enableHdMenu : false,
47291     viewConfig : {
47292         forceFit:true
47293     },
47294
47295     
47296     initComponent : function(){
47297         this.customRenderers = this.customRenderers || {};
47298         this.customEditors = this.customEditors || {};
47299         this.lastEditRow = null;
47300         var store = new Ext.grid.PropertyStore(this);
47301         this.propStore = store;
47302         var cm = new Ext.grid.PropertyColumnModel(this, store);
47303         store.store.sort('name', 'ASC');
47304         this.addEvents(
47305             
47306             'beforepropertychange',
47307             
47308             'propertychange'
47309         );
47310         this.cm = cm;
47311         this.ds = store.store;
47312         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
47313
47314                 this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
47315             if(colIndex === 0){
47316                 this.startEditing.defer(200, this, [rowIndex, 1]);
47317                 return false;
47318             }
47319         }, this);
47320     },
47321
47322     
47323     onRender : function(){
47324         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
47325
47326         this.getGridEl().addClass('x-props-grid');
47327     },
47328
47329     
47330     afterRender: function(){
47331         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
47332         if(this.source){
47333             this.setSource(this.source);
47334         }
47335     },
47336
47337     
47338     setSource : function(source){
47339         this.propStore.setSource(source);
47340     },
47341
47342     
47343     getSource : function(){
47344         return this.propStore.getSource();
47345     },
47346     
47347     
47348     setProperty : function(prop, value, create){
47349         this.propStore.setValue(prop, value, create);    
47350     },
47351     
47352     
47353     removeProperty : function(prop){
47354         this.propStore.remove(prop);
47355     }
47356
47357     
47358     
47359     
47360     
47361 });
47362 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
47363
47364 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
47365
47366     
47367     groupByText : 'Group By This Field',
47368     
47369     showGroupsText : 'Show in Groups',
47370     
47371     hideGroupedColumn : false,
47372     
47373     showGroupName : true,
47374     
47375     startCollapsed : false,
47376     
47377     enableGrouping : true,
47378     
47379     enableGroupingMenu : true,
47380     
47381     enableNoGroups : true,
47382     
47383     emptyGroupText : '(None)',
47384     
47385     ignoreAdd : false,
47386     
47387     groupTextTpl : '{text}',
47388
47389     
47390     groupMode: 'value',
47391
47392     
47393
47394     
47395     initTemplates : function(){
47396         Ext.grid.GroupingView.superclass.initTemplates.call(this);
47397         this.state = {};
47398
47399         var sm = this.grid.getSelectionModel();
47400         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
47401                 this.onBeforeRowSelect, this);
47402
47403         if(!this.startGroup){
47404             this.startGroup = new Ext.XTemplate(
47405                 '<div id="{groupId}" class="x-grid-group {cls}">',
47406                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
47407                     '<div id="{groupId}-bd" class="x-grid-group-body">'
47408             );
47409         }
47410         this.startGroup.compile();
47411
47412         if (!this.endGroup) {
47413             this.endGroup = '</div></div>';
47414         }
47415     },
47416
47417     
47418     findGroup : function(el){
47419         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
47420     },
47421
47422     
47423     getGroups : function(){
47424         return this.hasRows() ? this.mainBody.dom.childNodes : [];
47425     },
47426
47427     
47428     onAdd : function(ds, records, index) {
47429         if (this.canGroup() && !this.ignoreAdd) {
47430             var ss = this.getScrollState();
47431             this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
47432             this.refresh();
47433             this.restoreScroll(ss);
47434             this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
47435         } else if (!this.canGroup()) {
47436             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
47437         }
47438     },
47439
47440     
47441     onRemove : function(ds, record, index, isUpdate){
47442         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
47443         var g = document.getElementById(record._groupId);
47444         if(g && g.childNodes[1].childNodes.length < 1){
47445             Ext.removeNode(g);
47446         }
47447         this.applyEmptyText();
47448     },
47449
47450     
47451     refreshRow : function(record){
47452         if(this.ds.getCount()==1){
47453             this.refresh();
47454         }else{
47455             this.isUpdating = true;
47456             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
47457             this.isUpdating = false;
47458         }
47459     },
47460
47461     
47462     beforeMenuShow : function(){
47463         var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
47464         if((item = items.get('groupBy'))){
47465             item.setDisabled(disabled);
47466         }
47467         if((item = items.get('showGroups'))){
47468             item.setDisabled(disabled);
47469             item.setChecked(this.canGroup(), true);
47470         }
47471     },
47472
47473     
47474     renderUI : function(){
47475         Ext.grid.GroupingView.superclass.renderUI.call(this);
47476         this.mainBody.on('mousedown', this.interceptMouse, this);
47477
47478         if(this.enableGroupingMenu && this.hmenu){
47479             this.hmenu.add('-',{
47480                 itemId:'groupBy',
47481                 text: this.groupByText,
47482                 handler: this.onGroupByClick,
47483                 scope: this,
47484                 iconCls:'x-group-by-icon'
47485             });
47486             if(this.enableNoGroups){
47487                 this.hmenu.add({
47488                     itemId:'showGroups',
47489                     text: this.showGroupsText,
47490                     checked: true,
47491                     checkHandler: this.onShowGroupsClick,
47492                     scope: this
47493                 });
47494             }
47495             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
47496         }
47497     },
47498
47499     processEvent: function(name, e){
47500         Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
47501         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
47502         if(hd){
47503             
47504             var field = this.getGroupField(),
47505                 prefix = this.getPrefix(field),
47506                 groupValue = hd.id.substring(prefix.length),
47507                 emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
47508
47509             
47510             groupValue = groupValue.substr(0, groupValue.length - 3);
47511             
47512             
47513             if(groupValue || emptyRe.test(hd.id)){
47514                 this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
47515             }
47516             if(name == 'mousedown' && e.button == 0){
47517                 this.toggleGroup(hd.parentNode);
47518             }
47519         }
47520
47521     },
47522
47523     
47524     onGroupByClick : function(){
47525         this.enableGrouping = true;
47526         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
47527         this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());
47528         this.beforeMenuShow(); 
47529         this.refresh();
47530     },
47531
47532     
47533     onShowGroupsClick : function(mi, checked){
47534         this.enableGrouping = checked;
47535         if(checked){
47536             this.onGroupByClick();
47537         }else{
47538             this.grid.store.clearGrouping();
47539             this.grid.fireEvent('groupchange', this, null);
47540         }
47541     },
47542
47543     
47544     toggleRowIndex : function(rowIndex, expanded){
47545         if(!this.canGroup()){
47546             return;
47547         }
47548         var row = this.getRow(rowIndex);
47549         if(row){
47550             this.toggleGroup(this.findGroup(row), expanded);
47551         }
47552     },
47553
47554     
47555     toggleGroup : function(group, expanded){
47556         var gel = Ext.get(group);
47557         expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
47558         if(this.state[gel.id] !== expanded){
47559             this.grid.stopEditing(true);
47560             this.state[gel.id] = expanded;
47561             gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
47562         }
47563     },
47564
47565     
47566     toggleAllGroups : function(expanded){
47567         var groups = this.getGroups();
47568         for(var i = 0, len = groups.length; i < len; i++){
47569             this.toggleGroup(groups[i], expanded);
47570         }
47571     },
47572
47573     
47574     expandAllGroups : function(){
47575         this.toggleAllGroups(true);
47576     },
47577
47578     
47579     collapseAllGroups : function(){
47580         this.toggleAllGroups(false);
47581     },
47582
47583     
47584     interceptMouse : function(e){
47585         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
47586         if(hd){
47587             e.stopEvent();
47588             this.toggleGroup(hd.parentNode);
47589         }
47590     },
47591
47592     
47593     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
47594         var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
47595         if(g === '' || g === '&#160;'){
47596             g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
47597         }
47598         return g;
47599     },
47600
47601     
47602     getGroupField : function(){
47603         return this.grid.store.getGroupState();
47604     },
47605
47606     
47607     afterRender : function(){
47608         if(!this.ds || !this.cm){
47609             return;
47610         }
47611         Ext.grid.GroupingView.superclass.afterRender.call(this);
47612         if(this.grid.deferRowRender){
47613             this.updateGroupWidths();
47614         }
47615     },
47616
47617     
47618     renderRows : function(){
47619         var groupField = this.getGroupField();
47620         var eg = !!groupField;
47621         
47622         if(this.hideGroupedColumn) {
47623             var colIndex = this.cm.findColumnIndex(groupField),
47624                 hasLastGroupField = Ext.isDefined(this.lastGroupField);
47625             if(!eg && hasLastGroupField){
47626                 this.mainBody.update('');
47627                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
47628                 delete this.lastGroupField;
47629             }else if (eg && !hasLastGroupField){
47630                 this.lastGroupField = groupField;
47631                 this.cm.setHidden(colIndex, true);
47632             }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
47633                 this.mainBody.update('');
47634                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
47635                 this.cm.setHidden(oldIndex, false);
47636                 this.lastGroupField = groupField;
47637                 this.cm.setHidden(colIndex, true);
47638             }
47639         }
47640         return Ext.grid.GroupingView.superclass.renderRows.apply(
47641                     this, arguments);
47642     },
47643
47644     
47645     doRender : function(cs, rs, ds, startRow, colCount, stripe){
47646         if(rs.length < 1){
47647             return '';
47648         }
47649
47650         if(!this.canGroup() || this.isUpdating){
47651             return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
47652         }
47653
47654         var groupField = this.getGroupField(),
47655             colIndex = this.cm.findColumnIndex(groupField),
47656             g,
47657             gstyle = 'width:' + this.getTotalWidth() + ';',
47658             cfg = this.cm.config[colIndex],
47659             groupRenderer = cfg.groupRenderer || cfg.renderer,
47660             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
47661             groups = [],
47662             curGroup, i, len, gid;
47663
47664         for(i = 0, len = rs.length; i < len; i++){
47665             var rowIndex = startRow + i,
47666                 r = rs[i],
47667                 gvalue = r.data[groupField];
47668
47669                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
47670             if(!curGroup || curGroup.group != g){
47671                 gid = this.constructId(gvalue, groupField, colIndex);
47672                 
47673                 
47674                 this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
47675                 curGroup = {
47676                     group: g,
47677                     gvalue: gvalue,
47678                     text: prefix + g,
47679                     groupId: gid,
47680                     startRow: rowIndex,
47681                     rs: [r],
47682                     cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
47683                     style: gstyle
47684                 };
47685                 groups.push(curGroup);
47686             }else{
47687                 curGroup.rs.push(r);
47688             }
47689             r._groupId = gid;
47690         }
47691
47692         var buf = [];
47693         for(i = 0, len = groups.length; i < len; i++){
47694             g = groups[i];
47695             this.doGroupStart(buf, g, cs, ds, colCount);
47696             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
47697                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
47698
47699             this.doGroupEnd(buf, g, cs, ds, colCount);
47700         }
47701         return buf.join('');
47702     },
47703
47704     
47705     getGroupId : function(value){
47706         var field = this.getGroupField();
47707         return this.constructId(value, field, this.cm.findColumnIndex(field));
47708     },
47709
47710     
47711     constructId : function(value, field, idx){
47712         var cfg = this.cm.config[idx],
47713             groupRenderer = cfg.groupRenderer || cfg.renderer,
47714             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
47715
47716         return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
47717     },
47718
47719     
47720     canGroup  : function(){
47721         return this.enableGrouping && !!this.getGroupField();
47722     },
47723
47724     
47725     getPrefix: function(field){
47726         return this.grid.getGridEl().id + '-gp-' + field + '-';
47727     },
47728
47729     
47730     doGroupStart : function(buf, g, cs, ds, colCount){
47731         buf[buf.length] = this.startGroup.apply(g);
47732     },
47733
47734     
47735     doGroupEnd : function(buf, g, cs, ds, colCount){
47736         buf[buf.length] = this.endGroup;
47737     },
47738
47739     
47740     getRows : function(){
47741         if(!this.canGroup()){
47742             return Ext.grid.GroupingView.superclass.getRows.call(this);
47743         }
47744         var r = [],
47745             gs = this.getGroups(),
47746             g,
47747             i = 0,
47748             len = gs.length,
47749             j,
47750             jlen;
47751         for(; i < len; ++i){
47752             g = gs[i].childNodes[1];
47753             if(g){
47754                 g = g.childNodes;
47755                 for(j = 0, jlen = g.length; j < jlen; ++j){
47756                     r[r.length] = g[j];
47757                 }
47758             }
47759         }
47760         return r;
47761     },
47762
47763     
47764     updateGroupWidths : function(){
47765         if(!this.canGroup() || !this.hasRows()){
47766             return;
47767         }
47768         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
47769         var gs = this.getGroups();
47770         for(var i = 0, len = gs.length; i < len; i++){
47771             gs[i].firstChild.style.width = tw;
47772         }
47773     },
47774
47775     
47776     onColumnWidthUpdated : function(col, w, tw){
47777         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
47778         this.updateGroupWidths();
47779     },
47780
47781     
47782     onAllColumnWidthsUpdated : function(ws, tw){
47783         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
47784         this.updateGroupWidths();
47785     },
47786
47787     
47788     onColumnHiddenUpdated : function(col, hidden, tw){
47789         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
47790         this.updateGroupWidths();
47791     },
47792
47793     
47794     onLayout : function(){
47795         this.updateGroupWidths();
47796     },
47797
47798     
47799     onBeforeRowSelect : function(sm, rowIndex){
47800         this.toggleRowIndex(rowIndex, true);
47801     }
47802 });
47803
47804 Ext.grid.GroupingView.GROUP_ID = 1000;