commit extjs-2.2.1
[extjs.git] / ext-all-debug.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 \r
10 Ext.DomHelper = function(){\r
11     var tempTableEl = null;\r
12     var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;\r
13     var tableRe = /^table|tbody|tr|td$/i;\r
14 \r
15     // build as innerHTML where available\r
16     var createHtml = function(o){\r
17         if(typeof o == 'string'){\r
18             return o;\r
19         }\r
20         var b = "";\r
21         if (Ext.isArray(o)) {\r
22             for (var i = 0, l = o.length; i < l; i++) {\r
23                 b += createHtml(o[i]);\r
24             }\r
25             return b;\r
26         }\r
27         if(!o.tag){\r
28             o.tag = "div";\r
29         }\r
30         b += "<" + o.tag;\r
31         for(var attr in o){\r
32             if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;\r
33             if(attr == "style"){\r
34                 var s = o["style"];\r
35                 if(typeof s == "function"){\r
36                     s = s.call();\r
37                 }\r
38                 if(typeof s == "string"){\r
39                     b += ' style="' + s + '"';\r
40                 }else if(typeof s == "object"){\r
41                     b += ' style="';\r
42                     for(var key in s){\r
43                         if(typeof s[key] != "function"){\r
44                             b += key + ":" + s[key] + ";";\r
45                         }\r
46                     }\r
47                     b += '"';\r
48                 }\r
49             }else{\r
50                 if(attr == "cls"){\r
51                     b += ' class="' + o["cls"] + '"';\r
52                 }else if(attr == "htmlFor"){\r
53                     b += ' for="' + o["htmlFor"] + '"';\r
54                 }else{\r
55                     b += " " + attr + '="' + o[attr] + '"';\r
56                 }\r
57             }\r
58         }\r
59         if(emptyTags.test(o.tag)){\r
60             b += "/>";\r
61         }else{\r
62             b += ">";\r
63             var cn = o.children || o.cn;\r
64             if(cn){\r
65                 b += createHtml(cn);\r
66             } else if(o.html){\r
67                 b += o.html;\r
68             }\r
69             b += "</" + o.tag + ">";\r
70         }\r
71         return b;\r
72     };\r
73 \r
74     // build as dom\r
75     \r
76     var createDom = function(o, parentNode){\r
77         var el;\r
78         if (Ext.isArray(o)) {                       // Allow Arrays of siblings to be inserted\r
79             el = document.createDocumentFragment(); // in one shot using a DocumentFragment\r
80             for(var i = 0, l = o.length; i < l; i++) {\r
81                 createDom(o[i], el);\r
82             }\r
83         } else if (typeof o == "string") {         // Allow a string as a child spec.\r
84             el = document.createTextNode(o);\r
85         } else {\r
86             el = document.createElement(o.tag||'div');\r
87             var useSet = !!el.setAttribute; // In IE some elements don't have setAttribute\r
88             for(var attr in o){\r
89                 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;\r
90                 if(attr=="cls"){\r
91                     el.className = o["cls"];\r
92                 }else{\r
93                     if(useSet) el.setAttribute(attr, o[attr]);\r
94                     else el[attr] = o[attr];\r
95                 }\r
96             }\r
97             Ext.DomHelper.applyStyles(el, o.style);\r
98             var cn = o.children || o.cn;\r
99             if(cn){\r
100                 createDom(cn, el);\r
101             } else if(o.html){\r
102                 el.innerHTML = o.html;\r
103             }\r
104         }\r
105         if(parentNode){\r
106            parentNode.appendChild(el);\r
107         }\r
108         return el;\r
109     };\r
110 \r
111     var ieTable = function(depth, s, h, e){\r
112         tempTableEl.innerHTML = [s, h, e].join('');\r
113         var i = -1, el = tempTableEl;\r
114         while(++i < depth){\r
115             el = el.firstChild;\r
116         }\r
117         return el;\r
118     };\r
119 \r
120     // kill repeat to save bytes\r
121     var ts = '<table>',\r
122         te = '</table>',\r
123         tbs = ts+'<tbody>',\r
124         tbe = '</tbody>'+te,\r
125         trs = tbs + '<tr>',\r
126         tre = '</tr>'+tbe;\r
127 \r
128     \r
129     var insertIntoTable = function(tag, where, el, html){\r
130         if(!tempTableEl){\r
131             tempTableEl = document.createElement('div');\r
132         }\r
133         var node;\r
134         var before = null;\r
135         if(tag == 'td'){\r
136             if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD\r
137                 return;\r
138             }\r
139             if(where == 'beforebegin'){\r
140                 before = el;\r
141                 el = el.parentNode;\r
142             } else{\r
143                 before = el.nextSibling;\r
144                 el = el.parentNode;\r
145             }\r
146             node = ieTable(4, trs, html, tre);\r
147         }\r
148         else if(tag == 'tr'){\r
149             if(where == 'beforebegin'){\r
150                 before = el;\r
151                 el = el.parentNode;\r
152                 node = ieTable(3, tbs, html, tbe);\r
153             } else if(where == 'afterend'){\r
154                 before = el.nextSibling;\r
155                 el = el.parentNode;\r
156                 node = ieTable(3, tbs, html, tbe);\r
157             } else{ // INTO a TR\r
158                 if(where == 'afterbegin'){\r
159                     before = el.firstChild;\r
160                 }\r
161                 node = ieTable(4, trs, html, tre);\r
162             }\r
163         } else if(tag == 'tbody'){\r
164             if(where == 'beforebegin'){\r
165                 before = el;\r
166                 el = el.parentNode;\r
167                 node = ieTable(2, ts, html, te);\r
168             } else if(where == 'afterend'){\r
169                 before = el.nextSibling;\r
170                 el = el.parentNode;\r
171                 node = ieTable(2, ts, html, te);\r
172             } else{\r
173                 if(where == 'afterbegin'){\r
174                     before = el.firstChild;\r
175                 }\r
176                 node = ieTable(3, tbs, html, tbe);\r
177             }\r
178         } else{ // TABLE\r
179             if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table\r
180                 return;\r
181             }\r
182             if(where == 'afterbegin'){\r
183                 before = el.firstChild;\r
184             }\r
185             node = ieTable(2, ts, html, te);\r
186         }\r
187         el.insertBefore(node, before);\r
188         return node;\r
189     };\r
190 \r
191 \r
192     return {\r
193     \r
194     useDom : false,\r
195 \r
196     \r
197     markup : function(o){\r
198         return createHtml(o);\r
199     },\r
200 \r
201     \r
202     applyStyles : function(el, styles){\r
203         if(styles){\r
204            el = Ext.fly(el);\r
205            if(typeof styles == "string"){\r
206                var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;\r
207                var matches;\r
208                while ((matches = re.exec(styles)) != null){\r
209                    el.setStyle(matches[1], matches[2]);\r
210                }\r
211            }else if (typeof styles == "object"){\r
212                for (var style in styles){\r
213                   el.setStyle(style, styles[style]);\r
214                }\r
215            }else if (typeof styles == "function"){\r
216                 Ext.DomHelper.applyStyles(el, styles.call());\r
217            }\r
218         }\r
219     },\r
220 \r
221     \r
222     insertHtml : function(where, el, html){\r
223         where = where.toLowerCase();\r
224         if(el.insertAdjacentHTML){\r
225             if(tableRe.test(el.tagName)){\r
226                 var rs;\r
227                 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){\r
228                     return rs;\r
229                 }\r
230             }\r
231             switch(where){\r
232                 case "beforebegin":\r
233                     el.insertAdjacentHTML('BeforeBegin', html);\r
234                     return el.previousSibling;\r
235                 case "afterbegin":\r
236                     el.insertAdjacentHTML('AfterBegin', html);\r
237                     return el.firstChild;\r
238                 case "beforeend":\r
239                     el.insertAdjacentHTML('BeforeEnd', html);\r
240                     return el.lastChild;\r
241                 case "afterend":\r
242                     el.insertAdjacentHTML('AfterEnd', html);\r
243                     return el.nextSibling;\r
244             }\r
245             throw 'Illegal insertion point -> "' + where + '"';\r
246         }\r
247         var range = el.ownerDocument.createRange();\r
248         var frag;\r
249         switch(where){\r
250              case "beforebegin":\r
251                 range.setStartBefore(el);\r
252                 frag = range.createContextualFragment(html);\r
253                 el.parentNode.insertBefore(frag, el);\r
254                 return el.previousSibling;\r
255              case "afterbegin":\r
256                 if(el.firstChild){\r
257                     range.setStartBefore(el.firstChild);\r
258                     frag = range.createContextualFragment(html);\r
259                     el.insertBefore(frag, el.firstChild);\r
260                     return el.firstChild;\r
261                 }else{\r
262                     el.innerHTML = html;\r
263                     return el.firstChild;\r
264                 }\r
265             case "beforeend":\r
266                 if(el.lastChild){\r
267                     range.setStartAfter(el.lastChild);\r
268                     frag = range.createContextualFragment(html);\r
269                     el.appendChild(frag);\r
270                     return el.lastChild;\r
271                 }else{\r
272                     el.innerHTML = html;\r
273                     return el.lastChild;\r
274                 }\r
275             case "afterend":\r
276                 range.setStartAfter(el);\r
277                 frag = range.createContextualFragment(html);\r
278                 el.parentNode.insertBefore(frag, el.nextSibling);\r
279                 return el.nextSibling;\r
280             }\r
281             throw 'Illegal insertion point -> "' + where + '"';\r
282     },\r
283 \r
284     \r
285     insertBefore : function(el, o, returnElement){\r
286         return this.doInsert(el, o, returnElement, "beforeBegin");\r
287     },\r
288 \r
289     \r
290     insertAfter : function(el, o, returnElement){\r
291         return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");\r
292     },\r
293 \r
294     \r
295     insertFirst : function(el, o, returnElement){\r
296         return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");\r
297     },\r
298 \r
299     // private\r
300     doInsert : function(el, o, returnElement, pos, sibling){\r
301         el = Ext.getDom(el);\r
302         var newNode;\r
303         if(this.useDom){\r
304             newNode = createDom(o, null);\r
305             (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);\r
306         }else{\r
307             var html = createHtml(o);\r
308             newNode = this.insertHtml(pos, el, html);\r
309         }\r
310         return returnElement ? Ext.get(newNode, true) : newNode;\r
311     },\r
312 \r
313     \r
314     append : function(el, o, returnElement){\r
315         el = Ext.getDom(el);\r
316         var newNode;\r
317         if(this.useDom){\r
318             newNode = createDom(o, null);\r
319             el.appendChild(newNode);\r
320         }else{\r
321             var html = createHtml(o);\r
322             newNode = this.insertHtml("beforeEnd", el, html);\r
323         }\r
324         return returnElement ? Ext.get(newNode, true) : newNode;\r
325     },\r
326 \r
327     \r
328     overwrite : function(el, o, returnElement){\r
329         el = Ext.getDom(el);\r
330         el.innerHTML = createHtml(o);\r
331         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;\r
332     },\r
333 \r
334     \r
335     createTemplate : function(o){\r
336         var html = createHtml(o);\r
337         return new Ext.Template(html);\r
338     }\r
339     };\r
340 }();\r
341 \r
342 \r
343 Ext.Template = function(html){\r
344     var a = arguments;\r
345     if(Ext.isArray(html)){\r
346         html = html.join("");\r
347     }else if(a.length > 1){\r
348         var buf = [];\r
349         for(var i = 0, len = a.length; i < len; i++){\r
350             if(typeof a[i] == 'object'){\r
351                 Ext.apply(this, a[i]);\r
352             }else{\r
353                 buf[buf.length] = a[i];\r
354             }\r
355         }\r
356         html = buf.join('');\r
357     }\r
358     \r
359     this.html = html;\r
360     if(this.compiled){\r
361         this.compile();\r
362     }\r
363 };\r
364 Ext.Template.prototype = {\r
365     \r
366     applyTemplate : function(values){\r
367         if(this.compiled){\r
368             return this.compiled(values);\r
369         }\r
370         var useF = this.disableFormats !== true;\r
371         var fm = Ext.util.Format, tpl = this;\r
372         var fn = function(m, name, format, args){\r
373             if(format && useF){\r
374                 if(format.substr(0, 5) == "this."){\r
375                     return tpl.call(format.substr(5), values[name], values);\r
376                 }else{\r
377                     if(args){\r
378                         // quoted values are required for strings in compiled templates,\r
379                         // but for non compiled we need to strip them\r
380                         // quoted reversed for jsmin\r
381                         var re = /^\s*['"](.*)["']\s*$/;\r
382                         args = args.split(',');\r
383                         for(var i = 0, len = args.length; i < len; i++){\r
384                             args[i] = args[i].replace(re, "$1");\r
385                         }\r
386                         args = [values[name]].concat(args);\r
387                     }else{\r
388                         args = [values[name]];\r
389                     }\r
390                     return fm[format].apply(fm, args);\r
391                 }\r
392             }else{\r
393                 return values[name] !== undefined ? values[name] : "";\r
394             }\r
395         };\r
396         return this.html.replace(this.re, fn);\r
397     },\r
398 \r
399     \r
400     set : function(html, compile){\r
401         this.html = html;\r
402         this.compiled = null;\r
403         if(compile){\r
404             this.compile();\r
405         }\r
406         return this;\r
407     },\r
408 \r
409     \r
410     disableFormats : false,\r
411 \r
412     \r
413     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,\r
414 \r
415     \r
416     compile : function(){\r
417         var fm = Ext.util.Format;\r
418         var useF = this.disableFormats !== true;\r
419         var sep = Ext.isGecko ? "+" : ",";\r
420         var fn = function(m, name, format, args){\r
421             if(format && useF){\r
422                 args = args ? ',' + args : "";\r
423                 if(format.substr(0, 5) != "this."){\r
424                     format = "fm." + format + '(';\r
425                 }else{\r
426                     format = 'this.call("'+ format.substr(5) + '", ';\r
427                     args = ", values";\r
428                 }\r
429             }else{\r
430                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";\r
431             }\r
432             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";\r
433         };\r
434         var body;\r
435         // branched to use + in gecko and [].join() in others\r
436         if(Ext.isGecko){\r
437             body = "this.compiled = function(values){ return '" +\r
438                    this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +\r
439                     "';};";\r
440         }else{\r
441             body = ["this.compiled = function(values){ return ['"];\r
442             body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));\r
443             body.push("'].join('');};");\r
444             body = body.join('');\r
445         }\r
446         eval(body);\r
447         return this;\r
448     },\r
449 \r
450     // private function used to call members\r
451     call : function(fnName, value, allValues){\r
452         return this[fnName](value, allValues);\r
453     },\r
454 \r
455     \r
456     insertFirst: function(el, values, returnElement){\r
457         return this.doInsert('afterBegin', el, values, returnElement);\r
458     },\r
459 \r
460     \r
461     insertBefore: function(el, values, returnElement){\r
462         return this.doInsert('beforeBegin', el, values, returnElement);\r
463     },\r
464 \r
465     \r
466     insertAfter : function(el, values, returnElement){\r
467         return this.doInsert('afterEnd', el, values, returnElement);\r
468     },\r
469 \r
470     \r
471     append : function(el, values, returnElement){\r
472         return this.doInsert('beforeEnd', el, values, returnElement);\r
473     },\r
474 \r
475     doInsert : function(where, el, values, returnEl){\r
476         el = Ext.getDom(el);\r
477         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));\r
478         return returnEl ? Ext.get(newNode, true) : newNode;\r
479     },\r
480 \r
481     \r
482     overwrite : function(el, values, returnElement){\r
483         el = Ext.getDom(el);\r
484         el.innerHTML = this.applyTemplate(values);\r
485         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;\r
486     }\r
487 };\r
488 \r
489 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;\r
490 \r
491 // backwards compat\r
492 Ext.DomHelper.Template = Ext.Template;\r
493 \r
494 \r
495 Ext.Template.from = function(el, config){\r
496     el = Ext.getDom(el);\r
497     return new Ext.Template(el.value || el.innerHTML, config || '');\r
498 };\r
499 \r
500 \r
501 Ext.DomQuery = function(){\r
502     var cache = {}, simpleCache = {}, valueCache = {};\r
503     var nonSpace = /\S/;\r
504     var trimRe = /^\s+|\s+$/g;\r
505     var tplRe = /\{(\d+)\}/g;\r
506     var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;\r
507     var tagTokenRe = /^(#)?([\w-\*]+)/;\r
508     var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;\r
509 \r
510     function child(p, index){\r
511         var i = 0;\r
512         var n = p.firstChild;\r
513         while(n){\r
514             if(n.nodeType == 1){\r
515                if(++i == index){\r
516                    return n;\r
517                }\r
518             }\r
519             n = n.nextSibling;\r
520         }\r
521         return null;\r
522     };\r
523 \r
524     function next(n){\r
525         while((n = n.nextSibling) && n.nodeType != 1);\r
526         return n;\r
527     };\r
528 \r
529     function prev(n){\r
530         while((n = n.previousSibling) && n.nodeType != 1);\r
531         return n;\r
532     };\r
533 \r
534     function children(d){\r
535         var n = d.firstChild, ni = -1;\r
536             while(n){\r
537                 var nx = n.nextSibling;\r
538                 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
539                     d.removeChild(n);\r
540                 }else{\r
541                     n.nodeIndex = ++ni;\r
542                 }\r
543                 n = nx;\r
544             }\r
545             return this;\r
546         };\r
547 \r
548     function byClassName(c, a, v){\r
549         if(!v){\r
550             return c;\r
551         }\r
552         var r = [], ri = -1, cn;\r
553         for(var i = 0, ci; ci = c[i]; i++){\r
554             if((' '+ci.className+' ').indexOf(v) != -1){\r
555                 r[++ri] = ci;\r
556             }\r
557         }\r
558         return r;\r
559     };\r
560 \r
561     function attrValue(n, attr){\r
562         if(!n.tagName && typeof n.length != "undefined"){\r
563             n = n[0];\r
564         }\r
565         if(!n){\r
566             return null;\r
567         }\r
568         if(attr == "for"){\r
569             return n.htmlFor;\r
570         }\r
571         if(attr == "class" || attr == "className"){\r
572             return n.className;\r
573         }\r
574         return n.getAttribute(attr) || n[attr];\r
575 \r
576     };\r
577 \r
578     function getNodes(ns, mode, tagName){\r
579         var result = [], ri = -1, cs;\r
580         if(!ns){\r
581             return result;\r
582         }\r
583         tagName = tagName || "*";\r
584         if(typeof ns.getElementsByTagName != "undefined"){\r
585             ns = [ns];\r
586         }\r
587         if(!mode){\r
588             for(var i = 0, ni; ni = ns[i]; i++){\r
589                 cs = ni.getElementsByTagName(tagName);\r
590                 for(var j = 0, ci; ci = cs[j]; j++){\r
591                     result[++ri] = ci;\r
592                 }\r
593             }\r
594         }else if(mode == "/" || mode == ">"){\r
595             var utag = tagName.toUpperCase();\r
596             for(var i = 0, ni, cn; ni = ns[i]; i++){\r
597                 cn = ni.children || ni.childNodes;\r
598                 for(var j = 0, cj; cj = cn[j]; j++){\r
599                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){\r
600                         result[++ri] = cj;\r
601                     }\r
602                 }\r
603             }\r
604         }else if(mode == "+"){\r
605             var utag = tagName.toUpperCase();\r
606             for(var i = 0, n; n = ns[i]; i++){\r
607                 while((n = n.nextSibling) && n.nodeType != 1);\r
608                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){\r
609                     result[++ri] = n;\r
610                 }\r
611             }\r
612         }else if(mode == "~"){\r
613             for(var i = 0, n; n = ns[i]; i++){\r
614                 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));\r
615                 if(n){\r
616                     result[++ri] = n;\r
617                 }\r
618             }\r
619         }\r
620         return result;\r
621     };\r
622 \r
623     function concat(a, b){\r
624         if(b.slice){\r
625             return a.concat(b);\r
626         }\r
627         for(var i = 0, l = b.length; i < l; i++){\r
628             a[a.length] = b[i];\r
629         }\r
630         return a;\r
631     }\r
632 \r
633     function byTag(cs, tagName){\r
634         if(cs.tagName || cs == document){\r
635             cs = [cs];\r
636         }\r
637         if(!tagName){\r
638             return cs;\r
639         }\r
640         var r = [], ri = -1;\r
641         tagName = tagName.toLowerCase();\r
642         for(var i = 0, ci; ci = cs[i]; i++){\r
643             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){\r
644                 r[++ri] = ci;\r
645             }\r
646         }\r
647         return r;\r
648     };\r
649 \r
650     function byId(cs, attr, id){\r
651         if(cs.tagName || cs == document){\r
652             cs = [cs];\r
653         }\r
654         if(!id){\r
655             return cs;\r
656         }\r
657         var r = [], ri = -1;\r
658         for(var i = 0,ci; ci = cs[i]; i++){\r
659             if(ci && ci.id == id){\r
660                 r[++ri] = ci;\r
661                 return r;\r
662             }\r
663         }\r
664         return r;\r
665     };\r
666 \r
667     function byAttribute(cs, attr, value, op, custom){\r
668         var r = [], ri = -1, st = custom=="{";\r
669         var f = Ext.DomQuery.operators[op];\r
670         for(var i = 0, ci; ci = cs[i]; i++){\r
671             var a;\r
672             if(st){\r
673                 a = Ext.DomQuery.getStyle(ci, attr);\r
674             }\r
675             else if(attr == "class" || attr == "className"){\r
676                 a = ci.className;\r
677             }else if(attr == "for"){\r
678                 a = ci.htmlFor;\r
679             }else if(attr == "href"){\r
680                 a = ci.getAttribute("href", 2);\r
681             }else{\r
682                 a = ci.getAttribute(attr);\r
683             }\r
684             if((f && f(a, value)) || (!f && a)){\r
685                 r[++ri] = ci;\r
686             }\r
687         }\r
688         return r;\r
689     };\r
690 \r
691     function byPseudo(cs, name, value){\r
692         return Ext.DomQuery.pseudos[name](cs, value);\r
693     };\r
694 \r
695     // This is for IE MSXML which does not support expandos.\r
696     // IE runs the same speed using setAttribute, however FF slows way down\r
697     // and Safari completely fails so they need to continue to use expandos.\r
698     var isIE = window.ActiveXObject ? true : false;\r
699 \r
700     // this eval is stop the compressor from\r
701     // renaming the variable to something shorter\r
702     eval("var batch = 30803;");\r
703 \r
704     var key = 30803;\r
705 \r
706     function nodupIEXml(cs){\r
707         var d = ++key;\r
708         cs[0].setAttribute("_nodup", d);\r
709         var r = [cs[0]];\r
710         for(var i = 1, len = cs.length; i < len; i++){\r
711             var c = cs[i];\r
712             if(!c.getAttribute("_nodup") != d){\r
713                 c.setAttribute("_nodup", d);\r
714                 r[r.length] = c;\r
715             }\r
716         }\r
717         for(var i = 0, len = cs.length; i < len; i++){\r
718             cs[i].removeAttribute("_nodup");\r
719         }\r
720         return r;\r
721     }\r
722 \r
723     function nodup(cs){\r
724         if(!cs){\r
725             return [];\r
726         }\r
727         var len = cs.length, c, i, r = cs, cj, ri = -1;\r
728         if(!len || typeof cs.nodeType != "undefined" || len == 1){\r
729             return cs;\r
730         }\r
731         if(isIE && typeof cs[0].selectSingleNode != "undefined"){\r
732             return nodupIEXml(cs);\r
733         }\r
734         var d = ++key;\r
735         cs[0]._nodup = d;\r
736         for(i = 1; c = cs[i]; i++){\r
737             if(c._nodup != d){\r
738                 c._nodup = d;\r
739             }else{\r
740                 r = [];\r
741                 for(var j = 0; j < i; j++){\r
742                     r[++ri] = cs[j];\r
743                 }\r
744                 for(j = i+1; cj = cs[j]; j++){\r
745                     if(cj._nodup != d){\r
746                         cj._nodup = d;\r
747                         r[++ri] = cj;\r
748                     }\r
749                 }\r
750                 return r;\r
751             }\r
752         }\r
753         return r;\r
754     }\r
755 \r
756     function quickDiffIEXml(c1, c2){\r
757         var d = ++key;\r
758         for(var i = 0, len = c1.length; i < len; i++){\r
759             c1[i].setAttribute("_qdiff", d);\r
760         }\r
761         var r = [];\r
762         for(var i = 0, len = c2.length; i < len; i++){\r
763             if(c2[i].getAttribute("_qdiff") != d){\r
764                 r[r.length] = c2[i];\r
765             }\r
766         }\r
767         for(var i = 0, len = c1.length; i < len; i++){\r
768            c1[i].removeAttribute("_qdiff");\r
769         }\r
770         return r;\r
771     }\r
772 \r
773     function quickDiff(c1, c2){\r
774         var len1 = c1.length;\r
775         if(!len1){\r
776             return c2;\r
777         }\r
778         if(isIE && c1[0].selectSingleNode){\r
779             return quickDiffIEXml(c1, c2);\r
780         }\r
781         var d = ++key;\r
782         for(var i = 0; i < len1; i++){\r
783             c1[i]._qdiff = d;\r
784         }\r
785         var r = [];\r
786         for(var i = 0, len = c2.length; i < len; i++){\r
787             if(c2[i]._qdiff != d){\r
788                 r[r.length] = c2[i];\r
789             }\r
790         }\r
791         return r;\r
792     }\r
793 \r
794     function quickId(ns, mode, root, id){\r
795         if(ns == root){\r
796            var d = root.ownerDocument || root;\r
797            return d.getElementById(id);\r
798         }\r
799         ns = getNodes(ns, mode, "*");\r
800         return byId(ns, null, id);\r
801     }\r
802 \r
803     return {\r
804         getStyle : function(el, name){\r
805             return Ext.fly(el).getStyle(name);\r
806         },\r
807         \r
808         compile : function(path, type){\r
809             type = type || "select";\r
810 \r
811             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];\r
812             var q = path, mode, lq;\r
813             var tk = Ext.DomQuery.matchers;\r
814             var tklen = tk.length;\r
815             var mm;\r
816 \r
817             // accept leading mode switch\r
818             var lmode = q.match(modeRe);\r
819             if(lmode && lmode[1]){\r
820                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';\r
821                 q = q.replace(lmode[1], "");\r
822             }\r
823             // strip leading slashes\r
824             while(path.substr(0, 1)=="/"){\r
825                 path = path.substr(1);\r
826             }\r
827 \r
828             while(q && lq != q){\r
829                 lq = q;\r
830                 var tm = q.match(tagTokenRe);\r
831                 if(type == "select"){\r
832                     if(tm){\r
833                         if(tm[1] == "#"){\r
834                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';\r
835                         }else{\r
836                             fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';\r
837                         }\r
838                         q = q.replace(tm[0], "");\r
839                     }else if(q.substr(0, 1) != '@'){\r
840                         fn[fn.length] = 'n = getNodes(n, mode, "*");';\r
841                     }\r
842                 }else{\r
843                     if(tm){\r
844                         if(tm[1] == "#"){\r
845                             fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';\r
846                         }else{\r
847                             fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';\r
848                         }\r
849                         q = q.replace(tm[0], "");\r
850                     }\r
851                 }\r
852                 while(!(mm = q.match(modeRe))){\r
853                     var matched = false;\r
854                     for(var j = 0; j < tklen; j++){\r
855                         var t = tk[j];\r
856                         var m = q.match(t.re);\r
857                         if(m){\r
858                             fn[fn.length] = t.select.replace(tplRe, function(x, i){\r
859                                                     return m[i];\r
860                                                 });\r
861                             q = q.replace(m[0], "");\r
862                             matched = true;\r
863                             break;\r
864                         }\r
865                     }\r
866                     // prevent infinite loop on bad selector\r
867                     if(!matched){\r
868                         throw 'Error parsing selector, parsing failed at "' + q + '"';\r
869                     }\r
870                 }\r
871                 if(mm[1]){\r
872                     fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';\r
873                     q = q.replace(mm[1], "");\r
874                 }\r
875             }\r
876             fn[fn.length] = "return nodup(n);\n}";\r
877             eval(fn.join(""));\r
878             return f;\r
879         },\r
880 \r
881         \r
882         select : function(path, root, type){\r
883             if(!root || root == document){\r
884                 root = document;\r
885             }\r
886             if(typeof root == "string"){\r
887                 root = document.getElementById(root);\r
888             }\r
889             var paths = path.split(",");\r
890             var results = [];\r
891             for(var i = 0, len = paths.length; i < len; i++){\r
892                 var p = paths[i].replace(trimRe, "");\r
893                 if(!cache[p]){\r
894                     cache[p] = Ext.DomQuery.compile(p);\r
895                     if(!cache[p]){\r
896                         throw p + " is not a valid selector";\r
897                     }\r
898                 }\r
899                 var result = cache[p](root);\r
900                 if(result && result != document){\r
901                     results = results.concat(result);\r
902                 }\r
903             }\r
904             if(paths.length > 1){\r
905                 return nodup(results);\r
906             }\r
907             return results;\r
908         },\r
909 \r
910         \r
911         selectNode : function(path, root){\r
912             return Ext.DomQuery.select(path, root)[0];\r
913         },\r
914 \r
915         \r
916         selectValue : function(path, root, defaultValue){\r
917             path = path.replace(trimRe, "");\r
918             if(!valueCache[path]){\r
919                 valueCache[path] = Ext.DomQuery.compile(path, "select");\r
920             }\r
921             var n = valueCache[path](root);\r
922             n = n[0] ? n[0] : n;\r
923             var v = (n && n.firstChild ? n.firstChild.nodeValue : null);\r
924             return ((v === null||v === undefined||v==='') ? defaultValue : v);\r
925         },\r
926 \r
927         \r
928         selectNumber : function(path, root, defaultValue){\r
929             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);\r
930             return parseFloat(v);\r
931         },\r
932 \r
933         \r
934         is : function(el, ss){\r
935             if(typeof el == "string"){\r
936                 el = document.getElementById(el);\r
937             }\r
938             var isArray = Ext.isArray(el);\r
939             var result = Ext.DomQuery.filter(isArray ? el : [el], ss);\r
940             return isArray ? (result.length == el.length) : (result.length > 0);\r
941         },\r
942 \r
943         \r
944         filter : function(els, ss, nonMatches){\r
945             ss = ss.replace(trimRe, "");\r
946             if(!simpleCache[ss]){\r
947                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");\r
948             }\r
949             var result = simpleCache[ss](els);\r
950             return nonMatches ? quickDiff(result, els) : result;\r
951         },\r
952 \r
953         \r
954         matchers : [{\r
955                 re: /^\.([\w-]+)/,\r
956                 select: 'n = byClassName(n, null, " {1} ");'\r
957             }, {\r
958                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,\r
959                 select: 'n = byPseudo(n, "{1}", "{2}");'\r
960             },{\r
961                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,\r
962                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'\r
963             }, {\r
964                 re: /^#([\w-]+)/,\r
965                 select: 'n = byId(n, null, "{1}");'\r
966             },{\r
967                 re: /^@([\w-]+)/,\r
968                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'\r
969             }\r
970         ],\r
971 \r
972         \r
973         operators : {\r
974             "=" : function(a, v){\r
975                 return a == v;\r
976             },\r
977             "!=" : function(a, v){\r
978                 return a != v;\r
979             },\r
980             "^=" : function(a, v){\r
981                 return a && a.substr(0, v.length) == v;\r
982             },\r
983             "$=" : function(a, v){\r
984                 return a && a.substr(a.length-v.length) == v;\r
985             },\r
986             "*=" : function(a, v){\r
987                 return a && a.indexOf(v) !== -1;\r
988             },\r
989             "%=" : function(a, v){\r
990                 return (a % v) == 0;\r
991             },\r
992             "|=" : function(a, v){\r
993                 return a && (a == v || a.substr(0, v.length+1) == v+'-');\r
994             },\r
995             "~=" : function(a, v){\r
996                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;\r
997             }\r
998         },\r
999 \r
1000         \r
1001         pseudos : {\r
1002             "first-child" : function(c){\r
1003                 var r = [], ri = -1, n;\r
1004                 for(var i = 0, ci; ci = n = c[i]; i++){\r
1005                     while((n = n.previousSibling) && n.nodeType != 1);\r
1006                     if(!n){\r
1007                         r[++ri] = ci;\r
1008                     }\r
1009                 }\r
1010                 return r;\r
1011             },\r
1012 \r
1013             "last-child" : function(c){\r
1014                 var r = [], ri = -1, n;\r
1015                 for(var i = 0, ci; ci = n = c[i]; i++){\r
1016                     while((n = n.nextSibling) && n.nodeType != 1);\r
1017                     if(!n){\r
1018                         r[++ri] = ci;\r
1019                     }\r
1020                 }\r
1021                 return r;\r
1022             },\r
1023 \r
1024             "nth-child" : function(c, a) {\r
1025                 var r = [], ri = -1;\r
1026                 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);\r
1027                 var f = (m[1] || 1) - 0, l = m[2] - 0;\r
1028                 for(var i = 0, n; n = c[i]; i++){\r
1029                     var pn = n.parentNode;\r
1030                     if (batch != pn._batch) {\r
1031                         var j = 0;\r
1032                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){\r
1033                             if(cn.nodeType == 1){\r
1034                                cn.nodeIndex = ++j;\r
1035                             }\r
1036                         }\r
1037                         pn._batch = batch;\r
1038                     }\r
1039                     if (f == 1) {\r
1040                         if (l == 0 || n.nodeIndex == l){\r
1041                             r[++ri] = n;\r
1042                         }\r
1043                     } else if ((n.nodeIndex + l) % f == 0){\r
1044                         r[++ri] = n;\r
1045                     }\r
1046                 }\r
1047 \r
1048                 return r;\r
1049             },\r
1050 \r
1051             "only-child" : function(c){\r
1052                 var r = [], ri = -1;;\r
1053                 for(var i = 0, ci; ci = c[i]; i++){\r
1054                     if(!prev(ci) && !next(ci)){\r
1055                         r[++ri] = ci;\r
1056                     }\r
1057                 }\r
1058                 return r;\r
1059             },\r
1060 \r
1061             "empty" : function(c){\r
1062                 var r = [], ri = -1;\r
1063                 for(var i = 0, ci; ci = c[i]; i++){\r
1064                     var cns = ci.childNodes, j = 0, cn, empty = true;\r
1065                     while(cn = cns[j]){\r
1066                         ++j;\r
1067                         if(cn.nodeType == 1 || cn.nodeType == 3){\r
1068                             empty = false;\r
1069                             break;\r
1070                         }\r
1071                     }\r
1072                     if(empty){\r
1073                         r[++ri] = ci;\r
1074                     }\r
1075                 }\r
1076                 return r;\r
1077             },\r
1078 \r
1079             "contains" : function(c, v){\r
1080                 var r = [], ri = -1;\r
1081                 for(var i = 0, ci; ci = c[i]; i++){\r
1082                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){\r
1083                         r[++ri] = ci;\r
1084                     }\r
1085                 }\r
1086                 return r;\r
1087             },\r
1088 \r
1089             "nodeValue" : function(c, v){\r
1090                 var r = [], ri = -1;\r
1091                 for(var i = 0, ci; ci = c[i]; i++){\r
1092                     if(ci.firstChild && ci.firstChild.nodeValue == v){\r
1093                         r[++ri] = ci;\r
1094                     }\r
1095                 }\r
1096                 return r;\r
1097             },\r
1098 \r
1099             "checked" : function(c){\r
1100                 var r = [], ri = -1;\r
1101                 for(var i = 0, ci; ci = c[i]; i++){\r
1102                     if(ci.checked == true){\r
1103                         r[++ri] = ci;\r
1104                     }\r
1105                 }\r
1106                 return r;\r
1107             },\r
1108 \r
1109             "not" : function(c, ss){\r
1110                 return Ext.DomQuery.filter(c, ss, true);\r
1111             },\r
1112 \r
1113             "any" : function(c, selectors){\r
1114                 var ss = selectors.split('|');\r
1115                 var r = [], ri = -1, s;\r
1116                 for(var i = 0, ci; ci = c[i]; i++){\r
1117                     for(var j = 0; s = ss[j]; j++){\r
1118                         if(Ext.DomQuery.is(ci, s)){\r
1119                             r[++ri] = ci;\r
1120                             break;\r
1121                         }\r
1122                     }\r
1123                 }\r
1124                 return r;\r
1125             },\r
1126 \r
1127             "odd" : function(c){\r
1128                 return this["nth-child"](c, "odd");\r
1129             },\r
1130 \r
1131             "even" : function(c){\r
1132                 return this["nth-child"](c, "even");\r
1133             },\r
1134 \r
1135             "nth" : function(c, a){\r
1136                 return c[a-1] || [];\r
1137             },\r
1138 \r
1139             "first" : function(c){\r
1140                 return c[0] || [];\r
1141             },\r
1142 \r
1143             "last" : function(c){\r
1144                 return c[c.length-1] || [];\r
1145             },\r
1146 \r
1147             "has" : function(c, ss){\r
1148                 var s = Ext.DomQuery.select;\r
1149                 var r = [], ri = -1;\r
1150                 for(var i = 0, ci; ci = c[i]; i++){\r
1151                     if(s(ss, ci).length > 0){\r
1152                         r[++ri] = ci;\r
1153                     }\r
1154                 }\r
1155                 return r;\r
1156             },\r
1157 \r
1158             "next" : function(c, ss){\r
1159                 var is = Ext.DomQuery.is;\r
1160                 var r = [], ri = -1;\r
1161                 for(var i = 0, ci; ci = c[i]; i++){\r
1162                     var n = next(ci);\r
1163                     if(n && is(n, ss)){\r
1164                         r[++ri] = ci;\r
1165                     }\r
1166                 }\r
1167                 return r;\r
1168             },\r
1169 \r
1170             "prev" : function(c, ss){\r
1171                 var is = Ext.DomQuery.is;\r
1172                 var r = [], ri = -1;\r
1173                 for(var i = 0, ci; ci = c[i]; i++){\r
1174                     var n = prev(ci);\r
1175                     if(n && is(n, ss)){\r
1176                         r[++ri] = ci;\r
1177                     }\r
1178                 }\r
1179                 return r;\r
1180             }\r
1181         }\r
1182     };\r
1183 }();\r
1184 \r
1185 \r
1186 Ext.query = Ext.DomQuery.select;\r
1187 \r
1188 \r
1189 Ext.util.Observable = function(){\r
1190     \r
1191     if(this.listeners){\r
1192         this.on(this.listeners);\r
1193         delete this.listeners;\r
1194     }\r
1195 };\r
1196 Ext.util.Observable.prototype = {\r
1197     \r
1198     fireEvent : function(){\r
1199         if(this.eventsSuspended !== true){\r
1200             var ce = this.events[arguments[0].toLowerCase()];\r
1201             if(typeof ce == "object"){\r
1202                 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));\r
1203             }\r
1204         }\r
1205         return true;\r
1206     },\r
1207 \r
1208     // private\r
1209     filterOptRe : /^(?:scope|delay|buffer|single)$/,\r
1210 \r
1211     \r
1212     addListener : function(eventName, fn, scope, o){\r
1213         if(typeof eventName == "object"){\r
1214             o = eventName;\r
1215             for(var e in o){\r
1216                 if(this.filterOptRe.test(e)){\r
1217                     continue;\r
1218                 }\r
1219                 if(typeof o[e] == "function"){\r
1220                     // shared options\r
1221                     this.addListener(e, o[e], o.scope,  o);\r
1222                 }else{\r
1223                     // individual options\r
1224                     this.addListener(e, o[e].fn, o[e].scope, o[e]);\r
1225                 }\r
1226             }\r
1227             return;\r
1228         }\r
1229         o = (!o || typeof o == "boolean") ? {} : o;\r
1230         eventName = eventName.toLowerCase();\r
1231         var ce = this.events[eventName] || true;\r
1232         if(typeof ce == "boolean"){\r
1233             ce = new Ext.util.Event(this, eventName);\r
1234             this.events[eventName] = ce;\r
1235         }\r
1236         ce.addListener(fn, scope, o);\r
1237     },\r
1238 \r
1239     \r
1240     removeListener : function(eventName, fn, scope){\r
1241         var ce = this.events[eventName.toLowerCase()];\r
1242         if(typeof ce == "object"){\r
1243             ce.removeListener(fn, scope);\r
1244         }\r
1245     },\r
1246 \r
1247     \r
1248     purgeListeners : function(){\r
1249         for(var evt in this.events){\r
1250             if(typeof this.events[evt] == "object"){\r
1251                  this.events[evt].clearListeners();\r
1252             }\r
1253         }\r
1254     },\r
1255 \r
1256     \r
1257     relayEvents : function(o, events){\r
1258         var createHandler = function(ename){\r
1259             return function(){\r
1260                 return this.fireEvent.apply(this, Ext.combine(ename, Array.prototype.slice.call(arguments, 0)));\r
1261             };\r
1262         };\r
1263         for(var i = 0, len = events.length; i < len; i++){\r
1264             var ename = events[i];\r
1265             if(!this.events[ename]){ this.events[ename] = true; };\r
1266             o.on(ename, createHandler(ename), this);\r
1267         }\r
1268     },\r
1269 \r
1270     \r
1271     addEvents : function(o){\r
1272         if(!this.events){\r
1273             this.events = {};\r
1274         }\r
1275         if(typeof o == 'string'){\r
1276             for(var i = 0, a = arguments, v; v = a[i]; i++){\r
1277                 if(!this.events[a[i]]){\r
1278                     this.events[a[i]] = true;\r
1279                 }\r
1280             }\r
1281         }else{\r
1282             Ext.applyIf(this.events, o);\r
1283         }\r
1284     },\r
1285 \r
1286     \r
1287     hasListener : function(eventName){\r
1288         var e = this.events[eventName];\r
1289         return typeof e == "object" && e.listeners.length > 0;\r
1290     },\r
1291 \r
1292     \r
1293     suspendEvents : function(){\r
1294         this.eventsSuspended = true;\r
1295     },\r
1296 \r
1297     \r
1298     resumeEvents : function(){\r
1299         this.eventsSuspended = false;\r
1300     },\r
1301 \r
1302     // these are considered experimental\r
1303     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call\r
1304     // private\r
1305     getMethodEvent : function(method){\r
1306         if(!this.methodEvents){\r
1307             this.methodEvents = {};\r
1308         }\r
1309         var e = this.methodEvents[method];\r
1310         if(!e){\r
1311             e = {};\r
1312             this.methodEvents[method] = e;\r
1313 \r
1314             e.originalFn = this[method];\r
1315             e.methodName = method;\r
1316             e.before = [];\r
1317             e.after = [];\r
1318 \r
1319 \r
1320             var returnValue, v, cancel;\r
1321             var obj = this;\r
1322 \r
1323             var makeCall = function(fn, scope, args){\r
1324                 if((v = fn.apply(scope || obj, args)) !== undefined){\r
1325                     if(typeof v === 'object'){\r
1326                         if(v.returnValue !== undefined){\r
1327                             returnValue = v.returnValue;\r
1328                         }else{\r
1329                             returnValue = v;\r
1330                         }\r
1331                         if(v.cancel === true){\r
1332                             cancel = true;\r
1333                         }\r
1334                     }else if(v === false){\r
1335                         cancel = true;\r
1336                     }else {\r
1337                         returnValue = v;\r
1338                     }\r
1339                 }\r
1340             }\r
1341 \r
1342             this[method] = function(){\r
1343                 returnValue = v = undefined; cancel = false;\r
1344                 var args = Array.prototype.slice.call(arguments, 0);\r
1345                 for(var i = 0, len = e.before.length; i < len; i++){\r
1346                     makeCall(e.before[i].fn, e.before[i].scope, args);\r
1347                     if(cancel){\r
1348                         return returnValue;\r
1349                     }\r
1350                 }\r
1351 \r
1352                 if((v = e.originalFn.apply(obj, args)) !== undefined){\r
1353                     returnValue = v;\r
1354                 }\r
1355 \r
1356                 for(var i = 0, len = e.after.length; i < len; i++){\r
1357                     makeCall(e.after[i].fn, e.after[i].scope, args);\r
1358                     if(cancel){\r
1359                         return returnValue;\r
1360                     }\r
1361                 }\r
1362                 return returnValue;\r
1363             };\r
1364         }\r
1365         return e;\r
1366     },\r
1367 \r
1368     // adds an "interceptor" called before the original method\r
1369     beforeMethod : function(method, fn, scope){\r
1370         var e = this.getMethodEvent(method);\r
1371         e.before.push({fn: fn, scope: scope});\r
1372     },\r
1373 \r
1374     // adds a "sequence" called after the original method\r
1375     afterMethod : function(method, fn, scope){\r
1376         var e = this.getMethodEvent(method);\r
1377         e.after.push({fn: fn, scope: scope});\r
1378     },\r
1379 \r
1380     removeMethodListener : function(method, fn, scope){\r
1381         var e = this.getMethodEvent(method);\r
1382         for(var i = 0, len = e.before.length; i < len; i++){\r
1383             if(e.before[i].fn == fn && e.before[i].scope == scope){\r
1384                 e.before.splice(i, 1);\r
1385                 return;\r
1386             }\r
1387         }\r
1388         for(var i = 0, len = e.after.length; i < len; i++){\r
1389             if(e.after[i].fn == fn && e.after[i].scope == scope){\r
1390                 e.after.splice(i, 1);\r
1391                 return;\r
1392             }\r
1393         }\r
1394     }\r
1395 };\r
1396 \r
1397 Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;\r
1398 \r
1399 Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;\r
1400 \r
1401 \r
1402 Ext.util.Observable.capture = function(o, fn, scope){\r
1403     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);\r
1404 };\r
1405 \r
1406 \r
1407 Ext.util.Observable.releaseCapture = function(o){\r
1408     o.fireEvent = Ext.util.Observable.prototype.fireEvent;\r
1409 };\r
1410 \r
1411 (function(){\r
1412 \r
1413     var createBuffered = function(h, o, scope){\r
1414         var task = new Ext.util.DelayedTask();\r
1415         return function(){\r
1416             task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));\r
1417         };\r
1418     };\r
1419 \r
1420     var createSingle = function(h, e, fn, scope){\r
1421         return function(){\r
1422             e.removeListener(fn, scope);\r
1423             return h.apply(scope, arguments);\r
1424         };\r
1425     };\r
1426 \r
1427     var createDelayed = function(h, o, scope){\r
1428         return function(){\r
1429             var args = Array.prototype.slice.call(arguments, 0);\r
1430             setTimeout(function(){\r
1431                 h.apply(scope, args);\r
1432             }, o.delay || 10);\r
1433         };\r
1434     };\r
1435 \r
1436     Ext.util.Event = function(obj, name){\r
1437         this.name = name;\r
1438         this.obj = obj;\r
1439         this.listeners = [];\r
1440     };\r
1441 \r
1442     Ext.util.Event.prototype = {\r
1443         addListener : function(fn, scope, options){\r
1444             scope = scope || this.obj;\r
1445             if(!this.isListening(fn, scope)){\r
1446                 var l = this.createListener(fn, scope, options);\r
1447                 if(!this.firing){\r
1448                     this.listeners.push(l);\r
1449                 }else{ // if we are currently firing this event, don't disturb the listener loop\r
1450                     this.listeners = this.listeners.slice(0);\r
1451                     this.listeners.push(l);\r
1452                 }\r
1453             }\r
1454         },\r
1455 \r
1456         createListener : function(fn, scope, o){\r
1457             o = o || {};\r
1458             scope = scope || this.obj;\r
1459             var l = {fn: fn, scope: scope, options: o};\r
1460             var h = fn;\r
1461             if(o.delay){\r
1462                 h = createDelayed(h, o, scope);\r
1463             }\r
1464             if(o.single){\r
1465                 h = createSingle(h, this, fn, scope);\r
1466             }\r
1467             if(o.buffer){\r
1468                 h = createBuffered(h, o, scope);\r
1469             }\r
1470             l.fireFn = h;\r
1471             return l;\r
1472         },\r
1473 \r
1474         findListener : function(fn, scope){\r
1475             scope = scope || this.obj;\r
1476             var ls = this.listeners;\r
1477             for(var i = 0, len = ls.length; i < len; i++){\r
1478                 var l = ls[i];\r
1479                 if(l.fn == fn && l.scope == scope){\r
1480                     return i;\r
1481                 }\r
1482             }\r
1483             return -1;\r
1484         },\r
1485 \r
1486         isListening : function(fn, scope){\r
1487             return this.findListener(fn, scope) != -1;\r
1488         },\r
1489 \r
1490         removeListener : function(fn, scope){\r
1491             var index;\r
1492             if((index = this.findListener(fn, scope)) != -1){\r
1493                 if(!this.firing){\r
1494                     this.listeners.splice(index, 1);\r
1495                 }else{\r
1496                     this.listeners = this.listeners.slice(0);\r
1497                     this.listeners.splice(index, 1);\r
1498                 }\r
1499                 return true;\r
1500             }\r
1501             return false;\r
1502         },\r
1503 \r
1504         clearListeners : function(){\r
1505             this.listeners = [];\r
1506         },\r
1507 \r
1508         fire : function(){\r
1509             var ls = this.listeners, scope, len = ls.length;\r
1510             if(len > 0){\r
1511                 this.firing = true;\r
1512                 var args = Array.prototype.slice.call(arguments, 0);\r
1513                 for(var i = 0; i < len; i++){\r
1514                     var l = ls[i];\r
1515                     if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){\r
1516                         this.firing = false;\r
1517                         return false;\r
1518                     }\r
1519                 }\r
1520                 this.firing = false;\r
1521             }\r
1522             return true;\r
1523         }\r
1524     };\r
1525 })();\r
1526 \r
1527 Ext.EventManager = function(){\r
1528     var docReadyEvent, docReadyProcId, docReadyState = false;\r
1529     var resizeEvent, resizeTask, textEvent, textSize;\r
1530     var E = Ext.lib.Event;\r
1531     var D = Ext.lib.Dom;\r
1532     // fix parser confusion\r
1533     var xname = 'Ex' + 't';\r
1534 \r
1535     var elHash = {};\r
1536 \r
1537     var addListener = function(el, ename, fn, wrap, scope){\r
1538         var id = Ext.id(el);\r
1539         if(!elHash[id]){\r
1540             elHash[id] = {};\r
1541         }\r
1542         var es = elHash[id];\r
1543         if(!es[ename]){\r
1544             es[ename] = [];\r
1545         }\r
1546         var ls = es[ename];\r
1547         ls.push({\r
1548             id: id,\r
1549             ename: ename,\r
1550             fn: fn,\r
1551             wrap: wrap,\r
1552             scope: scope\r
1553         });\r
1554 \r
1555          E.on(el, ename, wrap);\r
1556 \r
1557         if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery\r
1558             el.addEventListener("DOMMouseScroll", wrap, false);\r
1559             E.on(window, 'unload', function(){\r
1560                 el.removeEventListener("DOMMouseScroll", wrap, false);\r
1561             });\r
1562         }\r
1563         if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document\r
1564             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);\r
1565         }\r
1566     }\r
1567 \r
1568     var removeListener = function(el, ename, fn, scope){\r
1569         el = Ext.getDom(el);\r
1570 \r
1571         var id = Ext.id(el), es = elHash[id], wrap;\r
1572         if(es){\r
1573             var ls = es[ename], l;\r
1574             if(ls){\r
1575                 for(var i = 0, len = ls.length; i < len; i++){\r
1576                     l = ls[i];\r
1577                     if(l.fn == fn && (!scope || l.scope == scope)){\r
1578                         wrap = l.wrap;\r
1579                         E.un(el, ename, wrap);\r
1580                         ls.splice(i, 1);\r
1581                         break;\r
1582                     }\r
1583                 }\r
1584             }\r
1585         }\r
1586         if(ename == "mousewheel" && el.addEventListener && wrap){\r
1587             el.removeEventListener("DOMMouseScroll", wrap, false);\r
1588         }\r
1589         if(ename == "mousedown" && el == document && wrap){ // fix stopped mousedowns on the document\r
1590             Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
1591         }\r
1592     }\r
1593 \r
1594     var removeAll = function(el){\r
1595         el = Ext.getDom(el);\r
1596         var id = Ext.id(el), es = elHash[id], ls;\r
1597         if(es){\r
1598             for(var ename in es){\r
1599                 if(es.hasOwnProperty(ename)){\r
1600                     ls = es[ename];\r
1601                     for(var i = 0, len = ls.length; i < len; i++){\r
1602                         E.un(el, ename, ls[i].wrap);\r
1603                         ls[i] = null;\r
1604                     }\r
1605                 }\r
1606                 es[ename] = null;\r
1607             }\r
1608             delete elHash[id];\r
1609         }\r
1610     }\r
1611 \r
1612 \r
1613     var fireDocReady = function(){\r
1614         if(!docReadyState){\r
1615             docReadyState = true;\r
1616             Ext.isReady = true;\r
1617             if(docReadyProcId){\r
1618                 clearInterval(docReadyProcId);\r
1619             }\r
1620             if(Ext.isGecko || Ext.isOpera) {\r
1621                 document.removeEventListener("DOMContentLoaded", fireDocReady, false);\r
1622             }\r
1623             if(Ext.isIE){\r
1624                 var defer = document.getElementById("ie-deferred-loader");\r
1625                 if(defer){\r
1626                     defer.onreadystatechange = null;\r
1627                     defer.parentNode.removeChild(defer);\r
1628                 }\r
1629             }\r
1630             if(docReadyEvent){\r
1631                 docReadyEvent.fire();\r
1632                 docReadyEvent.clearListeners();\r
1633             }\r
1634         }\r
1635     };\r
1636 \r
1637     var initDocReady = function(){\r
1638         docReadyEvent = new Ext.util.Event();\r
1639         if(Ext.isGecko || Ext.isOpera) {\r
1640             document.addEventListener("DOMContentLoaded", fireDocReady, false);\r
1641         }else if(Ext.isIE){\r
1642             document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");\r
1643             var defer = document.getElementById("ie-deferred-loader");\r
1644             defer.onreadystatechange = function(){\r
1645                 if(this.readyState == "complete"){\r
1646                     fireDocReady();\r
1647                 }\r
1648             };\r
1649         }else if(Ext.isSafari){\r
1650             docReadyProcId = setInterval(function(){\r
1651                 var rs = document.readyState;\r
1652                 if(rs == "complete") {\r
1653                     fireDocReady();\r
1654                  }\r
1655             }, 10);\r
1656         }\r
1657         // no matter what, make sure it fires on load\r
1658         E.on(window, "load", fireDocReady);\r
1659     };\r
1660 \r
1661     var createBuffered = function(h, o){\r
1662         var task = new Ext.util.DelayedTask(h);\r
1663         return function(e){\r
1664             // create new event object impl so new events don't wipe out properties\r
1665             e = new Ext.EventObjectImpl(e);\r
1666             task.delay(o.buffer, h, null, [e]);\r
1667         };\r
1668     };\r
1669 \r
1670     var createSingle = function(h, el, ename, fn, scope){\r
1671         return function(e){\r
1672             Ext.EventManager.removeListener(el, ename, fn, scope);\r
1673             h(e);\r
1674         };\r
1675     };\r
1676 \r
1677     var createDelayed = function(h, o){\r
1678         return function(e){\r
1679             // create new event object impl so new events don't wipe out properties\r
1680             e = new Ext.EventObjectImpl(e);\r
1681             setTimeout(function(){\r
1682                 h(e);\r
1683             }, o.delay || 10);\r
1684         };\r
1685     };\r
1686 \r
1687     var listen = function(element, ename, opt, fn, scope){\r
1688         var o = (!opt || typeof opt == "boolean") ? {} : opt;\r
1689         fn = fn || o.fn; scope = scope || o.scope;\r
1690         var el = Ext.getDom(element);\r
1691         if(!el){\r
1692             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';\r
1693         }\r
1694         var h = function(e){\r
1695             // prevent errors while unload occurring\r
1696             if(!window[xname]){\r
1697                 return;\r
1698             }\r
1699             e = Ext.EventObject.setEvent(e);\r
1700             var t;\r
1701             if(o.delegate){\r
1702                 t = e.getTarget(o.delegate, el);\r
1703                 if(!t){\r
1704                     return;\r
1705                 }\r
1706             }else{\r
1707                 t = e.target;\r
1708             }\r
1709             if(o.stopEvent === true){\r
1710                 e.stopEvent();\r
1711             }\r
1712             if(o.preventDefault === true){\r
1713                e.preventDefault();\r
1714             }\r
1715             if(o.stopPropagation === true){\r
1716                 e.stopPropagation();\r
1717             }\r
1718 \r
1719             if(o.normalized === false){\r
1720                 e = e.browserEvent;\r
1721             }\r
1722 \r
1723             fn.call(scope || el, e, t, o);\r
1724         };\r
1725         if(o.delay){\r
1726             h = createDelayed(h, o);\r
1727         }\r
1728         if(o.single){\r
1729             h = createSingle(h, el, ename, fn, scope);\r
1730         }\r
1731         if(o.buffer){\r
1732             h = createBuffered(h, o);\r
1733         }\r
1734 \r
1735         addListener(el, ename, fn, h, scope);\r
1736         return h;\r
1737     };\r
1738 \r
1739     var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;\r
1740     var pub = {\r
1741 \r
1742     \r
1743         addListener : function(element, eventName, fn, scope, options){\r
1744             if(typeof eventName == "object"){\r
1745                 var o = eventName;\r
1746                 for(var e in o){\r
1747                     if(propRe.test(e)){\r
1748                         continue;\r
1749                     }\r
1750                     if(typeof o[e] == "function"){\r
1751                         // shared options\r
1752                         listen(element, e, o, o[e], o.scope);\r
1753                     }else{\r
1754                         // individual options\r
1755                         listen(element, e, o[e]);\r
1756                     }\r
1757                 }\r
1758                 return;\r
1759             }\r
1760             return listen(element, eventName, options, fn, scope);\r
1761         },\r
1762 \r
1763         \r
1764         removeListener : function(element, eventName, fn, scope){\r
1765             return removeListener(element, eventName, fn, scope);\r
1766         },\r
1767 \r
1768         \r
1769         removeAll : function(element){\r
1770             return removeAll(element);\r
1771         },\r
1772 \r
1773         \r
1774         onDocumentReady : function(fn, scope, options){\r
1775             if(docReadyState){ // if it already fired\r
1776                 docReadyEvent.addListener(fn, scope, options);\r
1777                 docReadyEvent.fire();\r
1778                 docReadyEvent.clearListeners();\r
1779                 return;\r
1780             }\r
1781             if(!docReadyEvent){\r
1782                 initDocReady();\r
1783             }\r
1784             options = options || {};\r
1785             if(!options.delay){\r
1786                 options.delay = 1;\r
1787             }\r
1788             docReadyEvent.addListener(fn, scope, options);\r
1789         },\r
1790         \r
1791         // private\r
1792         doResizeEvent: function(){\r
1793             resizeEvent.fire(D.getViewWidth(), D.getViewHeight());\r
1794         },\r
1795 \r
1796         \r
1797         onWindowResize : function(fn, scope, options){\r
1798             if(!resizeEvent){\r
1799                 resizeEvent = new Ext.util.Event();\r
1800                 resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);\r
1801                 E.on(window, "resize", this.fireWindowResize, this);\r
1802             }\r
1803             resizeEvent.addListener(fn, scope, options);\r
1804         },\r
1805 \r
1806         // exposed only to allow manual firing\r
1807         fireWindowResize : function(){\r
1808             if(resizeEvent){\r
1809                 if((Ext.isIE||Ext.isAir) && resizeTask){\r
1810                     resizeTask.delay(50);\r
1811                 }else{\r
1812                     resizeEvent.fire(D.getViewWidth(), D.getViewHeight());\r
1813                 }\r
1814             }\r
1815         },\r
1816 \r
1817         \r
1818         onTextResize : function(fn, scope, options){\r
1819             if(!textEvent){\r
1820                 textEvent = new Ext.util.Event();\r
1821                 var textEl = new Ext.Element(document.createElement('div'));\r
1822                 textEl.dom.className = 'x-text-resize';\r
1823                 textEl.dom.innerHTML = 'X';\r
1824                 textEl.appendTo(document.body);\r
1825                 textSize = textEl.dom.offsetHeight;\r
1826                 setInterval(function(){\r
1827                     if(textEl.dom.offsetHeight != textSize){\r
1828                         textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);\r
1829                     }\r
1830                 }, this.textResizeInterval);\r
1831             }\r
1832             textEvent.addListener(fn, scope, options);\r
1833         },\r
1834 \r
1835         \r
1836         removeResizeListener : function(fn, scope){\r
1837             if(resizeEvent){\r
1838                 resizeEvent.removeListener(fn, scope);\r
1839             }\r
1840         },\r
1841 \r
1842         // private\r
1843         fireResize : function(){\r
1844             if(resizeEvent){\r
1845                 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());\r
1846             }\r
1847         },\r
1848         \r
1849         ieDeferSrc : false,\r
1850         \r
1851         textResizeInterval : 50\r
1852     };\r
1853      \r
1854     pub.on = pub.addListener;\r
1855     \r
1856     pub.un = pub.removeListener;\r
1857 \r
1858     pub.stoppedMouseDownEvent = new Ext.util.Event();\r
1859     return pub;\r
1860 }();\r
1861 \r
1862 Ext.onReady = Ext.EventManager.onDocumentReady;\r
1863 \r
1864 \r
1865 // Initialize doc classes\r
1866 (function(){\r
1867     var initExtCss = function(){\r
1868         // find the body element\r
1869         var bd = document.body || document.getElementsByTagName('body')[0];\r
1870         if(!bd){ return false; }\r
1871         var cls = [' ',\r
1872                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))\r
1873                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')\r
1874                 : Ext.isOpera ? "ext-opera"\r
1875                 : Ext.isSafari ? "ext-safari"\r
1876                 : Ext.isChrome ? "ext-chrome" : ""];\r
1877 \r
1878         if(Ext.isMac){\r
1879             cls.push("ext-mac");\r
1880         }\r
1881         if(Ext.isLinux){\r
1882             cls.push("ext-linux");\r
1883         }\r
1884         if(Ext.isBorderBox){\r
1885             cls.push('ext-border-box');\r
1886         }\r
1887         if(Ext.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"\r
1888             var p = bd.parentNode;\r
1889             if(p){\r
1890                 p.className += ' ext-strict';\r
1891             }\r
1892         }\r
1893         bd.className += cls.join(' ');\r
1894         return true;\r
1895     }\r
1896 \r
1897     if(!initExtCss()){\r
1898         Ext.onReady(initExtCss);\r
1899     }\r
1900 })();\r
1901 \r
1902 \r
1903 Ext.EventObject = function(){\r
1904 \r
1905     var E = Ext.lib.Event;\r
1906 \r
1907     // safari keypress events for special keys return bad keycodes\r
1908     var safariKeys = {\r
1909         3 : 13, // enter\r
1910         63234 : 37, // left\r
1911         63235 : 39, // right\r
1912         63232 : 38, // up\r
1913         63233 : 40, // down\r
1914         63276 : 33, // page up\r
1915         63277 : 34, // page down\r
1916         63272 : 46, // delete\r
1917         63273 : 36, // home\r
1918         63275 : 35  // end\r
1919     };\r
1920 \r
1921     // normalize button clicks\r
1922     var btnMap = Ext.isIE ? {1:0,4:1,2:2} :\r
1923                 (Ext.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});\r
1924 \r
1925     Ext.EventObjectImpl = function(e){\r
1926         if(e){\r
1927             this.setEvent(e.browserEvent || e);\r
1928         }\r
1929     };\r
1930 \r
1931     Ext.EventObjectImpl.prototype = {\r
1932         \r
1933         browserEvent : null,\r
1934         \r
1935         button : -1,\r
1936         \r
1937         shiftKey : false,\r
1938         \r
1939         ctrlKey : false,\r
1940         \r
1941         altKey : false,\r
1942 \r
1943         \r
1944         BACKSPACE: 8,\r
1945         \r
1946         TAB: 9,\r
1947         \r
1948         NUM_CENTER: 12,\r
1949         \r
1950         ENTER: 13,\r
1951         \r
1952         RETURN: 13,\r
1953         \r
1954         SHIFT: 16,\r
1955         \r
1956         CTRL: 17,\r
1957         CONTROL : 17, // legacy\r
1958         \r
1959         ALT: 18,\r
1960         \r
1961         PAUSE: 19,\r
1962         \r
1963         CAPS_LOCK: 20,\r
1964         \r
1965         ESC: 27,\r
1966         \r
1967         SPACE: 32,\r
1968         \r
1969         PAGE_UP: 33,\r
1970         PAGEUP : 33, // legacy\r
1971         \r
1972         PAGE_DOWN: 34,\r
1973         PAGEDOWN : 34, // legacy\r
1974         \r
1975         END: 35,\r
1976         \r
1977         HOME: 36,\r
1978         \r
1979         LEFT: 37,\r
1980         \r
1981         UP: 38,\r
1982         \r
1983         RIGHT: 39,\r
1984         \r
1985         DOWN: 40,\r
1986         \r
1987         PRINT_SCREEN: 44,\r
1988         \r
1989         INSERT: 45,\r
1990         \r
1991         DELETE: 46,\r
1992         \r
1993         ZERO: 48,\r
1994         \r
1995         ONE: 49,\r
1996         \r
1997         TWO: 50,\r
1998         \r
1999         THREE: 51,\r
2000         \r
2001         FOUR: 52,\r
2002         \r
2003         FIVE: 53,\r
2004         \r
2005         SIX: 54,\r
2006         \r
2007         SEVEN: 55,\r
2008         \r
2009         EIGHT: 56,\r
2010         \r
2011         NINE: 57,\r
2012         \r
2013         A: 65,\r
2014         \r
2015         B: 66,\r
2016         \r
2017         C: 67,\r
2018         \r
2019         D: 68,\r
2020         \r
2021         E: 69,\r
2022         \r
2023         F: 70,\r
2024         \r
2025         G: 71,\r
2026         \r
2027         H: 72,\r
2028         \r
2029         I: 73,\r
2030         \r
2031         J: 74,\r
2032         \r
2033         K: 75,\r
2034         \r
2035         L: 76,\r
2036         \r
2037         M: 77,\r
2038         \r
2039         N: 78,\r
2040         \r
2041         O: 79,\r
2042         \r
2043         P: 80,\r
2044         \r
2045         Q: 81,\r
2046         \r
2047         R: 82,\r
2048         \r
2049         S: 83,\r
2050         \r
2051         T: 84,\r
2052         \r
2053         U: 85,\r
2054         \r
2055         V: 86,\r
2056         \r
2057         W: 87,\r
2058         \r
2059         X: 88,\r
2060         \r
2061         Y: 89,\r
2062         \r
2063         Z: 90,\r
2064         \r
2065         CONTEXT_MENU: 93,\r
2066         \r
2067         NUM_ZERO: 96,\r
2068         \r
2069         NUM_ONE: 97,\r
2070         \r
2071         NUM_TWO: 98,\r
2072         \r
2073         NUM_THREE: 99,\r
2074         \r
2075         NUM_FOUR: 100,\r
2076         \r
2077         NUM_FIVE: 101,\r
2078         \r
2079         NUM_SIX: 102,\r
2080         \r
2081         NUM_SEVEN: 103,\r
2082         \r
2083         NUM_EIGHT: 104,\r
2084         \r
2085         NUM_NINE: 105,\r
2086         \r
2087         NUM_MULTIPLY: 106,\r
2088         \r
2089         NUM_PLUS: 107,\r
2090         \r
2091         NUM_MINUS: 109,\r
2092         \r
2093         NUM_PERIOD: 110,\r
2094         \r
2095         NUM_DIVISION: 111,\r
2096         \r
2097         F1: 112,\r
2098         \r
2099         F2: 113,\r
2100         \r
2101         F3: 114,\r
2102         \r
2103         F4: 115,\r
2104         \r
2105         F5: 116,\r
2106         \r
2107         F6: 117,\r
2108         \r
2109         F7: 118,\r
2110         \r
2111         F8: 119,\r
2112         \r
2113         F9: 120,\r
2114         \r
2115         F10: 121,\r
2116         \r
2117         F11: 122,\r
2118         \r
2119         F12: 123,\r
2120 \r
2121            \r
2122         setEvent : function(e){\r
2123             if(e == this || (e && e.browserEvent)){ // already wrapped\r
2124                 return e;\r
2125             }\r
2126             this.browserEvent = e;\r
2127             if(e){\r
2128                 // normalize buttons\r
2129                 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);\r
2130                 if(e.type == 'click' && this.button == -1){\r
2131                     this.button = 0;\r
2132                 }\r
2133                 this.type = e.type;\r
2134                 this.shiftKey = e.shiftKey;\r
2135                 // mac metaKey behaves like ctrlKey\r
2136                 this.ctrlKey = e.ctrlKey || e.metaKey;\r
2137                 this.altKey = e.altKey;\r
2138                 // in getKey these will be normalized for the mac\r
2139                 this.keyCode = e.keyCode;\r
2140                 this.charCode = e.charCode;\r
2141                 // cache the target for the delayed and or buffered events\r
2142                 this.target = E.getTarget(e);\r
2143                 // same for XY\r
2144                 this.xy = E.getXY(e);\r
2145             }else{\r
2146                 this.button = -1;\r
2147                 this.shiftKey = false;\r
2148                 this.ctrlKey = false;\r
2149                 this.altKey = false;\r
2150                 this.keyCode = 0;\r
2151                 this.charCode = 0;\r
2152                 this.target = null;\r
2153                 this.xy = [0, 0];\r
2154             }\r
2155             return this;\r
2156         },\r
2157 \r
2158         \r
2159         stopEvent : function(){\r
2160             if(this.browserEvent){\r
2161                 if(this.browserEvent.type == 'mousedown'){\r
2162                     Ext.EventManager.stoppedMouseDownEvent.fire(this);\r
2163                 }\r
2164                 E.stopEvent(this.browserEvent);\r
2165             }\r
2166         },\r
2167 \r
2168         \r
2169         preventDefault : function(){\r
2170             if(this.browserEvent){\r
2171                 E.preventDefault(this.browserEvent);\r
2172             }\r
2173         },\r
2174 \r
2175         \r
2176         isNavKeyPress : function(){\r
2177             var k = this.keyCode;\r
2178             k = Ext.isSafari ? (safariKeys[k] || k) : k;\r
2179             return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;\r
2180         },\r
2181 \r
2182         isSpecialKey : function(){\r
2183             var k = this.keyCode;\r
2184             return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13  || k == 40 || k == 27 ||\r
2185             (k == 16) || (k == 17) ||\r
2186             (k >= 18 && k <= 20) ||\r
2187             (k >= 33 && k <= 35) ||\r
2188             (k >= 36 && k <= 39) ||\r
2189             (k >= 44 && k <= 45);\r
2190         },\r
2191 \r
2192         \r
2193         stopPropagation : function(){\r
2194             if(this.browserEvent){\r
2195                 if(this.browserEvent.type == 'mousedown'){\r
2196                     Ext.EventManager.stoppedMouseDownEvent.fire(this);\r
2197                 }\r
2198                 E.stopPropagation(this.browserEvent);\r
2199             }\r
2200         },\r
2201 \r
2202         \r
2203         getCharCode : function(){\r
2204             return this.charCode || this.keyCode;\r
2205         },\r
2206 \r
2207         \r
2208         getKey : function(){\r
2209             var k = this.keyCode || this.charCode;\r
2210             return Ext.isSafari ? (safariKeys[k] || k) : k;\r
2211         },\r
2212 \r
2213         \r
2214         getPageX : function(){\r
2215             return this.xy[0];\r
2216         },\r
2217 \r
2218         \r
2219         getPageY : function(){\r
2220             return this.xy[1];\r
2221         },\r
2222 \r
2223         \r
2224         getTime : function(){\r
2225             if(this.browserEvent){\r
2226                 return E.getTime(this.browserEvent);\r
2227             }\r
2228             return null;\r
2229         },\r
2230 \r
2231         \r
2232         getXY : function(){\r
2233             return this.xy;\r
2234         },\r
2235 \r
2236         \r
2237         getTarget : function(selector, maxDepth, returnEl){\r
2238             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);\r
2239         },\r
2240 \r
2241         \r
2242         getRelatedTarget : function(){\r
2243             if(this.browserEvent){\r
2244                 return E.getRelatedTarget(this.browserEvent);\r
2245             }\r
2246             return null;\r
2247         },\r
2248 \r
2249         \r
2250         getWheelDelta : function(){\r
2251             var e = this.browserEvent;\r
2252             var delta = 0;\r
2253             if(e.wheelDelta){ \r
2254                 delta = e.wheelDelta/120;\r
2255             }else if(e.detail){ \r
2256                 delta = -e.detail/3;\r
2257             }\r
2258             return delta;\r
2259         },\r
2260 \r
2261         \r
2262         hasModifier : function(){\r
2263             return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true : false;\r
2264         },\r
2265 \r
2266         \r
2267         within : function(el, related, allowEl){\r
2268             var t = this[related ? "getRelatedTarget" : "getTarget"]();\r
2269             return t && ((allowEl ? (t === Ext.getDom(el)) : false) || Ext.fly(el).contains(t));\r
2270         },\r
2271 \r
2272         getPoint : function(){\r
2273             return new Ext.lib.Point(this.xy[0], this.xy[1]);\r
2274         }\r
2275     };\r
2276 \r
2277     return new Ext.EventObjectImpl();\r
2278 }();\r
2279 \r
2280 (function(){\r
2281 var D = Ext.lib.Dom;\r
2282 var E = Ext.lib.Event;\r
2283 var A = Ext.lib.Anim;\r
2284 \r
2285 // local style camelizing for speed\r
2286 var propCache = {};\r
2287 var camelRe = /(-[a-z])/gi;\r
2288 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };\r
2289 var view = document.defaultView;\r
2290 \r
2291 Ext.Element = function(element, forceNew){\r
2292     var dom = typeof element == "string" ?\r
2293             document.getElementById(element) : element;\r
2294     if(!dom){ // invalid id/element\r
2295         return null;\r
2296     }\r
2297     var id = dom.id;\r
2298     if(forceNew !== true && id && Ext.Element.cache[id]){ // element object already exists\r
2299         return Ext.Element.cache[id];\r
2300     }\r
2301 \r
2302     \r
2303     this.dom = dom;\r
2304 \r
2305     \r
2306     this.id = id || Ext.id(dom);\r
2307 };\r
2308 \r
2309 var El = Ext.Element;\r
2310 \r
2311 El.prototype = {\r
2312     \r
2313     originalDisplay : "",\r
2314 \r
2315     visibilityMode : 1,\r
2316     \r
2317     defaultUnit : "px",\r
2318     \r
2319     setVisibilityMode : function(visMode){\r
2320         this.visibilityMode = visMode;\r
2321         return this;\r
2322     },\r
2323     \r
2324     enableDisplayMode : function(display){\r
2325         this.setVisibilityMode(El.DISPLAY);\r
2326         if(typeof display != "undefined") this.originalDisplay = display;\r
2327         return this;\r
2328     },\r
2329 \r
2330     \r
2331     findParent : function(simpleSelector, maxDepth, returnEl){\r
2332         var p = this.dom, b = document.body, depth = 0, dq = Ext.DomQuery, stopEl;\r
2333         maxDepth = maxDepth || 50;\r
2334         if(typeof maxDepth != "number"){\r
2335             stopEl = Ext.getDom(maxDepth);\r
2336             maxDepth = 10;\r
2337         }\r
2338         while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){\r
2339             if(dq.is(p, simpleSelector)){\r
2340                 return returnEl ? Ext.get(p) : p;\r
2341             }\r
2342             depth++;\r
2343             p = p.parentNode;\r
2344         }\r
2345         return null;\r
2346     },\r
2347 \r
2348 \r
2349     \r
2350     findParentNode : function(simpleSelector, maxDepth, returnEl){\r
2351         var p = Ext.fly(this.dom.parentNode, '_internal');\r
2352         return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;\r
2353     },\r
2354 \r
2355     \r
2356     up : function(simpleSelector, maxDepth){\r
2357         return this.findParentNode(simpleSelector, maxDepth, true);\r
2358     },\r
2359 \r
2360 \r
2361 \r
2362     \r
2363     is : function(simpleSelector){\r
2364         return Ext.DomQuery.is(this.dom, simpleSelector);\r
2365     },\r
2366 \r
2367     \r
2368     animate : function(args, duration, onComplete, easing, animType){\r
2369         this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);\r
2370         return this;\r
2371     },\r
2372 \r
2373     \r
2374     anim : function(args, opt, animType, defaultDur, defaultEase, cb){\r
2375         animType = animType || 'run';\r
2376         opt = opt || {};\r
2377         var anim = Ext.lib.Anim[animType](\r
2378             this.dom, args,\r
2379             (opt.duration || defaultDur) || .35,\r
2380             (opt.easing || defaultEase) || 'easeOut',\r
2381             function(){\r
2382                 Ext.callback(cb, this);\r
2383                 Ext.callback(opt.callback, opt.scope || this, [this, opt]);\r
2384             },\r
2385             this\r
2386         );\r
2387         opt.anim = anim;\r
2388         return anim;\r
2389     },\r
2390 \r
2391     // private legacy anim prep\r
2392     preanim : function(a, i){\r
2393         return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});\r
2394     },\r
2395 \r
2396     \r
2397     clean : function(forceReclean){\r
2398         if(this.isCleaned && forceReclean !== true){\r
2399             return this;\r
2400         }\r
2401         var ns = /\S/;\r
2402         var d = this.dom, n = d.firstChild, ni = -1;\r
2403             while(n){\r
2404                 var nx = n.nextSibling;\r
2405                 if(n.nodeType == 3 && !ns.test(n.nodeValue)){\r
2406                     d.removeChild(n);\r
2407                 }else{\r
2408                     n.nodeIndex = ++ni;\r
2409                 }\r
2410                 n = nx;\r
2411             }\r
2412             this.isCleaned = true;\r
2413             return this;\r
2414         },\r
2415 \r
2416     \r
2417     scrollIntoView : function(container, hscroll){\r
2418         var c = Ext.getDom(container) || Ext.getBody().dom;\r
2419         var el = this.dom;\r
2420 \r
2421         var o = this.getOffsetsTo(c),\r
2422             l = o[0] + c.scrollLeft,\r
2423             t = o[1] + c.scrollTop,\r
2424             b = t+el.offsetHeight,\r
2425             r = l+el.offsetWidth;\r
2426 \r
2427         var ch = c.clientHeight;\r
2428         var ct = parseInt(c.scrollTop, 10);\r
2429         var cl = parseInt(c.scrollLeft, 10);\r
2430         var cb = ct + ch;\r
2431         var cr = cl + c.clientWidth;\r
2432 \r
2433         if(el.offsetHeight > ch || t < ct){\r
2434                 c.scrollTop = t;\r
2435         }else if(b > cb){\r
2436             c.scrollTop = b-ch;\r
2437         }\r
2438         c.scrollTop = c.scrollTop; // corrects IE, other browsers will ignore\r
2439 \r
2440         if(hscroll !== false){\r
2441                         if(el.offsetWidth > c.clientWidth || l < cl){\r
2442                 c.scrollLeft = l;\r
2443             }else if(r > cr){\r
2444                 c.scrollLeft = r-c.clientWidth;\r
2445             }\r
2446             c.scrollLeft = c.scrollLeft;\r
2447         }\r
2448         return this;\r
2449     },\r
2450 \r
2451     // private\r
2452     scrollChildIntoView : function(child, hscroll){\r
2453         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);\r
2454     },\r
2455 \r
2456     \r
2457     autoHeight : function(animate, duration, onComplete, easing){\r
2458         var oldHeight = this.getHeight();\r
2459         this.clip();\r
2460         this.setHeight(1); // force clipping\r
2461         setTimeout(function(){\r
2462             var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari\r
2463             if(!animate){\r
2464                 this.setHeight(height);\r
2465                 this.unclip();\r
2466                 if(typeof onComplete == "function"){\r
2467                     onComplete();\r
2468                 }\r
2469             }else{\r
2470                 this.setHeight(oldHeight); // restore original height\r
2471                 this.setHeight(height, animate, duration, function(){\r
2472                     this.unclip();\r
2473                     if(typeof onComplete == "function") onComplete();\r
2474                 }.createDelegate(this), easing);\r
2475             }\r
2476         }.createDelegate(this), 0);\r
2477         return this;\r
2478     },\r
2479 \r
2480     \r
2481     contains : function(el){\r
2482         if(!el){return false;}\r
2483         return D.isAncestor(this.dom, el.dom ? el.dom : el);\r
2484     },\r
2485 \r
2486     \r
2487     isVisible : function(deep) {\r
2488         var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");\r
2489         if(deep !== true || !vis){\r
2490             return vis;\r
2491         }\r
2492         var p = this.dom.parentNode;\r
2493         while(p && p.tagName.toLowerCase() != "body"){\r
2494             if(!Ext.fly(p, '_isVisible').isVisible()){\r
2495                 return false;\r
2496             }\r
2497             p = p.parentNode;\r
2498         }\r
2499         return true;\r
2500     },\r
2501 \r
2502     \r
2503     select : function(selector, unique){\r
2504         return El.select(selector, unique, this.dom);\r
2505     },\r
2506 \r
2507     \r
2508     query : function(selector){\r
2509         return Ext.DomQuery.select(selector, this.dom);\r
2510     },\r
2511 \r
2512     \r
2513     child : function(selector, returnDom){\r
2514         var n = Ext.DomQuery.selectNode(selector, this.dom);\r
2515         return returnDom ? n : Ext.get(n);\r
2516     },\r
2517 \r
2518     \r
2519     down : function(selector, returnDom){\r
2520         var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);\r
2521         return returnDom ? n : Ext.get(n);\r
2522     },\r
2523 \r
2524     \r
2525     initDD : function(group, config, overrides){\r
2526         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);\r
2527         return Ext.apply(dd, overrides);\r
2528     },\r
2529 \r
2530     \r
2531     initDDProxy : function(group, config, overrides){\r
2532         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);\r
2533         return Ext.apply(dd, overrides);\r
2534     },\r
2535 \r
2536     \r
2537     initDDTarget : function(group, config, overrides){\r
2538         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);\r
2539         return Ext.apply(dd, overrides);\r
2540     },\r
2541 \r
2542     \r
2543      setVisible : function(visible, animate){\r
2544         if(!animate || !A){\r
2545             if(this.visibilityMode == El.DISPLAY){\r
2546                 this.setDisplayed(visible);\r
2547             }else{\r
2548                 this.fixDisplay();\r
2549                 this.dom.style.visibility = visible ? "visible" : "hidden";\r
2550             }\r
2551         }else{\r
2552             // closure for composites\r
2553             var dom = this.dom;\r
2554             var visMode = this.visibilityMode;\r
2555             if(visible){\r
2556                 this.setOpacity(.01);\r
2557                 this.setVisible(true);\r
2558             }\r
2559             this.anim({opacity: { to: (visible?1:0) }},\r
2560                   this.preanim(arguments, 1),\r
2561                   null, .35, 'easeIn', function(){\r
2562                      if(!visible){\r
2563                          if(visMode == El.DISPLAY){\r
2564                              dom.style.display = "none";\r
2565                          }else{\r
2566                              dom.style.visibility = "hidden";\r
2567                          }\r
2568                          Ext.get(dom).setOpacity(1);\r
2569                      }\r
2570                  });\r
2571         }\r
2572         return this;\r
2573     },\r
2574 \r
2575     \r
2576     isDisplayed : function() {\r
2577         return this.getStyle("display") != "none";\r
2578     },\r
2579 \r
2580     \r
2581     toggle : function(animate){\r
2582         this.setVisible(!this.isVisible(), this.preanim(arguments, 0));\r
2583         return this;\r
2584     },\r
2585 \r
2586     \r
2587     setDisplayed : function(value) {\r
2588         if(typeof value == "boolean"){\r
2589            value = value ? this.originalDisplay : "none";\r
2590         }\r
2591         this.setStyle("display", value);\r
2592         return this;\r
2593     },\r
2594 \r
2595     \r
2596     focus : function() {\r
2597         try{\r
2598             this.dom.focus();\r
2599         }catch(e){}\r
2600         return this;\r
2601     },\r
2602 \r
2603     \r
2604     blur : function() {\r
2605         try{\r
2606             this.dom.blur();\r
2607         }catch(e){}\r
2608         return this;\r
2609     },\r
2610 \r
2611     \r
2612     addClass : function(className){\r
2613         if(Ext.isArray(className)){\r
2614             for(var i = 0, len = className.length; i < len; i++) {\r
2615                 this.addClass(className[i]);\r
2616             }\r
2617         }else{\r
2618             if(className && !this.hasClass(className)){\r
2619                 this.dom.className = this.dom.className + " " + className;\r
2620             }\r
2621         }\r
2622         return this;\r
2623     },\r
2624 \r
2625     \r
2626     radioClass : function(className){\r
2627         var siblings = this.dom.parentNode.childNodes;\r
2628         for(var i = 0; i < siblings.length; i++) {\r
2629                 var s = siblings[i];\r
2630                 if(s.nodeType == 1){\r
2631                     Ext.get(s).removeClass(className);\r
2632                 }\r
2633         }\r
2634         this.addClass(className);\r
2635         return this;\r
2636     },\r
2637 \r
2638     \r
2639     removeClass : function(className){\r
2640         if(!className || !this.dom.className){\r
2641             return this;\r
2642         }\r
2643         if(Ext.isArray(className)){\r
2644             for(var i = 0, len = className.length; i < len; i++) {\r
2645                 this.removeClass(className[i]);\r
2646             }\r
2647         }else{\r
2648             if(this.hasClass(className)){\r
2649                 var re = this.classReCache[className];\r
2650                 if (!re) {\r
2651                    re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");\r
2652                    this.classReCache[className] = re;\r
2653                 }\r
2654                 this.dom.className =\r
2655                     this.dom.className.replace(re, " ");\r
2656             }\r
2657         }\r
2658         return this;\r
2659     },\r
2660 \r
2661     // private\r
2662     classReCache: {},\r
2663 \r
2664     \r
2665     toggleClass : function(className){\r
2666         if(this.hasClass(className)){\r
2667             this.removeClass(className);\r
2668         }else{\r
2669             this.addClass(className);\r
2670         }\r
2671         return this;\r
2672     },\r
2673 \r
2674     \r
2675     hasClass : function(className){\r
2676         return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;\r
2677     },\r
2678 \r
2679     \r
2680     replaceClass : function(oldClassName, newClassName){\r
2681         this.removeClass(oldClassName);\r
2682         this.addClass(newClassName);\r
2683         return this;\r
2684     },\r
2685 \r
2686     \r
2687     getStyles : function(){\r
2688         var a = arguments, len = a.length, r = {};\r
2689         for(var i = 0; i < len; i++){\r
2690             r[a[i]] = this.getStyle(a[i]);\r
2691         }\r
2692         return r;\r
2693     },\r
2694 \r
2695     \r
2696     getStyle : function(){\r
2697         return view && view.getComputedStyle ?\r
2698             function(prop){\r
2699                 var el = this.dom, v, cs, camel;\r
2700                 if(prop == 'float'){\r
2701                     prop = "cssFloat";\r
2702                 }\r
2703                 if(v = el.style[prop]){\r
2704                     return v;\r
2705                 }\r
2706                 if(cs = view.getComputedStyle(el, "")){\r
2707                     if(!(camel = propCache[prop])){\r
2708                         camel = propCache[prop] = prop.replace(camelRe, camelFn);\r
2709                     }\r
2710                     return cs[camel];\r
2711                 }\r
2712                 return null;\r
2713             } :\r
2714             function(prop){\r
2715                 var el = this.dom, v, cs, camel;\r
2716                 if(prop == 'opacity'){\r
2717                     if(typeof el.style.filter == 'string'){\r
2718                         var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);\r
2719                         if(m){\r
2720                             var fv = parseFloat(m[1]);\r
2721                             if(!isNaN(fv)){\r
2722                                 return fv ? fv / 100 : 0;\r
2723                             }\r
2724                         }\r
2725                     }\r
2726                     return 1;\r
2727                 }else if(prop == 'float'){\r
2728                     prop = "styleFloat";\r
2729                 }\r
2730                 if(!(camel = propCache[prop])){\r
2731                     camel = propCache[prop] = prop.replace(camelRe, camelFn);\r
2732                 }\r
2733                 if(v = el.style[camel]){\r
2734                     return v;\r
2735                 }\r
2736                 if(cs = el.currentStyle){\r
2737                     return cs[camel];\r
2738                 }\r
2739                 return null;\r
2740             };\r
2741     }(),\r
2742 \r
2743     \r
2744     setStyle : function(prop, value){\r
2745         if(typeof prop == "string"){\r
2746             var camel;\r
2747             if(!(camel = propCache[prop])){\r
2748                 camel = propCache[prop] = prop.replace(camelRe, camelFn);\r
2749             }\r
2750             if(camel == 'opacity') {\r
2751                 this.setOpacity(value);\r
2752             }else{\r
2753                 this.dom.style[camel] = value;\r
2754             }\r
2755         }else{\r
2756             for(var style in prop){\r
2757                 if(typeof prop[style] != "function"){\r
2758                    this.setStyle(style, prop[style]);\r
2759                 }\r
2760             }\r
2761         }\r
2762         return this;\r
2763     },\r
2764 \r
2765     \r
2766     applyStyles : function(style){\r
2767         Ext.DomHelper.applyStyles(this.dom, style);\r
2768         return this;\r
2769     },\r
2770 \r
2771     \r
2772     getX : function(){\r
2773         return D.getX(this.dom);\r
2774     },\r
2775 \r
2776     \r
2777     getY : function(){\r
2778         return D.getY(this.dom);\r
2779     },\r
2780 \r
2781     \r
2782     getXY : function(){\r
2783         return D.getXY(this.dom);\r
2784     },\r
2785 \r
2786     \r
2787     getOffsetsTo : function(el){\r
2788         var o = this.getXY();\r
2789         var e = Ext.fly(el, '_internal').getXY();\r
2790         return [o[0]-e[0],o[1]-e[1]];\r
2791     },\r
2792 \r
2793     \r
2794     setX : function(x, animate){\r
2795         if(!animate || !A){\r
2796             D.setX(this.dom, x);\r
2797         }else{\r
2798             this.setXY([x, this.getY()], this.preanim(arguments, 1));\r
2799         }\r
2800         return this;\r
2801     },\r
2802 \r
2803     \r
2804     setY : function(y, animate){\r
2805         if(!animate || !A){\r
2806             D.setY(this.dom, y);\r
2807         }else{\r
2808             this.setXY([this.getX(), y], this.preanim(arguments, 1));\r
2809         }\r
2810         return this;\r
2811     },\r
2812 \r
2813     \r
2814     setLeft : function(left){\r
2815         this.setStyle("left", this.addUnits(left));\r
2816         return this;\r
2817     },\r
2818 \r
2819     \r
2820     setTop : function(top){\r
2821         this.setStyle("top", this.addUnits(top));\r
2822         return this;\r
2823     },\r
2824 \r
2825     \r
2826     setRight : function(right){\r
2827         this.setStyle("right", this.addUnits(right));\r
2828         return this;\r
2829     },\r
2830 \r
2831     \r
2832     setBottom : function(bottom){\r
2833         this.setStyle("bottom", this.addUnits(bottom));\r
2834         return this;\r
2835     },\r
2836 \r
2837     \r
2838     setXY : function(pos, animate){\r
2839         if(!animate || !A){\r
2840             D.setXY(this.dom, pos);\r
2841         }else{\r
2842             this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');\r
2843         }\r
2844         return this;\r
2845     },\r
2846 \r
2847     \r
2848     setLocation : function(x, y, animate){\r
2849         this.setXY([x, y], this.preanim(arguments, 2));\r
2850         return this;\r
2851     },\r
2852 \r
2853     \r
2854     moveTo : function(x, y, animate){\r
2855         this.setXY([x, y], this.preanim(arguments, 2));\r
2856         return this;\r
2857     },\r
2858 \r
2859     \r
2860     getRegion : function(){\r
2861         return D.getRegion(this.dom);\r
2862     },\r
2863 \r
2864     \r
2865     getHeight : function(contentHeight){\r
2866         var h = this.dom.offsetHeight || 0;\r
2867         h = contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");\r
2868         return h < 0 ? 0 : h;\r
2869     },\r
2870 \r
2871     \r
2872     getWidth : function(contentWidth){\r
2873         var w = this.dom.offsetWidth || 0;\r
2874         w = contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");\r
2875         return w < 0 ? 0 : w;\r
2876     },\r
2877 \r
2878     \r
2879     getComputedHeight : function(){\r
2880         var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);\r
2881         if(!h){\r
2882             h = parseInt(this.getStyle('height'), 10) || 0;\r
2883             if(!this.isBorderBox()){\r
2884                 h += this.getFrameWidth('tb');\r
2885             }\r
2886         }\r
2887         return h;\r
2888     },\r
2889 \r
2890     \r
2891     getComputedWidth : function(){\r
2892         var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);\r
2893         if(!w){\r
2894             w = parseInt(this.getStyle('width'), 10) || 0;\r
2895             if(!this.isBorderBox()){\r
2896                 w += this.getFrameWidth('lr');\r
2897             }\r
2898         }\r
2899         return w;\r
2900     },\r
2901 \r
2902     \r
2903     getSize : function(contentSize){\r
2904         return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};\r
2905     },\r
2906 \r
2907     getStyleSize : function(){\r
2908         var w, h, d = this.dom, s = d.style;\r
2909         if(s.width && s.width != 'auto'){\r
2910             w = parseInt(s.width, 10);\r
2911             if(Ext.isBorderBox){\r
2912                w -= this.getFrameWidth('lr');\r
2913             }\r
2914         }\r
2915         if(s.height && s.height != 'auto'){\r
2916             h = parseInt(s.height, 10);\r
2917             if(Ext.isBorderBox){\r
2918                h -= this.getFrameWidth('tb');\r
2919             }\r
2920         }\r
2921         return {width: w || this.getWidth(true), height: h || this.getHeight(true)};\r
2922 \r
2923     },\r
2924 \r
2925     \r
2926     getViewSize : function(){\r
2927         var d = this.dom, doc = document, aw = 0, ah = 0;\r
2928         if(d == doc || d == doc.body){\r
2929             return {width : D.getViewWidth(), height: D.getViewHeight()};\r
2930         }else{\r
2931             return {\r
2932                 width : d.clientWidth,\r
2933                 height: d.clientHeight\r
2934             };\r
2935         }\r
2936     },\r
2937 \r
2938     \r
2939     getValue : function(asNumber){\r
2940         return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;\r
2941     },\r
2942 \r
2943     // private\r
2944     adjustWidth : function(width){\r
2945         if(typeof width == "number"){\r
2946             if(this.autoBoxAdjust && !this.isBorderBox()){\r
2947                width -= (this.getBorderWidth("lr") + this.getPadding("lr"));\r
2948             }\r
2949             if(width < 0){\r
2950                 width = 0;\r
2951             }\r
2952         }\r
2953         return width;\r
2954     },\r
2955 \r
2956     // private\r
2957     adjustHeight : function(height){\r
2958         if(typeof height == "number"){\r
2959            if(this.autoBoxAdjust && !this.isBorderBox()){\r
2960                height -= (this.getBorderWidth("tb") + this.getPadding("tb"));\r
2961            }\r
2962            if(height < 0){\r
2963                height = 0;\r
2964            }\r
2965         }\r
2966         return height;\r
2967     },\r
2968 \r
2969     \r
2970     setWidth : function(width, animate){\r
2971         width = this.adjustWidth(width);\r
2972         if(!animate || !A){\r
2973             this.dom.style.width = this.addUnits(width);\r
2974         }else{\r
2975             this.anim({width: {to: width}}, this.preanim(arguments, 1));\r
2976         }\r
2977         return this;\r
2978     },\r
2979 \r
2980     \r
2981      setHeight : function(height, animate){\r
2982         height = this.adjustHeight(height);\r
2983         if(!animate || !A){\r
2984             this.dom.style.height = this.addUnits(height);\r
2985         }else{\r
2986             this.anim({height: {to: height}}, this.preanim(arguments, 1));\r
2987         }\r
2988         return this;\r
2989     },\r
2990 \r
2991     \r
2992      setSize : function(width, height, animate){\r
2993         if(typeof width == "object"){ // in case of object from getSize()\r
2994             height = width.height; width = width.width;\r
2995         }\r
2996         width = this.adjustWidth(width); height = this.adjustHeight(height);\r
2997         if(!animate || !A){\r
2998             this.dom.style.width = this.addUnits(width);\r
2999             this.dom.style.height = this.addUnits(height);\r
3000         }else{\r
3001             this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));\r
3002         }\r
3003         return this;\r
3004     },\r
3005 \r
3006     \r
3007     setBounds : function(x, y, width, height, animate){\r
3008         if(!animate || !A){\r
3009             this.setSize(width, height);\r
3010             this.setLocation(x, y);\r
3011         }else{\r
3012             width = this.adjustWidth(width); height = this.adjustHeight(height);\r
3013             this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},\r
3014                           this.preanim(arguments, 4), 'motion');\r
3015         }\r
3016         return this;\r
3017     },\r
3018 \r
3019     \r
3020     setRegion : function(region, animate){\r
3021         this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));\r
3022         return this;\r
3023     },\r
3024 \r
3025     \r
3026     addListener : function(eventName, fn, scope, options){\r
3027         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);\r
3028     },\r
3029 \r
3030     \r
3031     removeListener : function(eventName, fn, scope){\r
3032         Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);\r
3033         return this;\r
3034     },\r
3035 \r
3036     \r
3037     removeAllListeners : function(){\r
3038         Ext.EventManager.removeAll(this.dom);\r
3039         return this;\r
3040     },\r
3041 \r
3042     \r
3043     relayEvent : function(eventName, observable){\r
3044         this.on(eventName, function(e){\r
3045             observable.fireEvent(eventName, e);\r
3046         });\r
3047     },\r
3048 \r
3049     \r
3050      setOpacity : function(opacity, animate){\r
3051         if(!animate || !A){\r
3052             var s = this.dom.style;\r
3053             if(Ext.isIE){\r
3054                 s.zoom = 1;\r
3055                 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +\r
3056                            (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");\r
3057             }else{\r
3058                 s.opacity = opacity;\r
3059             }\r
3060         }else{\r
3061             this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');\r
3062         }\r
3063         return this;\r
3064     },\r
3065 \r
3066     \r
3067     getLeft : function(local){\r
3068         if(!local){\r
3069             return this.getX();\r
3070         }else{\r
3071             return parseInt(this.getStyle("left"), 10) || 0;\r
3072         }\r
3073     },\r
3074 \r
3075     \r
3076     getRight : function(local){\r
3077         if(!local){\r
3078             return this.getX() + this.getWidth();\r
3079         }else{\r
3080             return (this.getLeft(true) + this.getWidth()) || 0;\r
3081         }\r
3082     },\r
3083 \r
3084     \r
3085     getTop : function(local) {\r
3086         if(!local){\r
3087             return this.getY();\r
3088         }else{\r
3089             return parseInt(this.getStyle("top"), 10) || 0;\r
3090         }\r
3091     },\r
3092 \r
3093     \r
3094     getBottom : function(local){\r
3095         if(!local){\r
3096             return this.getY() + this.getHeight();\r
3097         }else{\r
3098             return (this.getTop(true) + this.getHeight()) || 0;\r
3099         }\r
3100     },\r
3101 \r
3102     \r
3103     position : function(pos, zIndex, x, y){\r
3104         if(!pos){\r
3105            if(this.getStyle('position') == 'static'){\r
3106                this.setStyle('position', 'relative');\r
3107            }\r
3108         }else{\r
3109             this.setStyle("position", pos);\r
3110         }\r
3111         if(zIndex){\r
3112             this.setStyle("z-index", zIndex);\r
3113         }\r
3114         if(x !== undefined && y !== undefined){\r
3115             this.setXY([x, y]);\r
3116         }else if(x !== undefined){\r
3117             this.setX(x);\r
3118         }else if(y !== undefined){\r
3119             this.setY(y);\r
3120         }\r
3121     },\r
3122 \r
3123     \r
3124     clearPositioning : function(value){\r
3125         value = value ||'';\r
3126         this.setStyle({\r
3127             "left": value,\r
3128             "right": value,\r
3129             "top": value,\r
3130             "bottom": value,\r
3131             "z-index": "",\r
3132             "position" : "static"\r
3133         });\r
3134         return this;\r
3135     },\r
3136 \r
3137     \r
3138     getPositioning : function(){\r
3139         var l = this.getStyle("left");\r
3140         var t = this.getStyle("top");\r
3141         return {\r
3142             "position" : this.getStyle("position"),\r
3143             "left" : l,\r
3144             "right" : l ? "" : this.getStyle("right"),\r
3145             "top" : t,\r
3146             "bottom" : t ? "" : this.getStyle("bottom"),\r
3147             "z-index" : this.getStyle("z-index")\r
3148         };\r
3149     },\r
3150 \r
3151     \r
3152     getBorderWidth : function(side){\r
3153         return this.addStyles(side, El.borders);\r
3154     },\r
3155 \r
3156     \r
3157     getPadding : function(side){\r
3158         return this.addStyles(side, El.paddings);\r
3159     },\r
3160 \r
3161     \r
3162     setPositioning : function(pc){\r
3163         this.applyStyles(pc);\r
3164         if(pc.right == "auto"){\r
3165             this.dom.style.right = "";\r
3166         }\r
3167         if(pc.bottom == "auto"){\r
3168             this.dom.style.bottom = "";\r
3169         }\r
3170         return this;\r
3171     },\r
3172 \r
3173     // private\r
3174     fixDisplay : function(){\r
3175         if(this.getStyle("display") == "none"){\r
3176             this.setStyle("visibility", "hidden");\r
3177             this.setStyle("display", this.originalDisplay); // first try reverting to default\r
3178             if(this.getStyle("display") == "none"){ // if that fails, default to block\r
3179                 this.setStyle("display", "block");\r
3180             }\r
3181         }\r
3182     },\r
3183 \r
3184     // private\r
3185         setOverflow : function(v){\r
3186         if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug\r
3187                 this.dom.style.overflow = 'hidden';\r
3188                 (function(){this.dom.style.overflow = 'auto';}).defer(1, this);\r
3189         }else{\r
3190                 this.dom.style.overflow = v;\r
3191         }\r
3192         },\r
3193 \r
3194     \r
3195      setLeftTop : function(left, top){\r
3196         this.dom.style.left = this.addUnits(left);\r
3197         this.dom.style.top = this.addUnits(top);\r
3198         return this;\r
3199     },\r
3200 \r
3201     \r
3202      move : function(direction, distance, animate){\r
3203         var xy = this.getXY();\r
3204         direction = direction.toLowerCase();\r
3205         switch(direction){\r
3206             case "l":\r
3207             case "left":\r
3208                 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));\r
3209                 break;\r
3210            case "r":\r
3211            case "right":\r
3212                 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));\r
3213                 break;\r
3214            case "t":\r
3215            case "top":\r
3216            case "up":\r
3217                 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));\r
3218                 break;\r
3219            case "b":\r
3220            case "bottom":\r
3221            case "down":\r
3222                 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));\r
3223                 break;\r
3224         }\r
3225         return this;\r
3226     },\r
3227 \r
3228     \r
3229     clip : function(){\r
3230         if(!this.isClipped){\r
3231            this.isClipped = true;\r
3232            this.originalClip = {\r
3233                "o": this.getStyle("overflow"),\r
3234                "x": this.getStyle("overflow-x"),\r
3235                "y": this.getStyle("overflow-y")\r
3236            };\r
3237            this.setStyle("overflow", "hidden");\r
3238            this.setStyle("overflow-x", "hidden");\r
3239            this.setStyle("overflow-y", "hidden");\r
3240         }\r
3241         return this;\r
3242     },\r
3243 \r
3244     \r
3245     unclip : function(){\r
3246         if(this.isClipped){\r
3247             this.isClipped = false;\r
3248             var o = this.originalClip;\r
3249             if(o.o){this.setStyle("overflow", o.o);}\r
3250             if(o.x){this.setStyle("overflow-x", o.x);}\r
3251             if(o.y){this.setStyle("overflow-y", o.y);}\r
3252         }\r
3253         return this;\r
3254     },\r
3255 \r
3256 \r
3257     \r
3258     getAnchorXY : function(anchor, local, s){\r
3259         //Passing a different size is useful for pre-calculating anchors,\r
3260         //especially for anchored animations that change the el size.\r
3261 \r
3262         var w, h, vp = false;\r
3263         if(!s){\r
3264             var d = this.dom;\r
3265             if(d == document.body || d == document){\r
3266                 vp = true;\r
3267                 w = D.getViewWidth(); h = D.getViewHeight();\r
3268             }else{\r
3269                 w = this.getWidth(); h = this.getHeight();\r
3270             }\r
3271         }else{\r
3272             w = s.width;  h = s.height;\r
3273         }\r
3274         var x = 0, y = 0, r = Math.round;\r
3275         switch((anchor || "tl").toLowerCase()){\r
3276             case "c":\r
3277                 x = r(w*.5);\r
3278                 y = r(h*.5);\r
3279             break;\r
3280             case "t":\r
3281                 x = r(w*.5);\r
3282                 y = 0;\r
3283             break;\r
3284             case "l":\r
3285                 x = 0;\r
3286                 y = r(h*.5);\r
3287             break;\r
3288             case "r":\r
3289                 x = w;\r
3290                 y = r(h*.5);\r
3291             break;\r
3292             case "b":\r
3293                 x = r(w*.5);\r
3294                 y = h;\r
3295             break;\r
3296             case "tl":\r
3297                 x = 0;\r
3298                 y = 0;\r
3299             break;\r
3300             case "bl":\r
3301                 x = 0;\r
3302                 y = h;\r
3303             break;\r
3304             case "br":\r
3305                 x = w;\r
3306                 y = h;\r
3307             break;\r
3308             case "tr":\r
3309                 x = w;\r
3310                 y = 0;\r
3311             break;\r
3312         }\r
3313         if(local === true){\r
3314             return [x, y];\r
3315         }\r
3316         if(vp){\r
3317             var sc = this.getScroll();\r
3318             return [x + sc.left, y + sc.top];\r
3319         }\r
3320         //Add the element's offset xy\r
3321         var o = this.getXY();\r
3322         return [x+o[0], y+o[1]];\r
3323     },\r
3324 \r
3325     \r
3326     getAlignToXY : function(el, p, o){\r
3327         el = Ext.get(el);\r
3328         if(!el || !el.dom){\r
3329             throw "Element.alignToXY with an element that doesn't exist";\r
3330         }\r
3331         var d = this.dom;\r
3332         var c = false; //constrain to viewport\r
3333         var p1 = "", p2 = "";\r
3334         o = o || [0,0];\r
3335 \r
3336         if(!p){\r
3337             p = "tl-bl";\r
3338         }else if(p == "?"){\r
3339             p = "tl-bl?";\r
3340         }else if(p.indexOf("-") == -1){\r
3341             p = "tl-" + p;\r
3342         }\r
3343         p = p.toLowerCase();\r
3344         var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);\r
3345         if(!m){\r
3346            throw "Element.alignTo with an invalid alignment " + p;\r
3347         }\r
3348         p1 = m[1]; p2 = m[2]; c = !!m[3];\r
3349 \r
3350         //Subtract the aligned el's internal xy from the target's offset xy\r
3351         //plus custom offset to get the aligned el's new offset xy\r
3352         var a1 = this.getAnchorXY(p1, true);\r
3353         var a2 = el.getAnchorXY(p2, false);\r
3354 \r
3355         var x = a2[0] - a1[0] + o[0];\r
3356         var y = a2[1] - a1[1] + o[1];\r
3357 \r
3358         if(c){\r
3359             //constrain the aligned el to viewport if necessary\r
3360             var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();\r
3361             // 5px of margin for ie\r
3362             var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;\r
3363 \r
3364             //If we are at a viewport boundary and the aligned el is anchored on a target border that is\r
3365             //perpendicular to the vp border, allow the aligned el to slide on that border,\r
3366             //otherwise swap the aligned el to the opposite border of the target.\r
3367             var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);\r
3368            var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);\r
3369            var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));\r
3370            var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));\r
3371 \r
3372            var doc = document;\r
3373            var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;\r
3374            var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;\r
3375 \r
3376            if((x+w) > dw + scrollX){\r
3377                 x = swapX ? r.left-w : dw+scrollX-w;\r
3378             }\r
3379            if(x < scrollX){\r
3380                x = swapX ? r.right : scrollX;\r
3381            }\r
3382            if((y+h) > dh + scrollY){\r
3383                 y = swapY ? r.top-h : dh+scrollY-h;\r
3384             }\r
3385            if (y < scrollY){\r
3386                y = swapY ? r.bottom : scrollY;\r
3387            }\r
3388         }\r
3389         return [x,y];\r
3390     },\r
3391 \r
3392     // private\r
3393     getConstrainToXY : function(){\r
3394         var os = {top:0, left:0, bottom:0, right: 0};\r
3395 \r
3396         return function(el, local, offsets, proposedXY){\r
3397             el = Ext.get(el);\r
3398             offsets = offsets ? Ext.applyIf(offsets, os) : os;\r
3399 \r
3400             var vw, vh, vx = 0, vy = 0;\r
3401             if(el.dom == document.body || el.dom == document){\r
3402                 vw = Ext.lib.Dom.getViewWidth();\r
3403                 vh = Ext.lib.Dom.getViewHeight();\r
3404             }else{\r
3405                 vw = el.dom.clientWidth;\r
3406                 vh = el.dom.clientHeight;\r
3407                 if(!local){\r
3408                     var vxy = el.getXY();\r
3409                     vx = vxy[0];\r
3410                     vy = vxy[1];\r
3411                 }\r
3412             }\r
3413 \r
3414             var s = el.getScroll();\r
3415 \r
3416             vx += offsets.left + s.left;\r
3417             vy += offsets.top + s.top;\r
3418 \r
3419             vw -= offsets.right;\r
3420             vh -= offsets.bottom;\r
3421 \r
3422             var vr = vx+vw;\r
3423             var vb = vy+vh;\r
3424 \r
3425             var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);\r
3426             var x = xy[0], y = xy[1];\r
3427             var w = this.dom.offsetWidth, h = this.dom.offsetHeight;\r
3428 \r
3429             // only move it if it needs it\r
3430             var moved = false;\r
3431 \r
3432             // first validate right/bottom\r
3433             if((x + w) > vr){\r
3434                 x = vr - w;\r
3435                 moved = true;\r
3436             }\r
3437             if((y + h) > vb){\r
3438                 y = vb - h;\r
3439                 moved = true;\r
3440             }\r
3441             // then make sure top/left isn't negative\r
3442             if(x < vx){\r
3443                 x = vx;\r
3444                 moved = true;\r
3445             }\r
3446             if(y < vy){\r
3447                 y = vy;\r
3448                 moved = true;\r
3449             }\r
3450             return moved ? [x, y] : false;\r
3451         };\r
3452     }(),\r
3453 \r
3454     // private\r
3455     adjustForConstraints : function(xy, parent, offsets){\r
3456         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;\r
3457     },\r
3458 \r
3459     \r
3460     alignTo : function(element, position, offsets, animate){\r
3461         var xy = this.getAlignToXY(element, position, offsets);\r
3462         this.setXY(xy, this.preanim(arguments, 3));\r
3463         return this;\r
3464     },\r
3465 \r
3466     \r
3467     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){\r
3468         var action = function(){\r
3469             this.alignTo(el, alignment, offsets, animate);\r
3470             Ext.callback(callback, this);\r
3471         };\r
3472         Ext.EventManager.onWindowResize(action, this);\r
3473         var tm = typeof monitorScroll;\r
3474         if(tm != 'undefined'){\r
3475             Ext.EventManager.on(window, 'scroll', action, this,\r
3476                 {buffer: tm == 'number' ? monitorScroll : 50});\r
3477         }\r
3478         action.call(this); // align immediately\r
3479         return this;\r
3480     },\r
3481     \r
3482     clearOpacity : function(){\r
3483         if (window.ActiveXObject) {\r
3484             if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){\r
3485                 this.dom.style.filter = "";\r
3486             }\r
3487         } else {\r
3488             this.dom.style.opacity = "";\r
3489             this.dom.style["-moz-opacity"] = "";\r
3490             this.dom.style["-khtml-opacity"] = "";\r
3491         }\r
3492         return this;\r
3493     },\r
3494 \r
3495     \r
3496     hide : function(animate){\r
3497         this.setVisible(false, this.preanim(arguments, 0));\r
3498         return this;\r
3499     },\r
3500 \r
3501     \r
3502     show : function(animate){\r
3503         this.setVisible(true, this.preanim(arguments, 0));\r
3504         return this;\r
3505     },\r
3506 \r
3507     \r
3508     addUnits : function(size){\r
3509         return Ext.Element.addUnits(size, this.defaultUnit);\r
3510     },\r
3511 \r
3512     \r
3513     update : function(html, loadScripts, callback){\r
3514         if(typeof html == "undefined"){\r
3515             html = "";\r
3516         }\r
3517         if(loadScripts !== true){\r
3518             this.dom.innerHTML = html;\r
3519             if(typeof callback == "function"){\r
3520                 callback();\r
3521             }\r
3522             return this;\r
3523         }\r
3524         var id = Ext.id();\r
3525         var dom = this.dom;\r
3526 \r
3527         html += '<span id="' + id + '"></span>';\r
3528 \r
3529         E.onAvailable(id, function(){\r
3530             var hd = document.getElementsByTagName("head")[0];\r
3531             var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;\r
3532             var srcRe = /\ssrc=([\'\"])(.*?)\1/i;\r
3533             var typeRe = /\stype=([\'\"])(.*?)\1/i;\r
3534 \r
3535             var match;\r
3536             while(match = re.exec(html)){\r
3537                 var attrs = match[1];\r
3538                 var srcMatch = attrs ? attrs.match(srcRe) : false;\r
3539                 if(srcMatch && srcMatch[2]){\r
3540                    var s = document.createElement("script");\r
3541                    s.src = srcMatch[2];\r
3542                    var typeMatch = attrs.match(typeRe);\r
3543                    if(typeMatch && typeMatch[2]){\r
3544                        s.type = typeMatch[2];\r
3545                    }\r
3546                    hd.appendChild(s);\r
3547                 }else if(match[2] && match[2].length > 0){\r
3548                     if(window.execScript) {\r
3549                        window.execScript(match[2]);\r
3550                     } else {\r
3551                        window.eval(match[2]);\r
3552                     }\r
3553                 }\r
3554             }\r
3555             var el = document.getElementById(id);\r
3556             if(el){Ext.removeNode(el);}\r
3557             if(typeof callback == "function"){\r
3558                 callback();\r
3559             }\r
3560         });\r
3561         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");\r
3562         return this;\r
3563     },\r
3564 \r
3565     \r
3566     load : function(){\r
3567         var um = this.getUpdater();\r
3568         um.update.apply(um, arguments);\r
3569         return this;\r
3570     },\r
3571 \r
3572     \r
3573     getUpdater : function(){\r
3574         if(!this.updateManager){\r
3575             this.updateManager = new Ext.Updater(this);\r
3576         }\r
3577         return this.updateManager;\r
3578     },\r
3579 \r
3580     \r
3581     unselectable : function(){\r
3582         this.dom.unselectable = "on";\r
3583         this.swallowEvent("selectstart", true);\r
3584         this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");\r
3585         this.addClass("x-unselectable");\r
3586         return this;\r
3587     },\r
3588 \r
3589     \r
3590     getCenterXY : function(){\r
3591         return this.getAlignToXY(document, 'c-c');\r
3592     },\r
3593 \r
3594     \r
3595     center : function(centerIn){\r
3596         this.alignTo(centerIn || document, 'c-c');\r
3597         return this;\r
3598     },\r
3599 \r
3600     \r
3601     isBorderBox : function(){\r
3602         return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;\r
3603     },\r
3604 \r
3605     \r
3606     getBox : function(contentBox, local){\r
3607         var xy;\r
3608         if(!local){\r
3609             xy = this.getXY();\r
3610         }else{\r
3611             var left = parseInt(this.getStyle("left"), 10) || 0;\r
3612             var top = parseInt(this.getStyle("top"), 10) || 0;\r
3613             xy = [left, top];\r
3614         }\r
3615         var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;\r
3616         if(!contentBox){\r
3617             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};\r
3618         }else{\r
3619             var l = this.getBorderWidth("l")+this.getPadding("l");\r
3620             var r = this.getBorderWidth("r")+this.getPadding("r");\r
3621             var t = this.getBorderWidth("t")+this.getPadding("t");\r
3622             var b = this.getBorderWidth("b")+this.getPadding("b");\r
3623             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)};\r
3624         }\r
3625         bx.right = bx.x + bx.width;\r
3626         bx.bottom = bx.y + bx.height;\r
3627         return bx;\r
3628     },\r
3629 \r
3630     \r
3631     getFrameWidth : function(sides, onlyContentBox){\r
3632         return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));\r
3633     },\r
3634 \r
3635     \r
3636     setBox : function(box, adjust, animate){\r
3637         var w = box.width, h = box.height;\r
3638         if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){\r
3639            w -= (this.getBorderWidth("lr") + this.getPadding("lr"));\r
3640            h -= (this.getBorderWidth("tb") + this.getPadding("tb"));\r
3641         }\r
3642         this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));\r
3643         return this;\r
3644     },\r
3645 \r
3646     \r
3647      repaint : function(){\r
3648         var dom = this.dom;\r
3649         this.addClass("x-repaint");\r
3650         setTimeout(function(){\r
3651             Ext.get(dom).removeClass("x-repaint");\r
3652         }, 1);\r
3653         return this;\r
3654     },\r
3655 \r
3656     \r
3657     getMargins : function(side){\r
3658         if(!side){\r
3659             return {\r
3660                 top: parseInt(this.getStyle("margin-top"), 10) || 0,\r
3661                 left: parseInt(this.getStyle("margin-left"), 10) || 0,\r
3662                 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,\r
3663                 right: parseInt(this.getStyle("margin-right"), 10) || 0\r
3664             };\r
3665         }else{\r
3666             return this.addStyles(side, El.margins);\r
3667          }\r
3668     },\r
3669 \r
3670     // private\r
3671     addStyles : function(sides, styles){\r
3672         var val = 0, v, w;\r
3673         for(var i = 0, len = sides.length; i < len; i++){\r
3674             v = this.getStyle(styles[sides.charAt(i)]);\r
3675             if(v){\r
3676                  w = parseInt(v, 10);\r
3677                  if(w){ val += (w >= 0 ? w : -1 * w); }\r
3678             }\r
3679         }\r
3680         return val;\r
3681     },\r
3682 \r
3683     \r
3684     createProxy : function(config, renderTo, matchBox){\r
3685         config = typeof config == "object" ?\r
3686             config : {tag : "div", cls: config};\r
3687 \r
3688         var proxy;\r
3689         if(renderTo){\r
3690             proxy = Ext.DomHelper.append(renderTo, config, true);\r
3691         }else {\r
3692             proxy = Ext.DomHelper.insertBefore(this.dom, config, true);\r
3693         }\r
3694         if(matchBox){\r
3695            proxy.setBox(this.getBox());\r
3696         }\r
3697         return proxy;\r
3698     },\r
3699 \r
3700     \r
3701     mask : function(msg, msgCls){\r
3702         if(this.getStyle("position") == "static"){\r
3703             this.addClass("x-masked-relative");\r
3704         }\r
3705         if(this._maskMsg){\r
3706             this._maskMsg.remove();\r
3707         }\r
3708         if(this._mask){\r
3709             this._mask.remove();\r
3710         }\r
3711 \r
3712         this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);\r
3713 \r
3714         this.addClass("x-masked");\r
3715         this._mask.setDisplayed(true);\r
3716         if(typeof msg == 'string'){\r
3717             this._maskMsg = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask-msg", cn:{tag:'div'}}, true);\r
3718             var mm = this._maskMsg;\r
3719             mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls : "ext-el-mask-msg";\r
3720             mm.dom.firstChild.innerHTML = msg;\r
3721             mm.setDisplayed(true);\r
3722             mm.center(this);\r
3723         }\r
3724         if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically\r
3725             this._mask.setSize(this.getWidth(), this.getHeight());\r
3726         }\r
3727         return this._mask;\r
3728     },\r
3729 \r
3730     \r
3731     unmask : function(){\r
3732         if(this._mask){\r
3733             if(this._maskMsg){\r
3734                 this._maskMsg.remove();\r
3735                 delete this._maskMsg;\r
3736             }\r
3737             this._mask.remove();\r
3738             delete this._mask;\r
3739         }\r
3740         this.removeClass(["x-masked", "x-masked-relative"]);\r
3741     },\r
3742 \r
3743     \r
3744     isMasked : function(){\r
3745         return this._mask && this._mask.isVisible();\r
3746     },\r
3747 \r
3748     \r
3749     createShim : function(){\r
3750         var el = document.createElement('iframe');\r
3751         el.frameBorder = '0';\r
3752         el.className = 'ext-shim';\r
3753         if(Ext.isIE && Ext.isSecure){\r
3754             el.src = Ext.SSL_SECURE_URL;\r
3755         }\r
3756         var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));\r
3757         shim.autoBoxAdjust = false;\r
3758         return shim;\r
3759     },\r
3760 \r
3761     \r
3762     remove : function(){\r
3763         Ext.removeNode(this.dom);\r
3764         delete El.cache[this.dom.id];\r
3765     },\r
3766 \r
3767     \r
3768     hover : function(overFn, outFn, scope){\r
3769         var preOverFn = function(e){\r
3770             if(!e.within(this, true)){\r
3771                 overFn.apply(scope || this, arguments);\r
3772             }\r
3773         };\r
3774         var preOutFn = function(e){\r
3775             if(!e.within(this, true)){\r
3776                 outFn.apply(scope || this, arguments);\r
3777             }\r
3778         };\r
3779         this.on("mouseover", preOverFn, this.dom);\r
3780         this.on("mouseout", preOutFn, this.dom);\r
3781         return this;\r
3782     },\r
3783 \r
3784     \r
3785     addClassOnOver : function(className){\r
3786         this.hover(\r
3787             function(){\r
3788                 Ext.fly(this, '_internal').addClass(className);\r
3789             },\r
3790             function(){\r
3791                 Ext.fly(this, '_internal').removeClass(className);\r
3792             }\r
3793         );\r
3794         return this;\r
3795     },\r
3796 \r
3797     \r
3798     addClassOnFocus : function(className){\r
3799         this.on("focus", function(){\r
3800             Ext.fly(this, '_internal').addClass(className);\r
3801         }, this.dom);\r
3802         this.on("blur", function(){\r
3803             Ext.fly(this, '_internal').removeClass(className);\r
3804         }, this.dom);\r
3805         return this;\r
3806     },\r
3807     \r
3808     addClassOnClick : function(className){\r
3809         var dom = this.dom;\r
3810         this.on("mousedown", function(){\r
3811             Ext.fly(dom, '_internal').addClass(className);\r
3812             var d = Ext.getDoc();\r
3813             var fn = function(){\r
3814                 Ext.fly(dom, '_internal').removeClass(className);\r
3815                 d.removeListener("mouseup", fn);\r
3816             };\r
3817             d.on("mouseup", fn);\r
3818         });\r
3819         return this;\r
3820     },\r
3821 \r
3822     \r
3823     swallowEvent : function(eventName, preventDefault){\r
3824         var fn = function(e){\r
3825             e.stopPropagation();\r
3826             if(preventDefault){\r
3827                 e.preventDefault();\r
3828             }\r
3829         };\r
3830         if(Ext.isArray(eventName)){\r
3831             for(var i = 0, len = eventName.length; i < len; i++){\r
3832                  this.on(eventName[i], fn);\r
3833             }\r
3834             return this;\r
3835         }\r
3836         this.on(eventName, fn);\r
3837         return this;\r
3838     },\r
3839 \r
3840     \r
3841     parent : function(selector, returnDom){\r
3842         return this.matchNode('parentNode', 'parentNode', selector, returnDom);\r
3843     },\r
3844 \r
3845      \r
3846     next : function(selector, returnDom){\r
3847         return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);\r
3848     },\r
3849 \r
3850     \r
3851     prev : function(selector, returnDom){\r
3852         return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);\r
3853     },\r
3854 \r
3855 \r
3856     \r
3857     first : function(selector, returnDom){\r
3858         return this.matchNode('nextSibling', 'firstChild', selector, returnDom);\r
3859     },\r
3860 \r
3861     \r
3862     last : function(selector, returnDom){\r
3863         return this.matchNode('previousSibling', 'lastChild', selector, returnDom);\r
3864     },\r
3865 \r
3866     matchNode : function(dir, start, selector, returnDom){\r
3867         var n = this.dom[start];\r
3868         while(n){\r
3869             if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){\r
3870                 return !returnDom ? Ext.get(n) : n;\r
3871             }\r
3872             n = n[dir];\r
3873         }\r
3874         return null;\r
3875     },\r
3876 \r
3877     \r
3878     appendChild: function(el){\r
3879         el = Ext.get(el);\r
3880         el.appendTo(this);\r
3881         return this;\r
3882     },\r
3883 \r
3884     \r
3885     createChild: function(config, insertBefore, returnDom){\r
3886         config = config || {tag:'div'};\r
3887         if(insertBefore){\r
3888             return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);\r
3889         }\r
3890         return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);\r
3891     },\r
3892 \r
3893     \r
3894     appendTo: function(el){\r
3895         el = Ext.getDom(el);\r
3896         el.appendChild(this.dom);\r
3897         return this;\r
3898     },\r
3899 \r
3900     \r
3901     insertBefore: function(el){\r
3902         el = Ext.getDom(el);\r
3903         el.parentNode.insertBefore(this.dom, el);\r
3904         return this;\r
3905     },\r
3906 \r
3907     \r
3908     insertAfter: function(el){\r
3909         el = Ext.getDom(el);\r
3910         el.parentNode.insertBefore(this.dom, el.nextSibling);\r
3911         return this;\r
3912     },\r
3913 \r
3914     \r
3915     insertFirst: function(el, returnDom){\r
3916         el = el || {};\r
3917         if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config\r
3918             return this.createChild(el, this.dom.firstChild, returnDom);\r
3919         }else{\r
3920             el = Ext.getDom(el);\r
3921             this.dom.insertBefore(el, this.dom.firstChild);\r
3922             return !returnDom ? Ext.get(el) : el;\r
3923         }\r
3924     },\r
3925 \r
3926     \r
3927     insertSibling: function(el, where, returnDom){\r
3928         var rt;\r
3929         if(Ext.isArray(el)){\r
3930             for(var i = 0, len = el.length; i < len; i++){\r
3931                 rt = this.insertSibling(el[i], where, returnDom);\r
3932             }\r
3933             return rt;\r
3934         }\r
3935         where = where ? where.toLowerCase() : 'before';\r
3936         el = el || {};\r
3937         var refNode = where == 'before' ? this.dom : this.dom.nextSibling;\r
3938 \r
3939         if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config\r
3940             if(where == 'after' && !this.dom.nextSibling){\r
3941                 rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);\r
3942             }else{\r
3943                 rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);\r
3944             }\r
3945 \r
3946         }else{\r
3947             rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);\r
3948             if(!returnDom){\r
3949                 rt = Ext.get(rt);\r
3950             }\r
3951         }\r
3952         return rt;\r
3953     },\r
3954 \r
3955     \r
3956     wrap: function(config, returnDom){\r
3957         if(!config){\r
3958             config = {tag: "div"};\r
3959         }\r
3960         var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);\r
3961         newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);\r
3962         return newEl;\r
3963     },\r
3964 \r
3965     \r
3966     replace: function(el){\r
3967         el = Ext.get(el);\r
3968         this.insertBefore(el);\r
3969         el.remove();\r
3970         return this;\r
3971     },\r
3972 \r
3973     \r
3974     replaceWith: function(el){\r
3975         if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config\r
3976             el = this.insertSibling(el, 'before');\r
3977         }else{\r
3978             el = Ext.getDom(el);\r
3979             this.dom.parentNode.insertBefore(el, this.dom);\r
3980         }\r
3981         El.uncache(this.id);\r
3982         Ext.removeNode(this.dom);\r
3983         this.dom = el;\r
3984         this.id = Ext.id(el);\r
3985         El.cache[this.id] = this;\r
3986         return this;\r
3987     },\r
3988 \r
3989     \r
3990     insertHtml : function(where, html, returnEl){\r
3991         var el = Ext.DomHelper.insertHtml(where, this.dom, html);\r
3992         return returnEl ? Ext.get(el) : el;\r
3993     },\r
3994 \r
3995     \r
3996     set : function(o, useSet){\r
3997         var el = this.dom;\r
3998         useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;\r
3999         for(var attr in o){\r
4000             if(attr == "style" || typeof o[attr] == "function") continue;\r
4001             if(attr=="cls"){\r
4002                 el.className = o["cls"];\r
4003             }else if(o.hasOwnProperty(attr)){\r
4004                 if(useSet) el.setAttribute(attr, o[attr]);\r
4005                 else el[attr] = o[attr];\r
4006             }\r
4007         }\r
4008         if(o.style){\r
4009             Ext.DomHelper.applyStyles(el, o.style);\r
4010         }\r
4011         return this;\r
4012     },\r
4013 \r
4014     \r
4015     addKeyListener : function(key, fn, scope){\r
4016         var config;\r
4017         if(typeof key != "object" || Ext.isArray(key)){\r
4018             config = {\r
4019                 key: key,\r
4020                 fn: fn,\r
4021                 scope: scope\r
4022             };\r
4023         }else{\r
4024             config = {\r
4025                 key : key.key,\r
4026                 shift : key.shift,\r
4027                 ctrl : key.ctrl,\r
4028                 alt : key.alt,\r
4029                 fn: fn,\r
4030                 scope: scope\r
4031             };\r
4032         }\r
4033         return new Ext.KeyMap(this, config);\r
4034     },\r
4035 \r
4036     \r
4037     addKeyMap : function(config){\r
4038         return new Ext.KeyMap(this, config);\r
4039     },\r
4040 \r
4041     \r
4042      isScrollable : function(){\r
4043         var dom = this.dom;\r
4044         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;\r
4045     },\r
4046 \r
4047     \r
4048     scrollTo : function(side, value, animate){\r
4049         var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";\r
4050         if(!animate || !A){\r
4051             this.dom[prop] = value;\r
4052         }else{\r
4053             var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];\r
4054             this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');\r
4055         }\r
4056         return this;\r
4057     },\r
4058 \r
4059     \r
4060      scroll : function(direction, distance, animate){\r
4061          if(!this.isScrollable()){\r
4062              return;\r
4063          }\r
4064          var el = this.dom;\r
4065          var l = el.scrollLeft, t = el.scrollTop;\r
4066          var w = el.scrollWidth, h = el.scrollHeight;\r
4067          var cw = el.clientWidth, ch = el.clientHeight;\r
4068          direction = direction.toLowerCase();\r
4069          var scrolled = false;\r
4070          var a = this.preanim(arguments, 2);\r
4071          switch(direction){\r
4072              case "l":\r
4073              case "left":\r
4074                  if(w - l > cw){\r
4075                      var v = Math.min(l + distance, w-cw);\r
4076                      this.scrollTo("left", v, a);\r
4077                      scrolled = true;\r
4078                  }\r
4079                  break;\r
4080             case "r":\r
4081             case "right":\r
4082                  if(l > 0){\r
4083                      var v = Math.max(l - distance, 0);\r
4084                      this.scrollTo("left", v, a);\r
4085                      scrolled = true;\r
4086                  }\r
4087                  break;\r
4088             case "t":\r
4089             case "top":\r
4090             case "up":\r
4091                  if(t > 0){\r
4092                      var v = Math.max(t - distance, 0);\r
4093                      this.scrollTo("top", v, a);\r
4094                      scrolled = true;\r
4095                  }\r
4096                  break;\r
4097             case "b":\r
4098             case "bottom":\r
4099             case "down":\r
4100                  if(h - t > ch){\r
4101                      var v = Math.min(t + distance, h-ch);\r
4102                      this.scrollTo("top", v, a);\r
4103                      scrolled = true;\r
4104                  }\r
4105                  break;\r
4106          }\r
4107          return scrolled;\r
4108     },\r
4109 \r
4110     \r
4111     translatePoints : function(x, y){\r
4112         if(typeof x == 'object' || Ext.isArray(x)){\r
4113             y = x[1]; x = x[0];\r
4114         }\r
4115         var p = this.getStyle('position');\r
4116         var o = this.getXY();\r
4117 \r
4118         var l = parseInt(this.getStyle('left'), 10);\r
4119         var t = parseInt(this.getStyle('top'), 10);\r
4120 \r
4121         if(isNaN(l)){\r
4122             l = (p == "relative") ? 0 : this.dom.offsetLeft;\r
4123         }\r
4124         if(isNaN(t)){\r
4125             t = (p == "relative") ? 0 : this.dom.offsetTop;\r
4126         }\r
4127 \r
4128         return {left: (x - o[0] + l), top: (y - o[1] + t)};\r
4129     },\r
4130 \r
4131     \r
4132     getScroll : function(){\r
4133         var d = this.dom, doc = document;\r
4134         if(d == doc || d == doc.body){\r
4135             var l, t;\r
4136             if(Ext.isIE && Ext.isStrict){\r
4137                 l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);\r
4138                 t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);\r
4139             }else{\r
4140                 l = window.pageXOffset || (doc.body.scrollLeft || 0);\r
4141                 t = window.pageYOffset || (doc.body.scrollTop || 0);\r
4142             }\r
4143             return {left: l, top: t};\r
4144         }else{\r
4145             return {left: d.scrollLeft, top: d.scrollTop};\r
4146         }\r
4147     },\r
4148 \r
4149     \r
4150     getColor : function(attr, defaultValue, prefix){\r
4151         var v = this.getStyle(attr);\r
4152         if(!v || v == "transparent" || v == "inherit") {\r
4153             return defaultValue;\r
4154         }\r
4155         var color = typeof prefix == "undefined" ? "#" : prefix;\r
4156         if(v.substr(0, 4) == "rgb("){\r
4157             var rvs = v.slice(4, v.length -1).split(",");\r
4158             for(var i = 0; i < 3; i++){\r
4159                 var h = parseInt(rvs[i]);\r
4160                 var s = h.toString(16);\r
4161                 if(h < 16){\r
4162                     s = "0" + s;\r
4163                 }\r
4164                 color += s;\r
4165             }\r
4166         } else {\r
4167             if(v.substr(0, 1) == "#"){\r
4168                 if(v.length == 4) {\r
4169                     for(var i = 1; i < 4; i++){\r
4170                         var c = v.charAt(i);\r
4171                         color +=  c + c;\r
4172                     }\r
4173                 }else if(v.length == 7){\r
4174                     color += v.substr(1);\r
4175                 }\r
4176             }\r
4177         }\r
4178         return(color.length > 5 ? color.toLowerCase() : defaultValue);\r
4179     },\r
4180 \r
4181     \r
4182     boxWrap : function(cls){\r
4183         cls = cls || 'x-box';\r
4184         var el = Ext.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));\r
4185         el.child('.'+cls+'-mc').dom.appendChild(this.dom);\r
4186         return el;\r
4187     },\r
4188 \r
4189     \r
4190     getAttributeNS : Ext.isIE ? function(ns, name){\r
4191         var d = this.dom;\r
4192         var type = typeof d[ns+":"+name];\r
4193         if(type != 'undefined' && type != 'unknown'){\r
4194             return d[ns+":"+name];\r
4195         }\r
4196         return d[name];\r
4197     } : function(ns, name){\r
4198         var d = this.dom;\r
4199         return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];\r
4200     },\r
4201 \r
4202     \r
4203     getTextWidth : function(text, min, max){\r
4204         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);\r
4205     }\r
4206 };\r
4207 \r
4208 var ep = El.prototype;\r
4209 \r
4210 \r
4211 ep.on = ep.addListener;\r
4212     // backwards compat\r
4213 ep.mon = ep.addListener;\r
4214 \r
4215 ep.getUpdateManager = ep.getUpdater;\r
4216 \r
4217 \r
4218 ep.un = ep.removeListener;\r
4219 \r
4220 \r
4221 ep.autoBoxAdjust = true;\r
4222 \r
4223 // private\r
4224 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;\r
4225 \r
4226 // private\r
4227 El.addUnits = function(v, defaultUnit){\r
4228     if(v === "" || v == "auto"){\r
4229         return v;\r
4230     }\r
4231     if(v === undefined){\r
4232         return '';\r
4233     }\r
4234     if(typeof v == "number" || !El.unitPattern.test(v)){\r
4235         return v + (defaultUnit || 'px');\r
4236     }\r
4237     return v;\r
4238 };\r
4239 \r
4240 // special markup used throughout Ext when box wrapping elements\r
4241 El.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>';\r
4242 \r
4243 El.VISIBILITY = 1;\r
4244 \r
4245 El.DISPLAY = 2;\r
4246 \r
4247 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};\r
4248 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};\r
4249 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};\r
4250 \r
4251 \r
4252 \r
4253 \r
4254 El.cache = {};\r
4255 \r
4256 var docEl;\r
4257 \r
4258 \r
4259 El.get = function(el){\r
4260     var ex, elm, id;\r
4261     if(!el){ return null; }\r
4262     if(typeof el == "string"){ // element id\r
4263         if(!(elm = document.getElementById(el))){\r
4264             return null;\r
4265         }\r
4266         if(ex = El.cache[el]){\r
4267             ex.dom = elm;\r
4268         }else{\r
4269             ex = El.cache[el] = new El(elm);\r
4270         }\r
4271         return ex;\r
4272     }else if(el.tagName){ // dom element\r
4273         if(!(id = el.id)){\r
4274             id = Ext.id(el);\r
4275         }\r
4276         if(ex = El.cache[id]){\r
4277             ex.dom = el;\r
4278         }else{\r
4279             ex = El.cache[id] = new El(el);\r
4280         }\r
4281         return ex;\r
4282     }else if(el instanceof El){\r
4283         if(el != docEl){\r
4284             el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,\r
4285                                                           // catch case where it hasn't been appended\r
4286             El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it\r
4287         }\r
4288         return el;\r
4289     }else if(el.isComposite){\r
4290         return el;\r
4291     }else if(Ext.isArray(el)){\r
4292         return El.select(el);\r
4293     }else if(el == document){\r
4294         // create a bogus element object representing the document object\r
4295         if(!docEl){\r
4296             var f = function(){};\r
4297             f.prototype = El.prototype;\r
4298             docEl = new f();\r
4299             docEl.dom = document;\r
4300         }\r
4301         return docEl;\r
4302     }\r
4303     return null;\r
4304 };\r
4305 \r
4306 // private\r
4307 El.uncache = function(el){\r
4308     for(var i = 0, a = arguments, len = a.length; i < len; i++) {\r
4309         if(a[i]){\r
4310             delete El.cache[a[i].id || a[i]];\r
4311         }\r
4312     }\r
4313 };\r
4314 \r
4315 // private\r
4316 // Garbage collection - uncache elements/purge listeners on orphaned elements\r
4317 // so we don't hold a reference and cause the browser to retain them\r
4318 El.garbageCollect = function(){\r
4319     if(!Ext.enableGarbageCollector){\r
4320         clearInterval(El.collectorThread);\r
4321         return;\r
4322     }\r
4323     for(var eid in El.cache){\r
4324         var el = El.cache[eid], d = el.dom;\r
4325         // -------------------------------------------------------\r
4326         // Determining what is garbage:\r
4327         // -------------------------------------------------------\r
4328         // !d\r
4329         // dom node is null, definitely garbage\r
4330         // -------------------------------------------------------\r
4331         // !d.parentNode\r
4332         // no parentNode == direct orphan, definitely garbage\r
4333         // -------------------------------------------------------\r
4334         // !d.offsetParent && !document.getElementById(eid)\r
4335         // display none elements have no offsetParent so we will\r
4336         // also try to look it up by it's id. However, check\r
4337         // offsetParent first so we don't do unneeded lookups.\r
4338         // This enables collection of elements that are not orphans\r
4339         // directly, but somewhere up the line they have an orphan\r
4340         // parent.\r
4341         // -------------------------------------------------------\r
4342         if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){\r
4343             delete El.cache[eid];\r
4344             if(d && Ext.enableListenerCollection){\r
4345                 Ext.EventManager.removeAll(d);\r
4346             }\r
4347         }\r
4348     }\r
4349 }\r
4350 El.collectorThreadId = setInterval(El.garbageCollect, 30000);\r
4351 \r
4352 var flyFn = function(){};\r
4353 flyFn.prototype = El.prototype;\r
4354 var _cls = new flyFn();\r
4355 \r
4356 // dom is optional\r
4357 El.Flyweight = function(dom){\r
4358     this.dom = dom;\r
4359 };\r
4360 \r
4361 El.Flyweight.prototype = _cls;\r
4362 El.Flyweight.prototype.isFlyweight = true;\r
4363 \r
4364 El._flyweights = {};\r
4365 \r
4366 El.fly = function(el, named){\r
4367     named = named || '_global';\r
4368     el = Ext.getDom(el);\r
4369     if(!el){\r
4370         return null;\r
4371     }\r
4372     if(!El._flyweights[named]){\r
4373         El._flyweights[named] = new El.Flyweight();\r
4374     }\r
4375     El._flyweights[named].dom = el;\r
4376     return El._flyweights[named];\r
4377 };\r
4378 \r
4379 \r
4380 Ext.get = El.get;\r
4381 \r
4382 Ext.fly = El.fly;\r
4383 \r
4384 // speedy lookup for elements never to box adjust\r
4385 var noBoxAdjust = Ext.isStrict ? {\r
4386     select:1\r
4387 } : {\r
4388     input:1, select:1, textarea:1\r
4389 };\r
4390 if(Ext.isIE || Ext.isGecko){\r
4391     noBoxAdjust['button'] = 1;\r
4392 }\r
4393 \r
4394 \r
4395 Ext.EventManager.on(window, 'unload', function(){\r
4396     delete El.cache;\r
4397     delete El._flyweights;\r
4398 });\r
4399 })();\r
4400 \r
4401 //Notifies Element that fx methods are available\r
4402 Ext.enableFx = true;\r
4403 \r
4404 \r
4405 Ext.Fx = {\r
4406         \r
4407     slideIn : function(anchor, o){\r
4408         var el = this.getFxEl();\r
4409         o = o || {};\r
4410 \r
4411         el.queueFx(o, function(){\r
4412 \r
4413             anchor = anchor || "t";\r
4414 \r
4415             // fix display to visibility\r
4416             this.fixDisplay();\r
4417 \r
4418             // restore values after effect\r
4419             var r = this.getFxRestore();\r
4420             var b = this.getBox();\r
4421             // fixed size for slide\r
4422             this.setSize(b);\r
4423 \r
4424             // wrap if needed\r
4425             var wrap = this.fxWrap(r.pos, o, "hidden");\r
4426 \r
4427             var st = this.dom.style;\r
4428             st.visibility = "visible";\r
4429             st.position = "absolute";\r
4430 \r
4431             // clear out temp styles after slide and unwrap\r
4432             var after = function(){\r
4433                 el.fxUnwrap(wrap, r.pos, o);\r
4434                 st.width = r.width;\r
4435                 st.height = r.height;\r
4436                 el.afterFx(o);\r
4437             };\r
4438             // time to calc the positions\r
4439             var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};\r
4440 \r
4441             switch(anchor.toLowerCase()){\r
4442                 case "t":\r
4443                     wrap.setSize(b.width, 0);\r
4444                     st.left = st.bottom = "0";\r
4445                     a = {height: bh};\r
4446                 break;\r
4447                 case "l":\r
4448                     wrap.setSize(0, b.height);\r
4449                     st.right = st.top = "0";\r
4450                     a = {width: bw};\r
4451                 break;\r
4452                 case "r":\r
4453                     wrap.setSize(0, b.height);\r
4454                     wrap.setX(b.right);\r
4455                     st.left = st.top = "0";\r
4456                     a = {width: bw, points: pt};\r
4457                 break;\r
4458                 case "b":\r
4459                     wrap.setSize(b.width, 0);\r
4460                     wrap.setY(b.bottom);\r
4461                     st.left = st.top = "0";\r
4462                     a = {height: bh, points: pt};\r
4463                 break;\r
4464                 case "tl":\r
4465                     wrap.setSize(0, 0);\r
4466                     st.right = st.bottom = "0";\r
4467                     a = {width: bw, height: bh};\r
4468                 break;\r
4469                 case "bl":\r
4470                     wrap.setSize(0, 0);\r
4471                     wrap.setY(b.y+b.height);\r
4472                     st.right = st.top = "0";\r
4473                     a = {width: bw, height: bh, points: pt};\r
4474                 break;\r
4475                 case "br":\r
4476                     wrap.setSize(0, 0);\r
4477                     wrap.setXY([b.right, b.bottom]);\r
4478                     st.left = st.top = "0";\r
4479                     a = {width: bw, height: bh, points: pt};\r
4480                 break;\r
4481                 case "tr":\r
4482                     wrap.setSize(0, 0);\r
4483                     wrap.setX(b.x+b.width);\r
4484                     st.left = st.bottom = "0";\r
4485                     a = {width: bw, height: bh, points: pt};\r
4486                 break;\r
4487             }\r
4488             this.dom.style.visibility = "visible";\r
4489             wrap.show();\r
4490 \r
4491             arguments.callee.anim = wrap.fxanim(a,\r
4492                 o,\r
4493                 'motion',\r
4494                 .5,\r
4495                 'easeOut', after);\r
4496         });\r
4497         return this;\r
4498     },\r
4499     \r
4500         \r
4501     slideOut : function(anchor, o){\r
4502         var el = this.getFxEl();\r
4503         o = o || {};\r
4504 \r
4505         el.queueFx(o, function(){\r
4506 \r
4507             anchor = anchor || "t";\r
4508 \r
4509             // restore values after effect\r
4510             var r = this.getFxRestore();\r
4511             \r
4512             var b = this.getBox();\r
4513             // fixed size for slide\r
4514             this.setSize(b);\r
4515 \r
4516             // wrap if needed\r
4517             var wrap = this.fxWrap(r.pos, o, "visible");\r
4518 \r
4519             var st = this.dom.style;\r
4520             st.visibility = "visible";\r
4521             st.position = "absolute";\r
4522 \r
4523             wrap.setSize(b);\r
4524 \r
4525             var after = function(){\r
4526                 if(o.useDisplay){\r
4527                     el.setDisplayed(false);\r
4528                 }else{\r
4529                     el.hide();\r
4530                 }\r
4531 \r
4532                 el.fxUnwrap(wrap, r.pos, o);\r
4533 \r
4534                 st.width = r.width;\r
4535                 st.height = r.height;\r
4536 \r
4537                 el.afterFx(o);\r
4538             };\r
4539 \r
4540             var a, zero = {to: 0};\r
4541             switch(anchor.toLowerCase()){\r
4542                 case "t":\r
4543                     st.left = st.bottom = "0";\r
4544                     a = {height: zero};\r
4545                 break;\r
4546                 case "l":\r
4547                     st.right = st.top = "0";\r
4548                     a = {width: zero};\r
4549                 break;\r
4550                 case "r":\r
4551                     st.left = st.top = "0";\r
4552                     a = {width: zero, points: {to:[b.right, b.y]}};\r
4553                 break;\r
4554                 case "b":\r
4555                     st.left = st.top = "0";\r
4556                     a = {height: zero, points: {to:[b.x, b.bottom]}};\r
4557                 break;\r
4558                 case "tl":\r
4559                     st.right = st.bottom = "0";\r
4560                     a = {width: zero, height: zero};\r
4561                 break;\r
4562                 case "bl":\r
4563                     st.right = st.top = "0";\r
4564                     a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};\r
4565                 break;\r
4566                 case "br":\r
4567                     st.left = st.top = "0";\r
4568                     a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};\r
4569                 break;\r
4570                 case "tr":\r
4571                     st.left = st.bottom = "0";\r
4572                     a = {width: zero, height: zero, points: {to:[b.right, b.y]}};\r
4573                 break;\r
4574             }\r
4575 \r
4576             arguments.callee.anim = wrap.fxanim(a,\r
4577                 o,\r
4578                 'motion',\r
4579                 .5,\r
4580                 "easeOut", after);\r
4581         });\r
4582         return this;\r
4583     },\r
4584 \r
4585         \r
4586     puff : function(o){\r
4587         var el = this.getFxEl();\r
4588         o = o || {};\r
4589 \r
4590         el.queueFx(o, function(){\r
4591             this.clearOpacity();\r
4592             this.show();\r
4593 \r
4594             // restore values after effect\r
4595             var r = this.getFxRestore();\r
4596             var st = this.dom.style;\r
4597 \r
4598             var after = function(){\r
4599                 if(o.useDisplay){\r
4600                     el.setDisplayed(false);\r
4601                 }else{\r
4602                     el.hide();\r
4603                 }\r
4604 \r
4605                 el.clearOpacity();\r
4606 \r
4607                 el.setPositioning(r.pos);\r
4608                 st.width = r.width;\r
4609                 st.height = r.height;\r
4610                 st.fontSize = '';\r
4611                 el.afterFx(o);\r
4612             };\r
4613 \r
4614             var width = this.getWidth();\r
4615             var height = this.getHeight();\r
4616 \r
4617             arguments.callee.anim = this.fxanim({\r
4618                     width : {to: this.adjustWidth(width * 2)},\r
4619                     height : {to: this.adjustHeight(height * 2)},\r
4620                     points : {by: [-(width * .5), -(height * .5)]},\r
4621                     opacity : {to: 0},\r
4622                     fontSize: {to:200, unit: "%"}\r
4623                 },\r
4624                 o,\r
4625                 'motion',\r
4626                 .5,\r
4627                 "easeOut", after);\r
4628         });\r
4629         return this;\r
4630     },\r
4631 \r
4632         \r
4633     switchOff : function(o){\r
4634         var el = this.getFxEl();\r
4635         o = o || {};\r
4636 \r
4637         el.queueFx(o, function(){\r
4638             this.clearOpacity();\r
4639             this.clip();\r
4640 \r
4641             // restore values after effect\r
4642             var r = this.getFxRestore();\r
4643             var st = this.dom.style;\r
4644 \r
4645             var after = function(){\r
4646                 if(o.useDisplay){\r
4647                     el.setDisplayed(false);\r
4648                 }else{\r
4649                     el.hide();\r
4650                 }\r
4651 \r
4652                 el.clearOpacity();\r
4653                 el.setPositioning(r.pos);\r
4654                 st.width = r.width;\r
4655                 st.height = r.height;\r
4656 \r
4657                 el.afterFx(o);\r
4658             };\r
4659 \r
4660             this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){\r
4661                 this.clearOpacity();\r
4662                 (function(){\r
4663                     this.fxanim({\r
4664                         height:{to:1},\r
4665                         points:{by:[0, this.getHeight() * .5]}\r
4666                     }, o, 'motion', 0.3, 'easeIn', after);\r
4667                 }).defer(100, this);\r
4668             });\r
4669         });\r
4670         return this;\r
4671     },\r
4672 \r
4673         \r
4674     highlight : function(color, o){\r
4675         var el = this.getFxEl();\r
4676         o = o || {};\r
4677 \r
4678         el.queueFx(o, function(){\r
4679             color = color || "ffff9c";\r
4680             var attr = o.attr || "backgroundColor";\r
4681 \r
4682             this.clearOpacity();\r
4683             this.show();\r
4684 \r
4685             var origColor = this.getColor(attr);\r
4686             var restoreColor = this.dom.style[attr];\r
4687             var endColor = (o.endColor || origColor) || "ffffff";\r
4688 \r
4689             var after = function(){\r
4690                 el.dom.style[attr] = restoreColor;\r
4691                 el.afterFx(o);\r
4692             };\r
4693 \r
4694             var a = {};\r
4695             a[attr] = {from: color, to: endColor};\r
4696             arguments.callee.anim = this.fxanim(a,\r
4697                 o,\r
4698                 'color',\r
4699                 1,\r
4700                 'easeIn', after);\r
4701         });\r
4702         return this;\r
4703     },\r
4704 \r
4705    \r
4706     frame : function(color, count, o){\r
4707         var el = this.getFxEl();\r
4708         o = o || {};\r
4709 \r
4710         el.queueFx(o, function(){\r
4711             color = color || "#C3DAF9";\r
4712             if(color.length == 6){\r
4713                 color = "#" + color;\r
4714             }\r
4715             count = count || 1;\r
4716             var duration = o.duration || 1;\r
4717             this.show();\r
4718 \r
4719             var b = this.getBox();\r
4720             var animFn = function(){\r
4721                 var proxy = Ext.getBody().createChild({\r
4722                      style:{\r
4723                         visbility:"hidden",\r
4724                         position:"absolute",\r
4725                         "z-index":"35000", // yee haw\r
4726                         border:"0px solid " + color\r
4727                      }\r
4728                   });\r
4729                 var scale = Ext.isBorderBox ? 2 : 1;\r
4730                 proxy.animate({\r
4731                     top:{from:b.y, to:b.y - 20},\r
4732                     left:{from:b.x, to:b.x - 20},\r
4733                     borderWidth:{from:0, to:10},\r
4734                     opacity:{from:1, to:0},\r
4735                     height:{from:b.height, to:(b.height + (20*scale))},\r
4736                     width:{from:b.width, to:(b.width + (20*scale))}\r
4737                 }, duration, function(){\r
4738                     proxy.remove();\r
4739                     if(--count > 0){\r
4740                          animFn();\r
4741                     }else{\r
4742                         el.afterFx(o);\r
4743                     }\r
4744                 });\r
4745             };\r
4746             animFn.call(this);\r
4747         });\r
4748         return this;\r
4749     },\r
4750 \r
4751    \r
4752     pause : function(seconds){\r
4753         var el = this.getFxEl();\r
4754         var o = {};\r
4755 \r
4756         el.queueFx(o, function(){\r
4757             setTimeout(function(){\r
4758                 el.afterFx(o);\r
4759             }, seconds * 1000);\r
4760         });\r
4761         return this;\r
4762     },\r
4763 \r
4764    \r
4765     fadeIn : function(o){\r
4766         var el = this.getFxEl();\r
4767         o = o || {};\r
4768         el.queueFx(o, function(){\r
4769             this.setOpacity(0);\r
4770             this.fixDisplay();\r
4771             this.dom.style.visibility = 'visible';\r
4772             var to = o.endOpacity || 1;\r
4773             arguments.callee.anim = this.fxanim({opacity:{to:to}},\r
4774                 o, null, .5, "easeOut", function(){\r
4775                 if(to == 1){\r
4776                     this.clearOpacity();\r
4777                 }\r
4778                 el.afterFx(o);\r
4779             });\r
4780         });\r
4781         return this;\r
4782     },\r
4783 \r
4784    \r
4785     fadeOut : function(o){\r
4786         var el = this.getFxEl();\r
4787         o = o || {};\r
4788         el.queueFx(o, function(){\r
4789             var to = o.endOpacity || 0;\r
4790             arguments.callee.anim = this.fxanim({opacity:{to:to}},\r
4791                 o, null, .5, "easeOut", function(){\r
4792                 if(to === 0){\r
4793                     if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){\r
4794                          this.dom.style.display = "none";\r
4795                     }else{\r
4796                          this.dom.style.visibility = "hidden";\r
4797                     }\r
4798                     this.clearOpacity();\r
4799                 }\r
4800                 el.afterFx(o);\r
4801             });\r
4802         });\r
4803         return this;\r
4804     },\r
4805 \r
4806    \r
4807     scale : function(w, h, o){\r
4808         this.shift(Ext.apply({}, o, {\r
4809             width: w,\r
4810             height: h\r
4811         }));\r
4812         return this;\r
4813     },\r
4814 \r
4815    \r
4816     shift : function(o){\r
4817         var el = this.getFxEl();\r
4818         o = o || {};\r
4819         el.queueFx(o, function(){\r
4820             var a = {}, w = o.width, h = o.height, x = o.x, y = o.y,  op = o.opacity;\r
4821             if(w !== undefined){\r
4822                 a.width = {to: this.adjustWidth(w)};\r
4823             }\r
4824             if(h !== undefined){\r
4825                 a.height = {to: this.adjustHeight(h)};\r
4826             }\r
4827             if(o.left !== undefined){\r
4828                 a.left = {to: o.left};\r
4829             }\r
4830             if(o.top !== undefined){\r
4831                 a.top = {to: o.top};\r
4832             }\r
4833             if(o.right !== undefined){\r
4834                 a.right = {to: o.right};\r
4835             }\r
4836             if(o.bottom !== undefined){\r
4837                 a.bottom = {to: o.bottom};\r
4838             }\r
4839             if(x !== undefined || y !== undefined){\r
4840                 a.points = {to: [\r
4841                     x !== undefined ? x : this.getX(),\r
4842                     y !== undefined ? y : this.getY()\r
4843                 ]};\r
4844             }\r
4845             if(op !== undefined){\r
4846                 a.opacity = {to: op};\r
4847             }\r
4848             if(o.xy !== undefined){\r
4849                 a.points = {to: o.xy};\r
4850             }\r
4851             arguments.callee.anim = this.fxanim(a,\r
4852                 o, 'motion', .35, "easeOut", function(){\r
4853                 el.afterFx(o);\r
4854             });\r
4855         });\r
4856         return this;\r
4857     },\r
4858 \r
4859         \r
4860     ghost : function(anchor, o){\r
4861         var el = this.getFxEl();\r
4862         o = o || {};\r
4863 \r
4864         el.queueFx(o, function(){\r
4865             anchor = anchor || "b";\r
4866 \r
4867             // restore values after effect\r
4868             var r = this.getFxRestore();\r
4869             var w = this.getWidth(),\r
4870                 h = this.getHeight();\r
4871 \r
4872             var st = this.dom.style;\r
4873 \r
4874             var after = function(){\r
4875                 if(o.useDisplay){\r
4876                     el.setDisplayed(false);\r
4877                 }else{\r
4878                     el.hide();\r
4879                 }\r
4880 \r
4881                 el.clearOpacity();\r
4882                 el.setPositioning(r.pos);\r
4883                 st.width = r.width;\r
4884                 st.height = r.height;\r
4885 \r
4886                 el.afterFx(o);\r
4887             };\r
4888 \r
4889             var a = {opacity: {to: 0}, points: {}}, pt = a.points;\r
4890             switch(anchor.toLowerCase()){\r
4891                 case "t":\r
4892                     pt.by = [0, -h];\r
4893                 break;\r
4894                 case "l":\r
4895                     pt.by = [-w, 0];\r
4896                 break;\r
4897                 case "r":\r
4898                     pt.by = [w, 0];\r
4899                 break;\r
4900                 case "b":\r
4901                     pt.by = [0, h];\r
4902                 break;\r
4903                 case "tl":\r
4904                     pt.by = [-w, -h];\r
4905                 break;\r
4906                 case "bl":\r
4907                     pt.by = [-w, h];\r
4908                 break;\r
4909                 case "br":\r
4910                     pt.by = [w, h];\r
4911                 break;\r
4912                 case "tr":\r
4913                     pt.by = [w, -h];\r
4914                 break;\r
4915             }\r
4916 \r
4917             arguments.callee.anim = this.fxanim(a,\r
4918                 o,\r
4919                 'motion',\r
4920                 .5,\r
4921                 "easeOut", after);\r
4922         });\r
4923         return this;\r
4924     },\r
4925 \r
4926         \r
4927     syncFx : function(){\r
4928         this.fxDefaults = Ext.apply(this.fxDefaults || {}, {\r
4929             block : false,\r
4930             concurrent : true,\r
4931             stopFx : false\r
4932         });\r
4933         return this;\r
4934     },\r
4935 \r
4936         \r
4937     sequenceFx : function(){\r
4938         this.fxDefaults = Ext.apply(this.fxDefaults || {}, {\r
4939             block : false,\r
4940             concurrent : false,\r
4941             stopFx : false\r
4942         });\r
4943         return this;\r
4944     },\r
4945 \r
4946         \r
4947     nextFx : function(){\r
4948         var ef = this.fxQueue[0];\r
4949         if(ef){\r
4950             ef.call(this);\r
4951         }\r
4952     },\r
4953 \r
4954         \r
4955     hasActiveFx : function(){\r
4956         return this.fxQueue && this.fxQueue[0];\r
4957     },\r
4958 \r
4959         \r
4960     stopFx : function(){\r
4961         if(this.hasActiveFx()){\r
4962             var cur = this.fxQueue[0];\r
4963             if(cur && cur.anim && cur.anim.isAnimated()){\r
4964                 this.fxQueue = [cur]; // clear out others\r
4965                 cur.anim.stop(true);\r
4966             }\r
4967         }\r
4968         return this;\r
4969     },\r
4970 \r
4971         \r
4972     beforeFx : function(o){\r
4973         if(this.hasActiveFx() && !o.concurrent){\r
4974            if(o.stopFx){\r
4975                this.stopFx();\r
4976                return true;\r
4977            }\r
4978            return false;\r
4979         }\r
4980         return true;\r
4981     },\r
4982 \r
4983         \r
4984     hasFxBlock : function(){\r
4985         var q = this.fxQueue;\r
4986         return q && q[0] && q[0].block;\r
4987     },\r
4988 \r
4989         \r
4990     queueFx : function(o, fn){\r
4991         if(!this.fxQueue){\r
4992             this.fxQueue = [];\r
4993         }\r
4994         if(!this.hasFxBlock()){\r
4995             Ext.applyIf(o, this.fxDefaults);\r
4996             if(!o.concurrent){\r
4997                 var run = this.beforeFx(o);\r
4998                 fn.block = o.block;\r
4999                 this.fxQueue.push(fn);\r
5000                 if(run){\r
5001                     this.nextFx();\r
5002                 }\r
5003             }else{\r
5004                 fn.call(this);\r
5005             }\r
5006         }\r
5007         return this;\r
5008     },\r
5009 \r
5010         \r
5011     fxWrap : function(pos, o, vis){\r
5012         var wrap;\r
5013         if(!o.wrap || !(wrap = Ext.get(o.wrap))){\r
5014             var wrapXY;\r
5015             if(o.fixPosition){\r
5016                 wrapXY = this.getXY();\r
5017             }\r
5018             var div = document.createElement("div");\r
5019             div.style.visibility = vis;\r
5020             wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));\r
5021             wrap.setPositioning(pos);\r
5022             if(wrap.getStyle("position") == "static"){\r
5023                 wrap.position("relative");\r
5024             }\r
5025             this.clearPositioning('auto');\r
5026             wrap.clip();\r
5027             wrap.dom.appendChild(this.dom);\r
5028             if(wrapXY){\r
5029                 wrap.setXY(wrapXY);\r
5030             }\r
5031         }\r
5032         return wrap;\r
5033     },\r
5034 \r
5035         \r
5036     fxUnwrap : function(wrap, pos, o){\r
5037         this.clearPositioning();\r
5038         this.setPositioning(pos);\r
5039         if(!o.wrap){\r
5040             wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);\r
5041             wrap.remove();\r
5042         }\r
5043     },\r
5044 \r
5045         \r
5046     getFxRestore : function(){\r
5047         var st = this.dom.style;\r
5048         return {pos: this.getPositioning(), width: st.width, height : st.height};\r
5049     },\r
5050 \r
5051         \r
5052     afterFx : function(o){\r
5053         if(o.afterStyle){\r
5054             this.applyStyles(o.afterStyle);\r
5055         }\r
5056         if(o.afterCls){\r
5057             this.addClass(o.afterCls);\r
5058         }\r
5059         if(o.remove === true){\r
5060             this.remove();\r
5061         }\r
5062         Ext.callback(o.callback, o.scope, [this]);\r
5063         if(!o.concurrent){\r
5064             this.fxQueue.shift();\r
5065             this.nextFx();\r
5066         }\r
5067     },\r
5068 \r
5069         \r
5070     getFxEl : function(){ // support for composite element fx\r
5071         return Ext.get(this.dom);\r
5072     },\r
5073 \r
5074         \r
5075     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){\r
5076         animType = animType || 'run';\r
5077         opt = opt || {};\r
5078         var anim = Ext.lib.Anim[animType](\r
5079             this.dom, args,\r
5080             (opt.duration || defaultDur) || .35,\r
5081             (opt.easing || defaultEase) || 'easeOut',\r
5082             function(){\r
5083                 Ext.callback(cb, this);\r
5084             },\r
5085             this\r
5086         );\r
5087         opt.anim = anim;\r
5088         return anim;\r
5089     }\r
5090 };\r
5091 \r
5092 // backwords compat\r
5093 Ext.Fx.resize = Ext.Fx.scale;\r
5094 \r
5095 //When included, Ext.Fx is automatically applied to Element so that all basic\r
5096 //effects are available directly via the Element API\r
5097 Ext.apply(Ext.Element.prototype, Ext.Fx);\r
5098 \r
5099 \r
5100 Ext.CompositeElement = function(els){\r
5101     this.elements = [];\r
5102     this.addElements(els);\r
5103 };\r
5104 Ext.CompositeElement.prototype = {\r
5105     isComposite: true,\r
5106     addElements : function(els){\r
5107         if(!els) return this;\r
5108         if(typeof els == "string"){\r
5109             els = Ext.Element.selectorFunction(els);\r
5110         }\r
5111         var yels = this.elements;\r
5112         var index = yels.length-1;\r
5113         for(var i = 0, len = els.length; i < len; i++) {\r
5114                 yels[++index] = Ext.get(els[i]);\r
5115         }\r
5116         return this;\r
5117     },\r
5118 \r
5119     \r
5120     fill : function(els){\r
5121         this.elements = [];\r
5122         this.add(els);\r
5123         return this;\r
5124     },\r
5125 \r
5126     \r
5127     filter : function(selector){\r
5128         var els = [];\r
5129         this.each(function(el){\r
5130             if(el.is(selector)){\r
5131                 els[els.length] = el.dom;\r
5132             }\r
5133         });\r
5134         this.fill(els);\r
5135         return this;\r
5136     },\r
5137 \r
5138     invoke : function(fn, args){\r
5139         var els = this.elements;\r
5140         for(var i = 0, len = els.length; i < len; i++) {\r
5141                 Ext.Element.prototype[fn].apply(els[i], args);\r
5142         }\r
5143         return this;\r
5144     },\r
5145     \r
5146     add : function(els){\r
5147         if(typeof els == "string"){\r
5148             this.addElements(Ext.Element.selectorFunction(els));\r
5149         }else if(els.length !== undefined){\r
5150             this.addElements(els);\r
5151         }else{\r
5152             this.addElements([els]);\r
5153         }\r
5154         return this;\r
5155     },\r
5156     \r
5157     each : function(fn, scope){\r
5158         var els = this.elements;\r
5159         for(var i = 0, len = els.length; i < len; i++){\r
5160             if(fn.call(scope || els[i], els[i], this, i) === false) {\r
5161                 break;\r
5162             }\r
5163         }\r
5164         return this;\r
5165     },\r
5166 \r
5167     \r
5168     item : function(index){\r
5169         return this.elements[index] || null;\r
5170     },\r
5171 \r
5172     \r
5173     first : function(){\r
5174         return this.item(0);\r
5175     },\r
5176 \r
5177     \r
5178     last : function(){\r
5179         return this.item(this.elements.length-1);\r
5180     },\r
5181 \r
5182     \r
5183     getCount : function(){\r
5184         return this.elements.length;\r
5185     },\r
5186 \r
5187     \r
5188     contains : function(el){\r
5189         return this.indexOf(el) !== -1;\r
5190     },\r
5191 \r
5192     \r
5193     indexOf : function(el){\r
5194         return this.elements.indexOf(Ext.get(el));\r
5195     },\r
5196 \r
5197 \r
5198     \r
5199     removeElement : function(el, removeDom){\r
5200         if(Ext.isArray(el)){\r
5201             for(var i = 0, len = el.length; i < len; i++){\r
5202                 this.removeElement(el[i]);\r
5203             }\r
5204             return this;\r
5205         }\r
5206         var index = typeof el == 'number' ? el : this.indexOf(el);\r
5207         if(index !== -1 && this.elements[index]){\r
5208             if(removeDom){\r
5209                 var d = this.elements[index];\r
5210                 if(d.dom){\r
5211                     d.remove();\r
5212                 }else{\r
5213                     Ext.removeNode(d);\r
5214                 }\r
5215             }\r
5216             this.elements.splice(index, 1);\r
5217         }\r
5218         return this;\r
5219     },\r
5220 \r
5221     \r
5222     replaceElement : function(el, replacement, domReplace){\r
5223         var index = typeof el == 'number' ? el : this.indexOf(el);\r
5224         if(index !== -1){\r
5225             if(domReplace){\r
5226                 this.elements[index].replaceWith(replacement);\r
5227             }else{\r
5228                 this.elements.splice(index, 1, Ext.get(replacement))\r
5229             }\r
5230         }\r
5231         return this;\r
5232     },\r
5233 \r
5234     \r
5235     clear : function(){\r
5236         this.elements = [];\r
5237     }\r
5238 };\r
5239 (function(){\r
5240 Ext.CompositeElement.createCall = function(proto, fnName){\r
5241     if(!proto[fnName]){\r
5242         proto[fnName] = function(){\r
5243             return this.invoke(fnName, arguments);\r
5244         };\r
5245     }\r
5246 };\r
5247 for(var fnName in Ext.Element.prototype){\r
5248     if(typeof Ext.Element.prototype[fnName] == "function"){\r
5249         Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName);\r
5250     }\r
5251 };\r
5252 })();\r
5253 \r
5254 \r
5255 Ext.CompositeElementLite = function(els){\r
5256     Ext.CompositeElementLite.superclass.constructor.call(this, els);\r
5257     this.el = new Ext.Element.Flyweight();\r
5258 };\r
5259 Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {\r
5260     addElements : function(els){\r
5261         if(els){\r
5262             if(Ext.isArray(els)){\r
5263                 this.elements = this.elements.concat(els);\r
5264             }else{\r
5265                 var yels = this.elements;\r
5266                 var index = yels.length-1;\r
5267                 for(var i = 0, len = els.length; i < len; i++) {\r
5268                     yels[++index] = els[i];\r
5269                 }\r
5270             }\r
5271         }\r
5272         return this;\r
5273     },\r
5274     invoke : function(fn, args){\r
5275         var els = this.elements;\r
5276         var el = this.el;\r
5277         for(var i = 0, len = els.length; i < len; i++) {\r
5278             el.dom = els[i];\r
5279                 Ext.Element.prototype[fn].apply(el, args);\r
5280         }\r
5281         return this;\r
5282     },\r
5283     \r
5284     item : function(index){\r
5285         if(!this.elements[index]){\r
5286             return null;\r
5287         }\r
5288         this.el.dom = this.elements[index];\r
5289         return this.el;\r
5290     },\r
5291 \r
5292     // fixes scope with flyweight\r
5293     addListener : function(eventName, handler, scope, opt){\r
5294         var els = this.elements;\r
5295         for(var i = 0, len = els.length; i < len; i++) {\r
5296             Ext.EventManager.on(els[i], eventName, handler, scope || els[i], opt);\r
5297         }\r
5298         return this;\r
5299     },\r
5300 \r
5301     \r
5302     each : function(fn, scope){\r
5303         var els = this.elements;\r
5304         var el = this.el;\r
5305         for(var i = 0, len = els.length; i < len; i++){\r
5306             el.dom = els[i];\r
5307                 if(fn.call(scope || el, el, this, i) === false){\r
5308                 break;\r
5309             }\r
5310         }\r
5311         return this;\r
5312     },\r
5313 \r
5314     indexOf : function(el){\r
5315         return this.elements.indexOf(Ext.getDom(el));\r
5316     },\r
5317 \r
5318     replaceElement : function(el, replacement, domReplace){\r
5319         var index = typeof el == 'number' ? el : this.indexOf(el);\r
5320         if(index !== -1){\r
5321             replacement = Ext.getDom(replacement);\r
5322             if(domReplace){\r
5323                 var d = this.elements[index];\r
5324                 d.parentNode.insertBefore(replacement, d);\r
5325                 Ext.removeNode(d);\r
5326             }\r
5327             this.elements.splice(index, 1, replacement);\r
5328         }\r
5329         return this;\r
5330     }\r
5331 });\r
5332 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;\r
5333 if(Ext.DomQuery){\r
5334     Ext.Element.selectorFunction = Ext.DomQuery.select;\r
5335 }\r
5336 \r
5337 Ext.Element.select = function(selector, unique, root){\r
5338     var els;\r
5339     if(typeof selector == "string"){\r
5340         els = Ext.Element.selectorFunction(selector, root);\r
5341     }else if(selector.length !== undefined){\r
5342         els = selector;\r
5343     }else{\r
5344         throw "Invalid selector";\r
5345     }\r
5346     if(unique === true){\r
5347         return new Ext.CompositeElement(els);\r
5348     }else{\r
5349         return new Ext.CompositeElementLite(els);\r
5350     }\r
5351 };\r
5352 \r
5353 Ext.select = Ext.Element.select;\r
5354 \r
5355 Ext.data.Connection = function(config){\r
5356     Ext.apply(this, config);\r
5357     this.addEvents(\r
5358         \r
5359         "beforerequest",\r
5360         \r
5361         "requestcomplete",\r
5362         \r
5363         "requestexception"\r
5364     );\r
5365     Ext.data.Connection.superclass.constructor.call(this);\r
5366 };\r
5367 \r
5368 Ext.extend(Ext.data.Connection, Ext.util.Observable, {\r
5369     \r
5370     \r
5371     \r
5372     \r
5373     \r
5374     timeout : 30000,\r
5375     \r
5376     autoAbort:false,\r
5377 \r
5378     \r
5379     disableCaching: true,\r
5380     \r
5381     \r
5382     disableCachingParam: '_dc',\r
5383     \r
5384 \r
5385     \r
5386     request : function(o){\r
5387         if(this.fireEvent("beforerequest", this, o) !== false){\r
5388             var p = o.params;\r
5389 \r
5390             if(typeof p == "function"){\r
5391                 p = p.call(o.scope||window, o);\r
5392             }\r
5393             if(typeof p == "object"){\r
5394                 p = Ext.urlEncode(p);\r
5395             }\r
5396             if(this.extraParams){\r
5397                 var extras = Ext.urlEncode(this.extraParams);\r
5398                 p = p ? (p + '&' + extras) : extras;\r
5399             }\r
5400 \r
5401             var url = o.url || this.url;\r
5402             if(typeof url == 'function'){\r
5403                 url = url.call(o.scope||window, o);\r
5404             }\r
5405 \r
5406             if(o.form){\r
5407                 var form = Ext.getDom(o.form);\r
5408                 url = url || form.action;\r
5409 \r
5410                 var enctype = form.getAttribute("enctype");\r
5411                 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){\r
5412                     return this.doFormUpload(o, p, url);\r
5413                 }\r
5414                 var f = Ext.lib.Ajax.serializeForm(form);\r
5415                 p = p ? (p + '&' + f) : f;\r
5416             }\r
5417 \r
5418             var hs = o.headers;\r
5419             if(this.defaultHeaders){\r
5420                 hs = Ext.apply(hs || {}, this.defaultHeaders);\r
5421                 if(!o.headers){\r
5422                     o.headers = hs;\r
5423                 }\r
5424             }\r
5425 \r
5426             var cb = {\r
5427                 success: this.handleResponse,\r
5428                 failure: this.handleFailure,\r
5429                 scope: this,\r
5430                 argument: {options: o},\r
5431                 timeout : o.timeout || this.timeout\r
5432             };\r
5433 \r
5434             var method = o.method||this.method||((p || o.xmlData || o.jsonData) ? "POST" : "GET");\r
5435 \r
5436             if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){\r
5437                 var dcp = o.disableCachingParam || this.disableCachingParam;\r
5438                 url += (url.indexOf('?') != -1 ? '&' : '?') + dcp + '=' + (new Date().getTime());\r
5439             }\r
5440 \r
5441             if(typeof o.autoAbort == 'boolean'){ // options gets top priority\r
5442                 if(o.autoAbort){\r
5443                     this.abort();\r
5444                 }\r
5445             }else if(this.autoAbort !== false){\r
5446                 this.abort();\r
5447             }\r
5448             if((method == 'GET' || o.xmlData || o.jsonData) && p){\r
5449                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;\r
5450                 p = '';\r
5451             }\r
5452             this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);\r
5453             return this.transId;\r
5454         }else{\r
5455             Ext.callback(o.callback, o.scope, [o, null, null]);\r
5456             return null;\r
5457         }\r
5458     },\r
5459 \r
5460     \r
5461     isLoading : function(transId){\r
5462         if(transId){\r
5463             return Ext.lib.Ajax.isCallInProgress(transId);\r
5464         }else{\r
5465             return this.transId ? true : false;\r
5466         }\r
5467     },\r
5468 \r
5469     \r
5470     abort : function(transId){\r
5471         if(transId || this.isLoading()){\r
5472             Ext.lib.Ajax.abort(transId || this.transId);\r
5473         }\r
5474     },\r
5475 \r
5476     // private\r
5477     handleResponse : function(response){\r
5478         this.transId = false;\r
5479         var options = response.argument.options;\r
5480         response.argument = options ? options.argument : null;\r
5481         this.fireEvent("requestcomplete", this, response, options);\r
5482         Ext.callback(options.success, options.scope, [response, options]);\r
5483         Ext.callback(options.callback, options.scope, [options, true, response]);\r
5484     },\r
5485 \r
5486     // private\r
5487     handleFailure : function(response, e){\r
5488         this.transId = false;\r
5489         var options = response.argument.options;\r
5490         response.argument = options ? options.argument : null;\r
5491         this.fireEvent("requestexception", this, response, options, e);\r
5492         Ext.callback(options.failure, options.scope, [response, options]);\r
5493         Ext.callback(options.callback, options.scope, [options, false, response]);\r
5494     },\r
5495 \r
5496     // private\r
5497     doFormUpload : function(o, ps, url){\r
5498         var id = Ext.id();\r
5499         var frame = document.createElement('iframe');\r
5500         frame.id = id;\r
5501         frame.name = id;\r
5502         frame.className = 'x-hidden';\r
5503         if(Ext.isIE){\r
5504             frame.src = Ext.SSL_SECURE_URL;\r
5505         }\r
5506         document.body.appendChild(frame);\r
5507 \r
5508         if(Ext.isIE){\r
5509            document.frames[id].name = id;\r
5510         }\r
5511 \r
5512         var form = Ext.getDom(o.form);\r
5513         form.target = id;\r
5514         form.method = 'POST';\r
5515         form.enctype = form.encoding = 'multipart/form-data';\r
5516         if(url){\r
5517             form.action = url;\r
5518         }\r
5519 \r
5520         var hiddens, hd;\r
5521         if(ps){ // add dynamic params\r
5522             hiddens = [];\r
5523             ps = Ext.urlDecode(ps, false);\r
5524             for(var k in ps){\r
5525                 if(ps.hasOwnProperty(k)){\r
5526                     hd = document.createElement('input');\r
5527                     hd.type = 'hidden';\r
5528                     hd.name = k;\r
5529                     hd.value = ps[k];\r
5530                     form.appendChild(hd);\r
5531                     hiddens.push(hd);\r
5532                 }\r
5533             }\r
5534         }\r
5535 \r
5536         function cb(){\r
5537             var r = {  // bogus response object\r
5538                 responseText : '',\r
5539                 responseXML : null\r
5540             };\r
5541 \r
5542             r.argument = o ? o.argument : null;\r
5543 \r
5544             try { //\r
5545                 var doc;\r
5546                 if(Ext.isIE){\r
5547                     doc = frame.contentWindow.document;\r
5548                 }else {\r
5549                     doc = (frame.contentDocument || window.frames[id].document);\r
5550                 }\r
5551                 if(doc && doc.body){\r
5552                     r.responseText = doc.body.innerHTML;\r
5553                 }\r
5554                 if(doc && doc.XMLDocument){\r
5555                     r.responseXML = doc.XMLDocument;\r
5556                 }else {\r
5557                     r.responseXML = doc;\r
5558                 }\r
5559             }\r
5560             catch(e) {\r
5561                 // ignore\r
5562             }\r
5563 \r
5564             Ext.EventManager.removeListener(frame, 'load', cb, this);\r
5565 \r
5566             this.fireEvent("requestcomplete", this, r, o);\r
5567 \r
5568             Ext.callback(o.success, o.scope, [r, o]);\r
5569             Ext.callback(o.callback, o.scope, [o, true, r]);\r
5570 \r
5571             setTimeout(function(){Ext.removeNode(frame);}, 100);\r
5572         }\r
5573 \r
5574         Ext.EventManager.on(frame, 'load', cb, this);\r
5575         form.submit();\r
5576 \r
5577         if(hiddens){ // remove dynamic params\r
5578             for(var i = 0, len = hiddens.length; i < len; i++){\r
5579                 Ext.removeNode(hiddens[i]);\r
5580             }\r
5581         }\r
5582     }\r
5583 });\r
5584 \r
5585 \r
5586 Ext.Ajax = new Ext.data.Connection({\r
5587     \r
5588     \r
5589     \r
5590     \r
5591     \r
5592     \r
5593 \r
5594     \r
5595 \r
5596     \r
5597     \r
5598     \r
5599     \r
5600     \r
5601     \r
5602 \r
5603     \r
5604     autoAbort : false,\r
5605 \r
5606     \r
5607     serializeForm : function(form){\r
5608         return Ext.lib.Ajax.serializeForm(form);\r
5609     }\r
5610 });\r
5611 \r
5612 Ext.Updater = Ext.extend(Ext.util.Observable, {\r
5613     constructor: function(el, forceNew){\r
5614         el = Ext.get(el);\r
5615         if(!forceNew && el.updateManager){\r
5616             return el.updateManager;\r
5617         }\r
5618         \r
5619         this.el = el;\r
5620         \r
5621         this.defaultUrl = null;\r
5622 \r
5623         this.addEvents(\r
5624             \r
5625             "beforeupdate",\r
5626             \r
5627             "update",\r
5628             \r
5629             "failure"\r
5630         );\r
5631         var d = Ext.Updater.defaults;\r
5632         \r
5633         this.sslBlankUrl = d.sslBlankUrl;\r
5634         \r
5635         this.disableCaching = d.disableCaching;\r
5636         \r
5637         this.indicatorText = d.indicatorText;\r
5638         \r
5639         this.showLoadIndicator = d.showLoadIndicator;\r
5640         \r
5641         this.timeout = d.timeout;\r
5642         \r
5643         this.loadScripts = d.loadScripts;\r
5644         \r
5645         this.transaction = null;\r
5646         \r
5647         this.refreshDelegate = this.refresh.createDelegate(this);\r
5648         \r
5649         this.updateDelegate = this.update.createDelegate(this);\r
5650         \r
5651         this.formUpdateDelegate = this.formUpdate.createDelegate(this);\r
5652 \r
5653         if(!this.renderer){\r
5654          \r
5655         this.renderer = this.getDefaultRenderer();\r
5656         }\r
5657         Ext.Updater.superclass.constructor.call(this);\r
5658     },\r
5659     \r
5660     getDefaultRenderer: function() {\r
5661         return new Ext.Updater.BasicRenderer();\r
5662     },\r
5663     \r
5664     getEl : function(){\r
5665         return this.el;\r
5666     },\r
5667 \r
5668     \r
5669     update : function(url, params, callback, discardUrl){\r
5670         if(this.fireEvent("beforeupdate", this.el, url, params) !== false){\r
5671             var cfg, callerScope;\r
5672             if(typeof url == "object"){ // must be config object\r
5673                 cfg = url;\r
5674                 url = cfg.url;\r
5675                 params = params || cfg.params;\r
5676                 callback = callback || cfg.callback;\r
5677                 discardUrl = discardUrl || cfg.discardUrl;\r
5678                 callerScope = cfg.scope;\r
5679                 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};\r
5680                 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};\r
5681                 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};\r
5682                 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};\r
5683             }\r
5684             this.showLoading();\r
5685 \r
5686             if(!discardUrl){\r
5687                 this.defaultUrl = url;\r
5688             }\r
5689             if(typeof url == "function"){\r
5690                 url = url.call(this);\r
5691             }\r
5692 \r
5693             var o = Ext.apply({}, {\r
5694                 url : url,\r
5695                 params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,\r
5696                 success: this.processSuccess,\r
5697                 failure: this.processFailure,\r
5698                 scope: this,\r
5699                 callback: undefined,\r
5700                 timeout: (this.timeout*1000),\r
5701                 disableCaching: this.disableCaching,\r
5702                 argument: {\r
5703                     "options": cfg,\r
5704                     "url": url,\r
5705                     "form": null,\r
5706                     "callback": callback,\r
5707                     "scope": callerScope || window,\r
5708                     "params": params\r
5709                 }\r
5710             }, cfg);\r
5711 \r
5712             this.transaction = Ext.Ajax.request(o);\r
5713         }\r
5714     },\r
5715 \r
5716     \r
5717     formUpdate : function(form, url, reset, callback){\r
5718         if(this.fireEvent("beforeupdate", this.el, form, url) !== false){\r
5719             if(typeof url == "function"){\r
5720                 url = url.call(this);\r
5721             }\r
5722             form = Ext.getDom(form)\r
5723             this.transaction = Ext.Ajax.request({\r
5724                 form: form,\r
5725                 url:url,\r
5726                 success: this.processSuccess,\r
5727                 failure: this.processFailure,\r
5728                 scope: this,\r
5729                 timeout: (this.timeout*1000),\r
5730                 argument: {\r
5731                     "url": url,\r
5732                     "form": form,\r
5733                     "callback": callback,\r
5734                     "reset": reset\r
5735                 }\r
5736             });\r
5737             this.showLoading.defer(1, this);\r
5738         }\r
5739     },\r
5740 \r
5741     \r
5742     refresh : function(callback){\r
5743         if(this.defaultUrl == null){\r
5744             return;\r
5745         }\r
5746         this.update(this.defaultUrl, null, callback, true);\r
5747     },\r
5748 \r
5749     \r
5750     startAutoRefresh : function(interval, url, params, callback, refreshNow){\r
5751         if(refreshNow){\r
5752             this.update(url || this.defaultUrl, params, callback, true);\r
5753         }\r
5754         if(this.autoRefreshProcId){\r
5755             clearInterval(this.autoRefreshProcId);\r
5756         }\r
5757         this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);\r
5758     },\r
5759 \r
5760     \r
5761      stopAutoRefresh : function(){\r
5762         if(this.autoRefreshProcId){\r
5763             clearInterval(this.autoRefreshProcId);\r
5764             delete this.autoRefreshProcId;\r
5765         }\r
5766     },\r
5767 \r
5768     \r
5769     isAutoRefreshing : function(){\r
5770        return this.autoRefreshProcId ? true : false;\r
5771     },\r
5772 \r
5773     \r
5774     showLoading : function(){\r
5775         if(this.showLoadIndicator){\r
5776             this.el.update(this.indicatorText);\r
5777         }\r
5778     },\r
5779 \r
5780     // private\r
5781     processSuccess : function(response){\r
5782         this.transaction = null;\r
5783         if(response.argument.form && response.argument.reset){\r
5784             try{ // put in try/catch since some older FF releases had problems with this\r
5785                 response.argument.form.reset();\r
5786             }catch(e){}\r
5787         }\r
5788         if(this.loadScripts){\r
5789             this.renderer.render(this.el, response, this,\r
5790                 this.updateComplete.createDelegate(this, [response]));\r
5791         }else{\r
5792             this.renderer.render(this.el, response, this);\r
5793             this.updateComplete(response);\r
5794         }\r
5795     },\r
5796 \r
5797     // private\r
5798     updateComplete : function(response){\r
5799         this.fireEvent("update", this.el, response);\r
5800         if(typeof response.argument.callback == "function"){\r
5801             response.argument.callback.call(response.argument.scope, this.el, true, response, response.argument.options);\r
5802         }\r
5803     },\r
5804 \r
5805     // private\r
5806     processFailure : function(response){\r
5807         this.transaction = null;\r
5808         this.fireEvent("failure", this.el, response);\r
5809         if(typeof response.argument.callback == "function"){\r
5810             response.argument.callback.call(response.argument.scope, this.el, false, response, response.argument.options);\r
5811         }\r
5812     },\r
5813 \r
5814     \r
5815     setRenderer : function(renderer){\r
5816         this.renderer = renderer;\r
5817     },\r
5818 \r
5819     \r
5820     getRenderer : function(){\r
5821        return this.renderer;\r
5822     },\r
5823 \r
5824     \r
5825     setDefaultUrl : function(defaultUrl){\r
5826         this.defaultUrl = defaultUrl;\r
5827     },\r
5828 \r
5829     \r
5830     abort : function(){\r
5831         if(this.transaction){\r
5832             Ext.Ajax.abort(this.transaction);\r
5833         }\r
5834     },\r
5835 \r
5836     \r
5837     isUpdating : function(){\r
5838         if(this.transaction){\r
5839             return Ext.Ajax.isLoading(this.transaction);\r
5840         }\r
5841         return false;\r
5842     }\r
5843 });\r
5844 \r
5845 \r
5846    Ext.Updater.defaults = {\r
5847        \r
5848          timeout : 30,\r
5849          \r
5850         loadScripts : false,\r
5851         \r
5852         sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false"),\r
5853         \r
5854         disableCaching : false,\r
5855         \r
5856         showLoadIndicator : true,\r
5857         \r
5858         indicatorText : '<div class="loading-indicator">Loading...</div>'\r
5859    };\r
5860 \r
5861 \r
5862 Ext.Updater.updateElement = function(el, url, params, options){\r
5863     var um = Ext.get(el).getUpdater();\r
5864     Ext.apply(um, options);\r
5865     um.update(url, params, options ? options.callback : null);\r
5866 };\r
5867 \r
5868 Ext.Updater.BasicRenderer = function(){};\r
5869 \r
5870 Ext.Updater.BasicRenderer.prototype = {\r
5871     \r
5872      render : function(el, response, updateManager, callback){\r
5873         el.update(response.responseText, updateManager.loadScripts, callback);\r
5874     }\r
5875 };\r
5876 \r
5877 Ext.UpdateManager = Ext.Updater;\r
5878 \r
5879 \r
5880 \r
5881 \r
5882 \r
5883 (function() {\r
5884 \r
5885 // create private copy of Ext's String.format() method\r
5886 // - to remove unnecessary dependency\r
5887 // - to resolve namespace conflict with M$-Ajax's implementation\r
5888 function xf(format) {\r
5889     var args = Array.prototype.slice.call(arguments, 1);\r
5890     return format.replace(/\{(\d+)\}/g, function(m, i) {\r
5891         return args[i];\r
5892     });\r
5893 }\r
5894 \r
5895 \r
5896 // private\r
5897 Date.formatCodeToRegex = function(character, currentGroup) {\r
5898     // Note: currentGroup - position in regex result array (see notes for Date.parseCodes below)\r
5899     var p = Date.parseCodes[character];\r
5900 \r
5901     if (p) {\r
5902       p = Ext.type(p) == 'function'? p() : p;\r
5903       Date.parseCodes[character] = p; // reassign function result to prevent repeated execution\r
5904     }\r
5905 \r
5906     return p? Ext.applyIf({\r
5907       c: p.c? xf(p.c, currentGroup || "{0}") : p.c\r
5908     }, p) : {\r
5909         g:0,\r
5910         c:null,\r
5911         s:Ext.escapeRe(character) // treat unrecognised characters as literals\r
5912     }\r
5913 }\r
5914 \r
5915 // private shorthand for Date.formatCodeToRegex since we'll be using it fairly often\r
5916 var $f = Date.formatCodeToRegex;\r
5917 \r
5918 Ext.apply(Date, {\r
5919     // private\r
5920     parseFunctions: {count:0},\r
5921     parseRegexes: [],\r
5922     formatFunctions: {count:0},\r
5923     daysInMonth : [31,28,31,30,31,30,31,31,30,31,30,31],\r
5924     y2kYear : 50,\r
5925 \r
5926     \r
5927     MILLI : "ms",\r
5928 \r
5929     \r
5930     SECOND : "s",\r
5931 \r
5932     \r
5933     MINUTE : "mi",\r
5934 \r
5935     \r
5936     HOUR : "h",\r
5937 \r
5938     \r
5939     DAY : "d",\r
5940 \r
5941     \r
5942     MONTH : "mo",\r
5943 \r
5944     \r
5945     YEAR : "y",\r
5946 \r
5947     \r
5948     dayNames : [\r
5949         "Sunday",\r
5950         "Monday",\r
5951         "Tuesday",\r
5952         "Wednesday",\r
5953         "Thursday",\r
5954         "Friday",\r
5955         "Saturday"\r
5956     ],\r
5957 \r
5958     \r
5959     monthNames : [\r
5960         "January",\r
5961         "February",\r
5962         "March",\r
5963         "April",\r
5964         "May",\r
5965         "June",\r
5966         "July",\r
5967         "August",\r
5968         "September",\r
5969         "October",\r
5970         "November",\r
5971         "December"\r
5972     ],\r
5973 \r
5974     \r
5975     monthNumbers : {\r
5976         Jan:0,\r
5977         Feb:1,\r
5978         Mar:2,\r
5979         Apr:3,\r
5980         May:4,\r
5981         Jun:5,\r
5982         Jul:6,\r
5983         Aug:7,\r
5984         Sep:8,\r
5985         Oct:9,\r
5986         Nov:10,\r
5987         Dec:11\r
5988     },\r
5989 \r
5990     \r
5991     getShortMonthName : function(month) {\r
5992         return Date.monthNames[month].substring(0, 3);\r
5993     },\r
5994 \r
5995     \r
5996     getShortDayName : function(day) {\r
5997         return Date.dayNames[day].substring(0, 3);\r
5998     },\r
5999 \r
6000     \r
6001     getMonthNumber : function(name) {\r
6002         // handle camel casing for english month names (since the keys for the Date.monthNumbers hash are case sensitive)\r
6003         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];\r
6004     },\r
6005 \r
6006     \r
6007     formatCodes : {\r
6008         d: "String.leftPad(this.getDate(), 2, '0')",\r
6009         D: "Date.getShortDayName(this.getDay())", // get localised short day name\r
6010         j: "this.getDate()",\r
6011         l: "Date.dayNames[this.getDay()]",\r
6012         N: "(this.getDay() ? this.getDay() : 7)",\r
6013         S: "this.getSuffix()",\r
6014         w: "this.getDay()",\r
6015         z: "this.getDayOfYear()",\r
6016         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",\r
6017         F: "Date.monthNames[this.getMonth()]",\r
6018         m: "String.leftPad(this.getMonth() + 1, 2, '0')",\r
6019         M: "Date.getShortMonthName(this.getMonth())", // get localised short month name\r
6020         n: "(this.getMonth() + 1)",\r
6021         t: "this.getDaysInMonth()",\r
6022         L: "(this.isLeapYear() ? 1 : 0)",\r
6023         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",\r
6024         Y: "this.getFullYear()",\r
6025         y: "('' + this.getFullYear()).substring(2, 4)",\r
6026         a: "(this.getHours() < 12 ? 'am' : 'pm')",\r
6027         A: "(this.getHours() < 12 ? 'AM' : 'PM')",\r
6028         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",\r
6029         G: "this.getHours()",\r
6030         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",\r
6031         H: "String.leftPad(this.getHours(), 2, '0')",\r
6032         i: "String.leftPad(this.getMinutes(), 2, '0')",\r
6033         s: "String.leftPad(this.getSeconds(), 2, '0')",\r
6034         u: "String.leftPad(this.getMilliseconds(), 3, '0')",\r
6035         O: "this.getGMTOffset()",\r
6036         P: "this.getGMTOffset(true)",\r
6037         T: "this.getTimezone()",\r
6038         Z: "(this.getTimezoneOffset() * -60)",\r
6039         c: function() { // ISO-8601 -- GMT format\r
6040             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {\r
6041                 var e = c.charAt(i);\r
6042                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); // treat T as a character literal\r
6043             }\r
6044             return code.join(" + ");\r
6045         },\r
6046         \r
6047         U: "Math.round(this.getTime() / 1000)"\r
6048     },\r
6049 \r
6050     \r
6051     parseDate : function(input, format) {\r
6052         var p = Date.parseFunctions;\r
6053         if (p[format] == null) {\r
6054             Date.createParser(format);\r
6055         }\r
6056         var func = p[format];\r
6057         return Date[func](input);\r
6058     },\r
6059 \r
6060     // private\r
6061     getFormatCode : function(character) {\r
6062         var f = Date.formatCodes[character];\r
6063 \r
6064         if (f) {\r
6065           f = Ext.type(f) == 'function'? f() : f;\r
6066           Date.formatCodes[character] = f; // reassign function result to prevent repeated execution\r
6067         }\r
6068 \r
6069         // note: unknown characters are treated as literals\r
6070         return f || ("'" + String.escape(character) + "'");\r
6071     },\r
6072 \r
6073     // private\r
6074     createNewFormat : function(format) {\r
6075         var funcName = "format" + Date.formatFunctions.count++,\r
6076             code = "Date.prototype." + funcName + " = function(){return ",\r
6077             special = false,\r
6078             ch = '';\r
6079 \r
6080         Date.formatFunctions[format] = funcName;\r
6081 \r
6082         for (var i = 0; i < format.length; ++i) {\r
6083             ch = format.charAt(i);\r
6084             if (!special && ch == "\\") {\r
6085                 special = true;\r
6086             }\r
6087             else if (special) {\r
6088                 special = false;\r
6089                 code += "'" + String.escape(ch) + "' + ";\r
6090             }\r
6091             else {\r
6092                 code += Date.getFormatCode(ch) + " + ";\r
6093             }\r
6094         }\r
6095         eval(code.substring(0, code.length - 3) + ";}");\r
6096     },\r
6097 \r
6098     // private\r
6099     createParser : function() {\r
6100         var code = [\r
6101             "Date.{0} = function(input){",\r
6102                 "var y, m, d, h = 0, i = 0, s = 0, ms = 0, o, z, u, v;",\r
6103                 "input = String(input);",\r
6104                 "d = new Date();",\r
6105                 "y = d.getFullYear();",\r
6106                 "m = d.getMonth();",\r
6107                 "d = d.getDate();",\r
6108                 "var results = input.match(Date.parseRegexes[{1}]);",\r
6109                 "if(results && results.length > 0){",\r
6110                     "{2}",\r
6111                     "if(u){",\r
6112                         "v = new Date(u * 1000);", // give top priority to UNIX time\r
6113                     "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0){",\r
6114                         "v = new Date(y, m, d, h, i, s, ms);",\r
6115                     "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0){",\r
6116                         "v = new Date(y, m, d, h, i, s);",\r
6117                     "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0){",\r
6118                         "v = new Date(y, m, d, h, i);",\r
6119                     "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0){",\r
6120                         "v = new Date(y, m, d, h);",\r
6121                     "}else if (y >= 0 && m >= 0 && d > 0){",\r
6122                         "v = new Date(y, m, d);",\r
6123                     "}else if (y >= 0 && m >= 0){",\r
6124                         "v = new Date(y, m);",\r
6125                     "}else if (y >= 0){",\r
6126                         "v = new Date(y);",\r
6127                     "}",\r
6128                 "}",\r
6129                 "return (v && (z != null || o != null))?" // favour UTC offset over GMT offset\r
6130                     + " (Ext.type(z) == 'number' ? v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - z) :" // reset to UTC, then add offset\r
6131                     + " v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn))) : v;", // reset to GMT, then add offset\r
6132             "}"\r
6133         ].join('\n');\r
6134 \r
6135         return function(format) {\r
6136             var funcName = "parse" + Date.parseFunctions.count++,\r
6137                 regexNum = Date.parseRegexes.length,\r
6138                 currentGroup = 1,\r
6139                 calc = "",\r
6140                 regex = "",\r
6141                 special = false,\r
6142                 ch = "";\r
6143 \r
6144             Date.parseFunctions[format] = funcName;\r
6145 \r
6146             for (var i = 0; i < format.length; ++i) {\r
6147                 ch = format.charAt(i);\r
6148                 if (!special && ch == "\\") {\r
6149                     special = true;\r
6150                 }\r
6151                 else if (special) {\r
6152                     special = false;\r
6153                     regex += String.escape(ch);\r
6154                 }\r
6155                 else {\r
6156                     var obj = $f(ch, currentGroup);\r
6157                     currentGroup += obj.g;\r
6158                     regex += obj.s;\r
6159                     if (obj.g && obj.c) {\r
6160                         calc += obj.c;\r
6161                     }\r
6162                 }\r
6163             }\r
6164 \r
6165             Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");\r
6166             eval(xf(code, funcName, regexNum, calc));\r
6167         }\r
6168     }(),\r
6169 \r
6170     // private\r
6171     parseCodes : {\r
6172         \r
6173         d: {\r
6174             g:1,\r
6175             c:"d = parseInt(results[{0}], 10);\n",\r
6176             s:"(\\d{2})" // day of month with leading zeroes (01 - 31)\r
6177         },\r
6178         j: {\r
6179             g:1,\r
6180             c:"d = parseInt(results[{0}], 10);\n",\r
6181             s:"(\\d{1,2})" // day of month without leading zeroes (1 - 31)\r
6182         },\r
6183         D: function() {\r
6184             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); // get localised short day names\r
6185             return {\r
6186                 g:0,\r
6187                 c:null,\r
6188                 s:"(?:" + a.join("|") +")"\r
6189             }\r
6190         },\r
6191         l: function() {\r
6192             return {\r
6193                 g:0,\r
6194                 c:null,\r
6195                 s:"(?:" + Date.dayNames.join("|") + ")"\r
6196             }\r
6197         },\r
6198         N: {\r
6199             g:0,\r
6200             c:null,\r
6201             s:"[1-7]" // ISO-8601 day number (1 (monday) - 7 (sunday))\r
6202         },\r
6203         S: {\r
6204             g:0,\r
6205             c:null,\r
6206             s:"(?:st|nd|rd|th)"\r
6207         },\r
6208         w: {\r
6209             g:0,\r
6210             c:null,\r
6211             s:"[0-6]" // javascript day number (0 (sunday) - 6 (saturday))\r
6212         },\r
6213         z: {\r
6214             g:0,\r
6215             c:null,\r
6216             s:"(?:\\d{1,3})" // day of the year (0 - 364 (365 in leap years))\r
6217         },\r
6218         W: {\r
6219             g:0,\r
6220             c:null,\r
6221             s:"(?:\\d{2})" // ISO-8601 week number (with leading zero)\r
6222         },\r
6223         F: function() {\r
6224             return {\r
6225                 g:1,\r
6226                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", // get localised month number\r
6227                 s:"(" + Date.monthNames.join("|") + ")"\r
6228             }\r
6229         },\r
6230         M: function() {\r
6231             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names\r
6232             return Ext.applyIf({\r
6233                 s:"(" + a.join("|") + ")"\r
6234             }, $f("F"));\r
6235         },\r
6236         m: {\r
6237             g:1,\r
6238             c:"m = parseInt(results[{0}], 10) - 1;\n",\r
6239             s:"(\\d{2})" // month number with leading zeros (01 - 12)\r
6240         },\r
6241         n: {\r
6242             g:1,\r
6243             c:"m = parseInt(results[{0}], 10) - 1;\n",\r
6244             s:"(\\d{1,2})" // month number without leading zeros (1 - 12)\r
6245         },\r
6246         t: {\r
6247             g:0,\r
6248             c:null,\r
6249             s:"(?:\\d{2})" // no. of days in the month (28 - 31)\r
6250         },\r
6251         L: {\r
6252             g:0,\r
6253             c:null,\r
6254             s:"(?:1|0)"\r
6255         },\r
6256         o: function() {\r
6257             return $f("Y");\r
6258         },\r
6259         Y: {\r
6260             g:1,\r
6261             c:"y = parseInt(results[{0}], 10);\n",\r
6262             s:"(\\d{4})" // 4-digit year\r
6263         },\r
6264         y: {\r
6265             g:1,\r
6266             c:"var ty = parseInt(results[{0}], 10);\n"\r
6267                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", // 2-digit year\r
6268             s:"(\\d{1,2})"\r
6269         },\r
6270         a: {\r
6271             g:1,\r
6272             c:"if (results[{0}] == 'am') {\n"\r
6273                 + "if (h == 12) { h = 0; }\n"\r
6274                 + "} else { if (h < 12) { h += 12; }}",\r
6275             s:"(am|pm)"\r
6276         },\r
6277         A: {\r
6278             g:1,\r
6279             c:"if (results[{0}] == 'AM') {\n"\r
6280                 + "if (h == 12) { h = 0; }\n"\r
6281                 + "} else { if (h < 12) { h += 12; }}",\r
6282             s:"(AM|PM)"\r
6283         },\r
6284         g: function() {\r
6285             return $f("G");\r
6286         },\r
6287         G: {\r
6288             g:1,\r
6289             c:"h = parseInt(results[{0}], 10);\n",\r
6290             s:"(\\d{1,2})" // 24-hr format of an hour without leading zeroes (0 - 23)\r
6291         },\r
6292         h: function() {\r
6293             return $f("H");\r
6294         },\r
6295         H: {\r
6296             g:1,\r
6297             c:"h = parseInt(results[{0}], 10);\n",\r
6298             s:"(\\d{2})" //  24-hr format of an hour with leading zeroes (00 - 23)\r
6299         },\r
6300         i: {\r
6301             g:1,\r
6302             c:"i = parseInt(results[{0}], 10);\n",\r
6303             s:"(\\d{2})" // minutes with leading zeros (00 - 59)\r
6304         },\r
6305         s: {\r
6306             g:1,\r
6307             c:"s = parseInt(results[{0}], 10);\n",\r
6308             s:"(\\d{2})" // seconds with leading zeros (00 - 59)\r
6309         },\r
6310         u: {\r
6311             g:1,\r
6312             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",\r
6313             s:"(\\d+)" // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)\r
6314         },\r
6315         O: {\r
6316             g:1,\r
6317             c:[\r
6318                 "o = results[{0}];",\r
6319                 "var sn = o.substring(0,1);", // get + / - sign\r
6320                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);", // get hours (performs minutes-to-hour conversion also, just in case)\r
6321                 "var mn = o.substring(3,5) % 60;", // get minutes\r
6322                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" // -12hrs <= GMT offset <= 14hrs\r
6323             ].join("\n"),\r
6324             s: "([+\-]\\d{4})" // GMT offset in hrs and mins\r
6325         },\r
6326         P: {\r
6327             g:1,\r
6328             c:[\r
6329                 "o = results[{0}];",\r
6330                 "var sn = o.substring(0,1);", // get + / - sign\r
6331                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);", // get hours (performs minutes-to-hour conversion also, just in case)\r
6332                 "var mn = o.substring(4,6) % 60;", // get minutes\r
6333                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" // -12hrs <= GMT offset <= 14hrs\r
6334             ].join("\n"),\r
6335             s: "([+\-]\\d{2}:\\d{2})" // GMT offset in hrs and mins (with colon separator)\r
6336         },\r
6337         T: {\r
6338             g:0,\r
6339             c:null,\r
6340             s:"[A-Z]{1,4}" // timezone abbrev. may be between 1 - 4 chars\r
6341         },\r
6342         Z: {\r
6343             g:1,\r
6344             c:"z = results[{0}] * 1;\n" // -43200 <= UTC offset <= 50400\r
6345                   + "z = (-43200 <= z && z <= 50400)? z : null;\n",\r
6346             s:"([+\-]?\\d{1,5})" // leading '+' sign is optional for UTC offset\r
6347         },\r
6348         c: function() {\r
6349             var calc = [],\r
6350                 arr = [\r
6351                     $f("Y", 1), // year\r
6352                     $f("m", 2), // month\r
6353                     $f("d", 3), // day\r
6354                     $f("h", 4), // hour\r
6355                     $f("i", 5), // minute\r
6356                     $f("s", 6), // second\r
6357                     {c:"ms = (results[7] || '.0').substring(1); ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)\r
6358                     {c:[ // allow both "Z" (i.e. UTC) and "+08:00" (i.e. UTC offset) time zone delimiters\r
6359                         "if(results[9] == 'Z'){",\r
6360                             "z = 0;",\r
6361                         "}else{",\r
6362                             $f("P", 9).c,\r
6363                         "}"\r
6364                     ].join('\n')}\r
6365                 ];\r
6366 \r
6367             for (var i = 0, l = arr.length; i < l; ++i) {\r
6368                 calc.push(arr[i].c);\r
6369             }\r
6370 \r
6371             return {\r
6372                 g:1,\r
6373                 c:calc.join(""),\r
6374                 s:arr[0].s + "-" + arr[1].s + "-" + arr[2].s + "T" + arr[3].s + ":" + arr[4].s + ":" + arr[5].s\r
6375                       + "((\.|,)\\d+)?" // decimal fraction of a second (e.g. ",998465" or ".998465")\r
6376                       + "(Z|([+\-]\\d{2}:\\d{2}))" // "Z" (UTC) or "+08:00" (UTC offset)\r
6377             }\r
6378         },\r
6379         U: {\r
6380             g:1,\r
6381             c:"u = parseInt(results[{0}], 10);\n",\r
6382             s:"(-?\\d+)" // leading minus sign indicates seconds before UNIX epoch\r
6383         }\r
6384     }\r
6385 });\r
6386 \r
6387 }());\r
6388 \r
6389 Ext.apply(Date.prototype, {\r
6390     // private\r
6391     dateFormat : function(format) {\r
6392         if (Date.formatFunctions[format] == null) {\r
6393             Date.createNewFormat(format);\r
6394         }\r
6395         var func = Date.formatFunctions[format];\r
6396         return this[func]();\r
6397     },\r
6398 \r
6399     \r
6400     getTimezone : function() {\r
6401         // the following list shows the differences between date strings from different browsers on a WinXP SP2 machine from an Asian locale:\r
6402         //\r
6403         // Opera  : "Thu, 25 Oct 2007 22:53:45 GMT+0800" -- shortest (weirdest) date string of the lot\r
6404         // Safari : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone (same as FF)\r
6405         // FF     : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone\r
6406         // IE     : "Thu Oct 25 22:54:35 UTC+0800 2007" -- (Asian system setting) look for 3-4 letter timezone abbrev\r
6407         // IE     : "Thu Oct 25 17:06:37 PDT 2007" -- (American system setting) look for 3-4 letter timezone abbrev\r
6408         //\r
6409         // this crazy regex attempts to guess the correct timezone abbreviation despite these differences.\r
6410         // step 1: (?:\((.*)\) -- find timezone in parentheses\r
6411         // step 2: ([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?) -- if nothing was found in step 1, find timezone from timezone offset portion of date string\r
6412         // step 3: remove all non uppercase characters found in step 1 and 2\r
6413         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");\r
6414     },\r
6415 \r
6416     \r
6417     getGMTOffset : function(colon) {\r
6418         return (this.getTimezoneOffset() > 0 ? "-" : "+")\r
6419             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")\r
6420             + (colon ? ":" : "")\r
6421             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");\r
6422     },\r
6423 \r
6424     \r
6425     getDayOfYear : function() {\r
6426         var num = 0;\r
6427         Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;\r
6428         for (var i = 0; i < this.getMonth(); ++i) {\r
6429             num += Date.daysInMonth[i];\r
6430         }\r
6431         return num + this.getDate() - 1;\r
6432     },\r
6433 \r
6434     \r
6435     getWeekOfYear : function() {\r
6436         // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm\r
6437         var ms1d = 864e5, // milliseconds in a day\r
6438             ms7d = 7 * ms1d; // milliseconds in a week\r
6439 \r
6440         return function() { // return a closure so constants get calculated only once\r
6441             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, // an Absolute Day Number\r
6442                 AWN = Math.floor(DC3 / 7), // an Absolute Week Number\r
6443                 Wyr = new Date(AWN * ms7d).getUTCFullYear();\r
6444 \r
6445             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;\r
6446         }\r
6447     }(),\r
6448 \r
6449     \r
6450     isLeapYear : function() {\r
6451         var year = this.getFullYear();\r
6452         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));\r
6453     },\r
6454 \r
6455     \r
6456     getFirstDayOfMonth : function() {\r
6457         var day = (this.getDay() - (this.getDate() - 1)) % 7;\r
6458         return (day < 0) ? (day + 7) : day;\r
6459     },\r
6460 \r
6461     \r
6462     getLastDayOfMonth : function() {\r
6463         var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;\r
6464         return (day < 0) ? (day + 7) : day;\r
6465     },\r
6466 \r
6467 \r
6468     \r
6469     getFirstDateOfMonth : function() {\r
6470         return new Date(this.getFullYear(), this.getMonth(), 1);\r
6471     },\r
6472 \r
6473     \r
6474     getLastDateOfMonth : function() {\r
6475         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());\r
6476     },\r
6477 \r
6478     \r
6479     getDaysInMonth : function() {\r
6480         Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;\r
6481         return Date.daysInMonth[this.getMonth()];\r
6482     },\r
6483 \r
6484     \r
6485     getSuffix : function() {\r
6486         switch (this.getDate()) {\r
6487             case 1:\r
6488             case 21:\r
6489             case 31:\r
6490                 return "st";\r
6491             case 2:\r
6492             case 22:\r
6493                 return "nd";\r
6494             case 3:\r
6495             case 23:\r
6496                 return "rd";\r
6497             default:\r
6498                 return "th";\r
6499         }\r
6500     },\r
6501 \r
6502     \r
6503     clone : function() {\r
6504         return new Date(this.getTime());\r
6505     },\r
6506 \r
6507     \r
6508     clearTime : function(clone){\r
6509         if(clone){\r
6510             return this.clone().clearTime();\r
6511         }\r
6512         this.setHours(0);\r
6513         this.setMinutes(0);\r
6514         this.setSeconds(0);\r
6515         this.setMilliseconds(0);\r
6516         return this;\r
6517     },\r
6518 \r
6519     \r
6520     add : function(interval, value){\r
6521         var d = this.clone();\r
6522         if (!interval || value === 0) return d;\r
6523 \r
6524         switch(interval.toLowerCase()){\r
6525             case Date.MILLI:\r
6526                 d.setMilliseconds(this.getMilliseconds() + value);\r
6527                 break;\r
6528             case Date.SECOND:\r
6529                 d.setSeconds(this.getSeconds() + value);\r
6530                 break;\r
6531             case Date.MINUTE:\r
6532                 d.setMinutes(this.getMinutes() + value);\r
6533                 break;\r
6534             case Date.HOUR:\r
6535                 d.setHours(this.getHours() + value);\r
6536                 break;\r
6537             case Date.DAY:\r
6538                 d.setDate(this.getDate() + value);\r
6539                 break;\r
6540             case Date.MONTH:\r
6541                 var day = this.getDate();\r
6542                 if(day > 28){\r
6543                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());\r
6544                 }\r
6545                 d.setDate(day);\r
6546                 d.setMonth(this.getMonth() + value);\r
6547                 break;\r
6548             case Date.YEAR:\r
6549                 d.setFullYear(this.getFullYear() + value);\r
6550                 break;\r
6551         }\r
6552         return d;\r
6553     },\r
6554 \r
6555     \r
6556     between : function(start, end){\r
6557         var t = this.getTime();\r
6558         return start.getTime() <= t && t <= end.getTime();\r
6559     }\r
6560 });\r
6561 \r
6562 \r
6563 \r
6564 Date.prototype.format = Date.prototype.dateFormat;\r
6565 \r
6566 \r
6567 // private\r
6568 // safari setMonth is broken\r
6569 if(Ext.isSafari){\r
6570     Date.brokenSetMonth = Date.prototype.setMonth;\r
6571     Date.prototype.setMonth = function(num){\r
6572         if(num <= -1){\r
6573             var n = Math.ceil(-num);\r
6574             var back_year = Math.ceil(n/12);\r
6575             var month = (n % 12) ? 12 - n % 12 : 0 ;\r
6576             this.setFullYear(this.getFullYear() - back_year);\r
6577             return Date.brokenSetMonth.call(this, month);\r
6578         } else {\r
6579             return Date.brokenSetMonth.apply(this, arguments);\r
6580         }\r
6581     };\r
6582 }\r
6583 \r
6584 Ext.util.DelayedTask = function(fn, scope, args){\r
6585     var id = null, d, t;\r
6586 \r
6587     var call = function(){\r
6588         var now = new Date().getTime();\r
6589         if(now - t >= d){\r
6590             clearInterval(id);\r
6591             id = null;\r
6592             fn.apply(scope, args || []);\r
6593         }\r
6594     };\r
6595     \r
6596     this.delay = function(delay, newFn, newScope, newArgs){\r
6597         if(id && delay != d){\r
6598             this.cancel();\r
6599         }\r
6600         d = delay;\r
6601         t = new Date().getTime();\r
6602         fn = newFn || fn;\r
6603         scope = newScope || scope;\r
6604         args = newArgs || args;\r
6605         if(!id){\r
6606             id = setInterval(call, d);\r
6607         }\r
6608     };\r
6609 \r
6610     \r
6611     this.cancel = function(){\r
6612         if(id){\r
6613             clearInterval(id);\r
6614             id = null;\r
6615         }\r
6616     };\r
6617 };\r
6618 \r
6619 Ext.util.TaskRunner = function(interval){\r
6620     interval = interval || 10;\r
6621     var tasks = [], removeQueue = [];\r
6622     var id = 0;\r
6623     var running = false;\r
6624 \r
6625     // private\r
6626     var stopThread = function(){\r
6627         running = false;\r
6628         clearInterval(id);\r
6629         id = 0;\r
6630     };\r
6631 \r
6632     // private\r
6633     var startThread = function(){\r
6634         if(!running){\r
6635             running = true;\r
6636             id = setInterval(runTasks, interval);\r
6637         }\r
6638     };\r
6639 \r
6640     // private\r
6641     var removeTask = function(t){\r
6642         removeQueue.push(t);\r
6643         if(t.onStop){\r
6644             t.onStop.apply(t.scope || t);\r
6645         }\r
6646     };\r
6647 \r
6648     // private\r
6649     var runTasks = function(){\r
6650         if(removeQueue.length > 0){\r
6651             for(var i = 0, len = removeQueue.length; i < len; i++){\r
6652                 tasks.remove(removeQueue[i]);\r
6653             }\r
6654             removeQueue = [];\r
6655             if(tasks.length < 1){\r
6656                 stopThread();\r
6657                 return;\r
6658             }\r
6659         }\r
6660         var now = new Date().getTime();\r
6661         for(var i = 0, len = tasks.length; i < len; ++i){\r
6662             var t = tasks[i];\r
6663             var itime = now - t.taskRunTime;\r
6664             if(t.interval <= itime){\r
6665                 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);\r
6666                 t.taskRunTime = now;\r
6667                 if(rt === false || t.taskRunCount === t.repeat){\r
6668                     removeTask(t);\r
6669                     return;\r
6670                 }\r
6671             }\r
6672             if(t.duration && t.duration <= (now - t.taskStartTime)){\r
6673                 removeTask(t);\r
6674             }\r
6675         }\r
6676     };\r
6677 \r
6678     \r
6679     this.start = function(task){\r
6680         tasks.push(task);\r
6681         task.taskStartTime = new Date().getTime();\r
6682         task.taskRunTime = 0;\r
6683         task.taskRunCount = 0;\r
6684         startThread();\r
6685         return task;\r
6686     };\r
6687 \r
6688     \r
6689     this.stop = function(task){\r
6690         removeTask(task);\r
6691         return task;\r
6692     };\r
6693 \r
6694     \r
6695     this.stopAll = function(){\r
6696         stopThread();\r
6697         for(var i = 0, len = tasks.length; i < len; i++){\r
6698             if(tasks[i].onStop){\r
6699                 tasks[i].onStop();\r
6700             }\r
6701         }\r
6702         tasks = [];\r
6703         removeQueue = [];\r
6704     };\r
6705 };\r
6706 \r
6707 \r
6708 Ext.TaskMgr = new Ext.util.TaskRunner();\r
6709 \r
6710 Ext.util.MixedCollection = function(allowFunctions, keyFn){\r
6711     this.items = [];\r
6712     this.map = {};\r
6713     this.keys = [];\r
6714     this.length = 0;\r
6715     this.addEvents(\r
6716         \r
6717         "clear",\r
6718         \r
6719         "add",\r
6720         \r
6721         "replace",\r
6722         \r
6723         "remove",\r
6724         "sort"\r
6725     );\r
6726     this.allowFunctions = allowFunctions === true;\r
6727     if(keyFn){\r
6728         this.getKey = keyFn;\r
6729     }\r
6730     Ext.util.MixedCollection.superclass.constructor.call(this);\r
6731 };\r
6732 \r
6733 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {\r
6734     allowFunctions : false,\r
6735 \r
6736 \r
6737     add : function(key, o){\r
6738         if(arguments.length == 1){\r
6739             o = arguments[0];\r
6740             key = this.getKey(o);\r
6741         }\r
6742         if(typeof key == "undefined" || key === null){\r
6743             this.length++;\r
6744             this.items.push(o);\r
6745             this.keys.push(null);\r
6746         }else{\r
6747             var old = this.map[key];\r
6748             if(old){\r
6749                 return this.replace(key, o);\r
6750             }\r
6751             this.length++;\r
6752             this.items.push(o);\r
6753             this.map[key] = o;\r
6754             this.keys.push(key);\r
6755         }\r
6756         this.fireEvent("add", this.length-1, o, key);\r
6757         return o;\r
6758     },\r
6759 \r
6760 \r
6761     getKey : function(o){\r
6762          return o.id;\r
6763     },\r
6764 \r
6765 \r
6766     replace : function(key, o){\r
6767         if(arguments.length == 1){\r
6768             o = arguments[0];\r
6769             key = this.getKey(o);\r
6770         }\r
6771         var old = this.item(key);\r
6772         if(typeof key == "undefined" || key === null || typeof old == "undefined"){\r
6773              return this.add(key, o);\r
6774         }\r
6775         var index = this.indexOfKey(key);\r
6776         this.items[index] = o;\r
6777         this.map[key] = o;\r
6778         this.fireEvent("replace", key, old, o);\r
6779         return o;\r
6780     },\r
6781 \r
6782 \r
6783     addAll : function(objs){\r
6784         if(arguments.length > 1 || Ext.isArray(objs)){\r
6785             var args = arguments.length > 1 ? arguments : objs;\r
6786             for(var i = 0, len = args.length; i < len; i++){\r
6787                 this.add(args[i]);\r
6788             }\r
6789         }else{\r
6790             for(var key in objs){\r
6791                 if(this.allowFunctions || typeof objs[key] != "function"){\r
6792                     this.add(key, objs[key]);\r
6793                 }\r
6794             }\r
6795         }\r
6796     },\r
6797 \r
6798 \r
6799     each : function(fn, scope){\r
6800         var items = [].concat(this.items); // each safe for removal\r
6801         for(var i = 0, len = items.length; i < len; i++){\r
6802             if(fn.call(scope || items[i], items[i], i, len) === false){\r
6803                 break;\r
6804             }\r
6805         }\r
6806     },\r
6807 \r
6808 \r
6809     eachKey : function(fn, scope){\r
6810         for(var i = 0, len = this.keys.length; i < len; i++){\r
6811             fn.call(scope || window, this.keys[i], this.items[i], i, len);\r
6812         }\r
6813     },\r
6814 \r
6815     \r
6816     find : function(fn, scope){\r
6817         for(var i = 0, len = this.items.length; i < len; i++){\r
6818             if(fn.call(scope || window, this.items[i], this.keys[i])){\r
6819                 return this.items[i];\r
6820             }\r
6821         }\r
6822         return null;\r
6823     },\r
6824 \r
6825 \r
6826     insert : function(index, key, o){\r
6827         if(arguments.length == 2){\r
6828             o = arguments[1];\r
6829             key = this.getKey(o);\r
6830         }\r
6831         if(index >= this.length){\r
6832             return this.add(key, o);\r
6833         }\r
6834         this.length++;\r
6835         this.items.splice(index, 0, o);\r
6836         if(typeof key != "undefined" && key != null){\r
6837             this.map[key] = o;\r
6838         }\r
6839         this.keys.splice(index, 0, key);\r
6840         this.fireEvent("add", index, o, key);\r
6841         return o;\r
6842     },\r
6843 \r
6844 \r
6845     remove : function(o){\r
6846         return this.removeAt(this.indexOf(o));\r
6847     },\r
6848 \r
6849 \r
6850     removeAt : function(index){\r
6851         if(index < this.length && index >= 0){\r
6852             this.length--;\r
6853             var o = this.items[index];\r
6854             this.items.splice(index, 1);\r
6855             var key = this.keys[index];\r
6856             if(typeof key != "undefined"){\r
6857                 delete this.map[key];\r
6858             }\r
6859             this.keys.splice(index, 1);\r
6860             this.fireEvent("remove", o, key);\r
6861             return o;\r
6862         }\r
6863         return false;\r
6864     },\r
6865 \r
6866 \r
6867     removeKey : function(key){\r
6868         return this.removeAt(this.indexOfKey(key));\r
6869     },\r
6870 \r
6871 \r
6872     getCount : function(){\r
6873         return this.length;\r
6874     },\r
6875 \r
6876 \r
6877     indexOf : function(o){\r
6878         return this.items.indexOf(o);\r
6879     },\r
6880 \r
6881 \r
6882     indexOfKey : function(key){\r
6883         return this.keys.indexOf(key);\r
6884     },\r
6885 \r
6886 \r
6887     item : function(key){\r
6888         var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];\r
6889         return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!\r
6890     },\r
6891 \r
6892 \r
6893     itemAt : function(index){\r
6894         return this.items[index];\r
6895     },\r
6896 \r
6897 \r
6898     key : function(key){\r
6899         return this.map[key];\r
6900     },\r
6901 \r
6902 \r
6903     contains : function(o){\r
6904         return this.indexOf(o) != -1;\r
6905     },\r
6906 \r
6907 \r
6908     containsKey : function(key){\r
6909         return typeof this.map[key] != "undefined";\r
6910     },\r
6911 \r
6912 \r
6913     clear : function(){\r
6914         this.length = 0;\r
6915         this.items = [];\r
6916         this.keys = [];\r
6917         this.map = {};\r
6918         this.fireEvent("clear");\r
6919     },\r
6920 \r
6921 \r
6922     first : function(){\r
6923         return this.items[0];\r
6924     },\r
6925 \r
6926 \r
6927     last : function(){\r
6928         return this.items[this.length-1];\r
6929     },\r
6930 \r
6931     // private\r
6932     _sort : function(property, dir, fn){\r
6933         var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;\r
6934         fn = fn || function(a, b){\r
6935             return a-b;\r
6936         };\r
6937         var c = [], k = this.keys, items = this.items;\r
6938         for(var i = 0, len = items.length; i < len; i++){\r
6939             c[c.length] = {key: k[i], value: items[i], index: i};\r
6940         }\r
6941         c.sort(function(a, b){\r
6942             var v = fn(a[property], b[property]) * dsc;\r
6943             if(v == 0){\r
6944                 v = (a.index < b.index ? -1 : 1);\r
6945             }\r
6946             return v;\r
6947         });\r
6948         for(var i = 0, len = c.length; i < len; i++){\r
6949             items[i] = c[i].value;\r
6950             k[i] = c[i].key;\r
6951         }\r
6952         this.fireEvent("sort", this);\r
6953     },\r
6954 \r
6955     \r
6956     sort : function(dir, fn){\r
6957         this._sort("value", dir, fn);\r
6958     },\r
6959 \r
6960     \r
6961     keySort : function(dir, fn){\r
6962         this._sort("key", dir, fn || function(a, b){\r
6963             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();\r
6964             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);\r
6965         });\r
6966     },\r
6967 \r
6968     \r
6969     getRange : function(start, end){\r
6970         var items = this.items;\r
6971         if(items.length < 1){\r
6972             return [];\r
6973         }\r
6974         start = start || 0;\r
6975         end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);\r
6976         var r = [];\r
6977         if(start <= end){\r
6978             for(var i = start; i <= end; i++) {\r
6979                     r[r.length] = items[i];\r
6980             }\r
6981         }else{\r
6982             for(var i = start; i >= end; i--) {\r
6983                     r[r.length] = items[i];\r
6984             }\r
6985         }\r
6986         return r;\r
6987     },\r
6988 \r
6989     \r
6990     filter : function(property, value, anyMatch, caseSensitive){\r
6991         if(Ext.isEmpty(value, false)){\r
6992             return this.clone();\r
6993         }\r
6994         value = this.createValueMatcher(value, anyMatch, caseSensitive);\r
6995         return this.filterBy(function(o){\r
6996             return o && value.test(o[property]);\r
6997         });\r
6998         },\r
6999 \r
7000     \r
7001     filterBy : function(fn, scope){\r
7002         var r = new Ext.util.MixedCollection();\r
7003         r.getKey = this.getKey;\r
7004         var k = this.keys, it = this.items;\r
7005         for(var i = 0, len = it.length; i < len; i++){\r
7006             if(fn.call(scope||this, it[i], k[i])){\r
7007                                 r.add(k[i], it[i]);\r
7008                         }\r
7009         }\r
7010         return r;\r
7011     },\r
7012 \r
7013     \r
7014     findIndex : function(property, value, start, anyMatch, caseSensitive){\r
7015         if(Ext.isEmpty(value, false)){\r
7016             return -1;\r
7017         }\r
7018         value = this.createValueMatcher(value, anyMatch, caseSensitive);\r
7019         return this.findIndexBy(function(o){\r
7020             return o && value.test(o[property]);\r
7021         }, null, start);\r
7022         },\r
7023 \r
7024     \r
7025     findIndexBy : function(fn, scope, start){\r
7026         var k = this.keys, it = this.items;\r
7027         for(var i = (start||0), len = it.length; i < len; i++){\r
7028             if(fn.call(scope||this, it[i], k[i])){\r
7029                                 return i;\r
7030             }\r
7031         }\r
7032         if(typeof start == 'number' && start > 0){\r
7033             for(var i = 0; i < start; i++){\r
7034                 if(fn.call(scope||this, it[i], k[i])){\r
7035                     return i;\r
7036                 }\r
7037             }\r
7038         }\r
7039         return -1;\r
7040     },\r
7041 \r
7042     // private\r
7043     createValueMatcher : function(value, anyMatch, caseSensitive){\r
7044         if(!value.exec){ // not a regex\r
7045             value = String(value);\r
7046             value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');\r
7047         }\r
7048         return value;\r
7049     },\r
7050 \r
7051     \r
7052     clone : function(){\r
7053         var r = new Ext.util.MixedCollection();\r
7054         var k = this.keys, it = this.items;\r
7055         for(var i = 0, len = it.length; i < len; i++){\r
7056             r.add(k[i], it[i]);\r
7057         }\r
7058         r.getKey = this.getKey;\r
7059         return r;\r
7060     }\r
7061 });\r
7062 \r
7063 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;\r
7064 \r
7065 Ext.util.JSON = new (function(){\r
7066     var useHasOwn = !!{}.hasOwnProperty;\r
7067 \r
7068     // crashes Safari in some instances\r
7069     //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;\r
7070 \r
7071     var pad = function(n) {\r
7072         return n < 10 ? "0" + n : n;\r
7073     };\r
7074 \r
7075     var m = {\r
7076         "\b": '\\b',\r
7077         "\t": '\\t',\r
7078         "\n": '\\n',\r
7079         "\f": '\\f',\r
7080         "\r": '\\r',\r
7081         '"' : '\\"',\r
7082         "\\": '\\\\'\r
7083     };\r
7084 \r
7085     var encodeString = function(s){\r
7086         if (/["\\\x00-\x1f]/.test(s)) {\r
7087             return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {\r
7088                 var c = m[b];\r
7089                 if(c){\r
7090                     return c;\r
7091                 }\r
7092                 c = b.charCodeAt();\r
7093                 return "\\u00" +\r
7094                     Math.floor(c / 16).toString(16) +\r
7095                     (c % 16).toString(16);\r
7096             }) + '"';\r
7097         }\r
7098         return '"' + s + '"';\r
7099     };\r
7100 \r
7101     var encodeArray = function(o){\r
7102         var a = ["["], b, i, l = o.length, v;\r
7103             for (i = 0; i < l; i += 1) {\r
7104                 v = o[i];\r
7105                 switch (typeof v) {\r
7106                     case "undefined":\r
7107                     case "function":\r
7108                     case "unknown":\r
7109                         break;\r
7110                     default:\r
7111                         if (b) {\r
7112                             a.push(',');\r
7113                         }\r
7114                         a.push(v === null ? "null" : Ext.util.JSON.encode(v));\r
7115                         b = true;\r
7116                 }\r
7117             }\r
7118             a.push("]");\r
7119             return a.join("");\r
7120     };\r
7121 \r
7122     this.encodeDate = function(o){\r
7123         return '"' + o.getFullYear() + "-" +\r
7124                 pad(o.getMonth() + 1) + "-" +\r
7125                 pad(o.getDate()) + "T" +\r
7126                 pad(o.getHours()) + ":" +\r
7127                 pad(o.getMinutes()) + ":" +\r
7128                 pad(o.getSeconds()) + '"';\r
7129     };\r
7130 \r
7131     \r
7132     this.encode = function(o){\r
7133         if(typeof o == "undefined" || o === null){\r
7134             return "null";\r
7135         }else if(Ext.isArray(o)){\r
7136             return encodeArray(o);\r
7137         }else if(Ext.isDate(o)){\r
7138             return Ext.util.JSON.encodeDate(o);\r
7139         }else if(typeof o == "string"){\r
7140             return encodeString(o);\r
7141         }else if(typeof o == "number"){\r
7142             return isFinite(o) ? String(o) : "null";\r
7143         }else if(typeof o == "boolean"){\r
7144             return String(o);\r
7145         }else {\r
7146             var a = ["{"], b, i, v;\r
7147             for (i in o) {\r
7148                 if(!useHasOwn || o.hasOwnProperty(i)) {\r
7149                     v = o[i];\r
7150                     switch (typeof v) {\r
7151                     case "undefined":\r
7152                     case "function":\r
7153                     case "unknown":\r
7154                         break;\r
7155                     default:\r
7156                         if(b){\r
7157                             a.push(',');\r
7158                         }\r
7159                         a.push(this.encode(i), ":",\r
7160                                 v === null ? "null" : this.encode(v));\r
7161                         b = true;\r
7162                     }\r
7163                 }\r
7164             }\r
7165             a.push("}");\r
7166             return a.join("");\r
7167         }\r
7168     };\r
7169 \r
7170     \r
7171     this.decode = function(json){\r
7172         return eval("(" + json + ')');\r
7173     };\r
7174 })();\r
7175 \r
7176 Ext.encode = Ext.util.JSON.encode;\r
7177 \r
7178 Ext.decode = Ext.util.JSON.decode;\r
7179 \r
7180 \r
7181 Ext.util.Format = function(){\r
7182     var trimRe = /^\s+|\s+$/g;\r
7183     return {\r
7184         \r
7185         ellipsis : function(value, len){\r
7186             if(value && value.length > len){\r
7187                 return value.substr(0, len-3)+"...";\r
7188             }\r
7189             return value;\r
7190         },\r
7191 \r
7192         \r
7193         undef : function(value){\r
7194             return value !== undefined ? value : "";\r
7195         },\r
7196 \r
7197         \r
7198         defaultValue : function(value, defaultValue){\r
7199             return value !== undefined && value !== '' ? value : defaultValue;\r
7200         },\r
7201 \r
7202         \r
7203         htmlEncode : function(value){\r
7204             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");\r
7205         },\r
7206 \r
7207         \r
7208         htmlDecode : function(value){\r
7209             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");\r
7210         },\r
7211 \r
7212         \r
7213         trim : function(value){\r
7214             return String(value).replace(trimRe, "");\r
7215         },\r
7216 \r
7217         \r
7218         substr : function(value, start, length){\r
7219             return String(value).substr(start, length);\r
7220         },\r
7221 \r
7222         \r
7223         lowercase : function(value){\r
7224             return String(value).toLowerCase();\r
7225         },\r
7226 \r
7227         \r
7228         uppercase : function(value){\r
7229             return String(value).toUpperCase();\r
7230         },\r
7231 \r
7232         \r
7233         capitalize : function(value){\r
7234             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();\r
7235         },\r
7236 \r
7237         // private\r
7238         call : function(value, fn){\r
7239             if(arguments.length > 2){\r
7240                 var args = Array.prototype.slice.call(arguments, 2);\r
7241                 args.unshift(value);\r
7242                 return eval(fn).apply(window, args);\r
7243             }else{\r
7244                 return eval(fn).call(window, value);\r
7245             }\r
7246         },\r
7247 \r
7248         \r
7249         usMoney : function(v){\r
7250             v = (Math.round((v-0)*100))/100;\r
7251             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);\r
7252             v = String(v);\r
7253             var ps = v.split('.');\r
7254             var whole = ps[0];\r
7255             var sub = ps[1] ? '.'+ ps[1] : '.00';\r
7256             var r = /(\d+)(\d{3})/;\r
7257             while (r.test(whole)) {\r
7258                 whole = whole.replace(r, '$1' + ',' + '$2');\r
7259             }\r
7260             v = whole + sub;\r
7261             if(v.charAt(0) == '-'){\r
7262                 return '-$' + v.substr(1);\r
7263             }\r
7264             return "$" +  v;\r
7265         },\r
7266 \r
7267         \r
7268         date : function(v, format){\r
7269             if(!v){\r
7270                 return "";\r
7271             }\r
7272             if(!Ext.isDate(v)){\r
7273                 v = new Date(Date.parse(v));\r
7274             }\r
7275             return v.dateFormat(format || "m/d/Y");\r
7276         },\r
7277 \r
7278         \r
7279         dateRenderer : function(format){\r
7280             return function(v){\r
7281                 return Ext.util.Format.date(v, format);\r
7282             };\r
7283         },\r
7284 \r
7285         // private\r
7286         stripTagsRE : /<\/?[^>]+>/gi,\r
7287         \r
7288         \r
7289         stripTags : function(v){\r
7290             return !v ? v : String(v).replace(this.stripTagsRE, "");\r
7291         },\r
7292 \r
7293         // private\r
7294         stripScriptsRe : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
7295 \r
7296         \r
7297         stripScripts : function(v){\r
7298             return !v ? v : String(v).replace(this.stripScriptsRe, "");\r
7299         },\r
7300 \r
7301         \r
7302         fileSize : function(size){\r
7303             if(size < 1024) {\r
7304                 return size + " bytes";\r
7305             } else if(size < 1048576) {\r
7306                 return (Math.round(((size*10) / 1024))/10) + " KB";\r
7307             } else {\r
7308                 return (Math.round(((size*10) / 1048576))/10) + " MB";\r
7309             }\r
7310         },\r
7311 \r
7312         math : function(){\r
7313             var fns = {};\r
7314             return function(v, a){\r
7315                 if(!fns[a]){\r
7316                     fns[a] = new Function('v', 'return v ' + a + ';');\r
7317                 }\r
7318                 return fns[a](v);\r
7319             }\r
7320         }(),\r
7321 \r
7322                 \r
7323         nl2br : function(v){\r
7324             return v === undefined || v === null ? '' : v.replace(/\n/g, '<br/>');\r
7325         }\r
7326     };\r
7327 }();\r
7328 \r
7329 Ext.XTemplate = function(){\r
7330     Ext.XTemplate.superclass.constructor.apply(this, arguments);\r
7331     var s = this.html;\r
7332 \r
7333     s = ['<tpl>', s, '</tpl>'].join('');\r
7334 \r
7335     var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;\r
7336 \r
7337     var nameRe = /^<tpl\b[^>]*?for="(.*?)"/;\r
7338     var ifRe = /^<tpl\b[^>]*?if="(.*?)"/;\r
7339     var execRe = /^<tpl\b[^>]*?exec="(.*?)"/;\r
7340     var m, id = 0;\r
7341     var tpls = [];\r
7342 \r
7343     while(m = s.match(re)){\r
7344        var m2 = m[0].match(nameRe);\r
7345        var m3 = m[0].match(ifRe);\r
7346        var m4 = m[0].match(execRe);\r
7347        var exp = null, fn = null, exec = null;\r
7348        var name = m2 && m2[1] ? m2[1] : '';\r
7349        if(m3){\r
7350            exp = m3 && m3[1] ? m3[1] : null;\r
7351            if(exp){\r
7352                fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return '+(Ext.util.Format.htmlDecode(exp))+'; }');\r
7353            }\r
7354        }\r
7355        if(m4){\r
7356            exp = m4 && m4[1] ? m4[1] : null;\r
7357            if(exp){\r
7358                exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ '+(Ext.util.Format.htmlDecode(exp))+'; }');\r
7359            }\r
7360        }\r
7361        if(name){\r
7362            switch(name){\r
7363                case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break;\r
7364                case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;\r
7365                default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }');\r
7366            }\r
7367        }\r
7368        tpls.push({\r
7369             id: id,\r
7370             target: name,\r
7371             exec: exec,\r
7372             test: fn,\r
7373             body: m[1]||''\r
7374         });\r
7375        s = s.replace(m[0], '{xtpl'+ id + '}');\r
7376        ++id;\r
7377     }\r
7378     for(var i = tpls.length-1; i >= 0; --i){\r
7379         this.compileTpl(tpls[i]);\r
7380     }\r
7381     this.master = tpls[tpls.length-1];\r
7382     this.tpls = tpls;\r
7383 };\r
7384 Ext.extend(Ext.XTemplate, Ext.Template, {\r
7385     // private\r
7386     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,\r
7387     // private\r
7388     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,\r
7389 \r
7390     // private\r
7391     applySubTemplate : function(id, values, parent, xindex, xcount){\r
7392         var t = this.tpls[id];\r
7393         if(t.test && !t.test.call(this, values, parent, xindex, xcount)){\r
7394             return '';\r
7395         }\r
7396         if(t.exec && t.exec.call(this, values, parent, xindex, xcount)){\r
7397             return '';\r
7398         }\r
7399         var vs = t.target ? t.target.call(this, values, parent) : values;\r
7400         parent = t.target ? values : parent;\r
7401         if(t.target && Ext.isArray(vs)){\r
7402             var buf = [];\r
7403             for(var i = 0, len = vs.length; i < len; i++){\r
7404                 buf[buf.length] = t.compiled.call(this, vs[i], parent, i+1, len);\r
7405             }\r
7406             return buf.join('');\r
7407         }\r
7408         return t.compiled.call(this, vs, parent, xindex, xcount);\r
7409     },\r
7410 \r
7411     // private\r
7412     compileTpl : function(tpl){\r
7413         var fm = Ext.util.Format;\r
7414         var useF = this.disableFormats !== true;\r
7415         var sep = Ext.isGecko ? "+" : ",";\r
7416         var fn = function(m, name, format, args, math){\r
7417             if(name.substr(0, 4) == 'xtpl'){\r
7418                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";\r
7419             }\r
7420             var v;\r
7421             if(name === '.'){\r
7422                 v = 'values';\r
7423             }else if(name === '#'){\r
7424                 v = 'xindex';\r
7425             }else if(name.indexOf('.') != -1){\r
7426                 v = name;\r
7427             }else{\r
7428                 v = "values['" + name + "']";\r
7429             }\r
7430             if(math){\r
7431                 v = '(' + v + math + ')';\r
7432             }\r
7433             if(format && useF){\r
7434                 args = args ? ',' + args : "";\r
7435                 if(format.substr(0, 5) != "this."){\r
7436                     format = "fm." + format + '(';\r
7437                 }else{\r
7438                     format = 'this.call("'+ format.substr(5) + '", ';\r
7439                     args = ", values";\r
7440                 }\r
7441             }else{\r
7442                 args= ''; format = "("+v+" === undefined ? '' : ";\r
7443             }\r
7444             return "'"+ sep + format + v + args + ")"+sep+"'";\r
7445         };\r
7446         var codeFn = function(m, code){\r
7447             return "'"+ sep +'('+code+')'+sep+"'";\r
7448         };\r
7449 \r
7450         var body;\r
7451         // branched to use + in gecko and [].join() in others\r
7452         if(Ext.isGecko){\r
7453             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +\r
7454                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +\r
7455                     "';};";\r
7456         }else{\r
7457             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];\r
7458             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));\r
7459             body.push("'].join('');};");\r
7460             body = body.join('');\r
7461         }\r
7462         eval(body);\r
7463         return this;\r
7464     },\r
7465 \r
7466     \r
7467     applyTemplate : function(values){\r
7468         return this.master.compiled.call(this, values, {}, 1, 1);\r
7469     },\r
7470 \r
7471     \r
7472     compile : function(){return this;}\r
7473 \r
7474     \r
7475     \r
7476     \r
7477 \r
7478 });\r
7479 \r
7480 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;\r
7481 \r
7482 \r
7483 Ext.XTemplate.from = function(el){\r
7484     el = Ext.getDom(el);\r
7485     return new Ext.XTemplate(el.value || el.innerHTML);\r
7486 };\r
7487 \r
7488 Ext.util.CSS = function(){\r
7489         var rules = null;\r
7490         var doc = document;\r
7491 \r
7492     var camelRe = /(-[a-z])/gi;\r
7493     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };\r
7494 \r
7495    return {\r
7496    \r
7497    createStyleSheet : function(cssText, id){\r
7498        var ss;\r
7499        var head = doc.getElementsByTagName("head")[0];\r
7500        var rules = doc.createElement("style");\r
7501        rules.setAttribute("type", "text/css");\r
7502        if(id){\r
7503            rules.setAttribute("id", id);\r
7504        }\r
7505        if(Ext.isIE){\r
7506            head.appendChild(rules);\r
7507            ss = rules.styleSheet;\r
7508            ss.cssText = cssText;\r
7509        }else{\r
7510            try{\r
7511                 rules.appendChild(doc.createTextNode(cssText));\r
7512            }catch(e){\r
7513                rules.cssText = cssText;\r
7514            }\r
7515            head.appendChild(rules);\r
7516            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);\r
7517        }\r
7518        this.cacheStyleSheet(ss);\r
7519        return ss;\r
7520    },\r
7521 \r
7522    \r
7523    removeStyleSheet : function(id){\r
7524        var existing = doc.getElementById(id);\r
7525        if(existing){\r
7526            existing.parentNode.removeChild(existing);\r
7527        }\r
7528    },\r
7529 \r
7530    \r
7531    swapStyleSheet : function(id, url){\r
7532        this.removeStyleSheet(id);\r
7533        var ss = doc.createElement("link");\r
7534        ss.setAttribute("rel", "stylesheet");\r
7535        ss.setAttribute("type", "text/css");\r
7536        ss.setAttribute("id", id);\r
7537        ss.setAttribute("href", url);\r
7538        doc.getElementsByTagName("head")[0].appendChild(ss);\r
7539    },\r
7540    \r
7541    \r
7542    refreshCache : function(){\r
7543        return this.getRules(true);\r
7544    },\r
7545 \r
7546    // private\r
7547    cacheStyleSheet : function(ss){\r
7548        if(!rules){\r
7549            rules = {};\r
7550        }\r
7551        try{// try catch for cross domain access issue\r
7552            var ssRules = ss.cssRules || ss.rules;\r
7553            for(var j = ssRules.length-1; j >= 0; --j){\r
7554                rules[ssRules[j].selectorText] = ssRules[j];\r
7555            }\r
7556        }catch(e){}\r
7557    },\r
7558    \r
7559    \r
7560    getRules : function(refreshCache){\r
7561                 if(rules == null || refreshCache){\r
7562                         rules = {};\r
7563                         var ds = doc.styleSheets;\r
7564                         for(var i =0, len = ds.length; i < len; i++){\r
7565                             try{\r
7566                         this.cacheStyleSheet(ds[i]);\r
7567                     }catch(e){} \r
7568                 }\r
7569                 }\r
7570                 return rules;\r
7571         },\r
7572         \r
7573         \r
7574    getRule : function(selector, refreshCache){\r
7575                 var rs = this.getRules(refreshCache);\r
7576                 if(!Ext.isArray(selector)){\r
7577                     return rs[selector];\r
7578                 }\r
7579                 for(var i = 0; i < selector.length; i++){\r
7580                         if(rs[selector[i]]){\r
7581                                 return rs[selector[i]];\r
7582                         }\r
7583                 }\r
7584                 return null;\r
7585         },\r
7586         \r
7587         \r
7588         \r
7589    updateRule : function(selector, property, value){\r
7590                 if(!Ext.isArray(selector)){\r
7591                         var rule = this.getRule(selector);\r
7592                         if(rule){\r
7593                                 rule.style[property.replace(camelRe, camelFn)] = value;\r
7594                                 return true;\r
7595                         }\r
7596                 }else{\r
7597                         for(var i = 0; i < selector.length; i++){\r
7598                                 if(this.updateRule(selector[i], property, value)){\r
7599                                         return true;\r
7600                                 }\r
7601                         }\r
7602                 }\r
7603                 return false;\r
7604         }\r
7605    };   \r
7606 }();\r
7607 \r
7608 Ext.util.ClickRepeater = function(el, config)\r
7609 {\r
7610     this.el = Ext.get(el);\r
7611     this.el.unselectable();\r
7612 \r
7613     Ext.apply(this, config);\r
7614 \r
7615     this.addEvents(\r
7616     \r
7617         "mousedown",\r
7618     \r
7619         "click",\r
7620     \r
7621         "mouseup"\r
7622     );\r
7623 \r
7624     this.el.on("mousedown", this.handleMouseDown, this);\r
7625     if(this.preventDefault || this.stopDefault){\r
7626         this.el.on("click", function(e){\r
7627             if(this.preventDefault){\r
7628                 e.preventDefault();\r
7629             }\r
7630             if(this.stopDefault){\r
7631                 e.stopEvent();\r
7632             }\r
7633         }, this);\r
7634     }\r
7635 \r
7636     // allow inline handler\r
7637     if(this.handler){\r
7638         this.on("click", this.handler,  this.scope || this);\r
7639     }\r
7640 \r
7641     Ext.util.ClickRepeater.superclass.constructor.call(this);\r
7642 };\r
7643 \r
7644 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {\r
7645     interval : 20,\r
7646     delay: 250,\r
7647     preventDefault : true,\r
7648     stopDefault : false,\r
7649     timer : 0,\r
7650 \r
7651     // private\r
7652     destroy : function() {\r
7653         Ext.destroy(this.el);\r
7654         this.purgeListeners();\r
7655     },\r
7656     \r
7657     // private\r
7658     handleMouseDown : function(){\r
7659         clearTimeout(this.timer);\r
7660         this.el.blur();\r
7661         if(this.pressClass){\r
7662             this.el.addClass(this.pressClass);\r
7663         }\r
7664         this.mousedownTime = new Date();\r
7665 \r
7666         Ext.getDoc().on("mouseup", this.handleMouseUp, this);\r
7667         this.el.on("mouseout", this.handleMouseOut, this);\r
7668 \r
7669         this.fireEvent("mousedown", this);\r
7670         this.fireEvent("click", this);\r
7671 \r
7672 //      Do not honor delay or interval if acceleration wanted.\r
7673         if (this.accelerate) {\r
7674             this.delay = 400;\r
7675             }\r
7676         this.timer = this.click.defer(this.delay || this.interval, this);\r
7677     },\r
7678 \r
7679     // private\r
7680     click : function(){\r
7681         this.fireEvent("click", this);\r
7682         this.timer = this.click.defer(this.accelerate ?\r
7683             this.easeOutExpo(this.mousedownTime.getElapsed(),\r
7684                 400,\r
7685                 -390,\r
7686                 12000) :\r
7687             this.interval, this);\r
7688     },\r
7689 \r
7690     easeOutExpo : function (t, b, c, d) {\r
7691         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;\r
7692     },\r
7693 \r
7694     // private\r
7695     handleMouseOut : function(){\r
7696         clearTimeout(this.timer);\r
7697         if(this.pressClass){\r
7698             this.el.removeClass(this.pressClass);\r
7699         }\r
7700         this.el.on("mouseover", this.handleMouseReturn, this);\r
7701     },\r
7702 \r
7703     // private\r
7704     handleMouseReturn : function(){\r
7705         this.el.un("mouseover", this.handleMouseReturn, this);\r
7706         if(this.pressClass){\r
7707             this.el.addClass(this.pressClass);\r
7708         }\r
7709         this.click();\r
7710     },\r
7711 \r
7712     // private\r
7713     handleMouseUp : function(){\r
7714         clearTimeout(this.timer);\r
7715         this.el.un("mouseover", this.handleMouseReturn, this);\r
7716         this.el.un("mouseout", this.handleMouseOut, this);\r
7717         Ext.getDoc().un("mouseup", this.handleMouseUp, this);\r
7718         this.el.removeClass(this.pressClass);\r
7719         this.fireEvent("mouseup", this);\r
7720     }\r
7721 });\r
7722 \r
7723 Ext.KeyNav = function(el, config){\r
7724     this.el = Ext.get(el);\r
7725     Ext.apply(this, config);\r
7726     if(!this.disabled){\r
7727         this.disabled = true;\r
7728         this.enable();\r
7729     }\r
7730 };\r
7731 \r
7732 Ext.KeyNav.prototype = {\r
7733     \r
7734     disabled : false,\r
7735     \r
7736     defaultEventAction: "stopEvent",\r
7737     \r
7738     forceKeyDown : false,\r
7739 \r
7740     // private\r
7741     prepareEvent : function(e){\r
7742         var k = e.getKey();\r
7743         var h = this.keyToHandler[k];\r
7744         //if(h && this[h]){\r
7745         //    e.stopPropagation();\r
7746         //}\r
7747         if(Ext.isSafari2 && h && k >= 37 && k <= 40){\r
7748             e.stopEvent();\r
7749         }\r
7750     },\r
7751 \r
7752     // private\r
7753     relay : function(e){\r
7754         var k = e.getKey();\r
7755         var h = this.keyToHandler[k];\r
7756         if(h && this[h]){\r
7757             if(this.doRelay(e, this[h], h) !== true){\r
7758                 e[this.defaultEventAction]();\r
7759             }\r
7760         }\r
7761     },\r
7762 \r
7763     // private\r
7764     doRelay : function(e, h, hname){\r
7765         return h.call(this.scope || this, e);\r
7766     },\r
7767 \r
7768     // possible handlers\r
7769     enter : false,\r
7770     left : false,\r
7771     right : false,\r
7772     up : false,\r
7773     down : false,\r
7774     tab : false,\r
7775     esc : false,\r
7776     pageUp : false,\r
7777     pageDown : false,\r
7778     del : false,\r
7779     home : false,\r
7780     end : false,\r
7781 \r
7782     // quick lookup hash\r
7783     keyToHandler : {\r
7784         37 : "left",\r
7785         39 : "right",\r
7786         38 : "up",\r
7787         40 : "down",\r
7788         33 : "pageUp",\r
7789         34 : "pageDown",\r
7790         46 : "del",\r
7791         36 : "home",\r
7792         35 : "end",\r
7793         13 : "enter",\r
7794         27 : "esc",\r
7795         9  : "tab"\r
7796     },\r
7797 \r
7798         \r
7799         enable: function(){\r
7800                 if(this.disabled){\r
7801             if(this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir){\r
7802                 this.el.on("keydown", this.relay,  this);\r
7803             }else{\r
7804                 this.el.on("keydown", this.prepareEvent,  this);\r
7805                 this.el.on("keypress", this.relay,  this);\r
7806             }\r
7807                     this.disabled = false;\r
7808                 }\r
7809         },\r
7810 \r
7811         \r
7812         disable: function(){\r
7813                 if(!this.disabled){\r
7814                     if(this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir){\r
7815                 this.el.un("keydown", this.relay, this);\r
7816             }else{\r
7817                 this.el.un("keydown", this.prepareEvent, this);\r
7818                 this.el.un("keypress", this.relay, this);\r
7819             }\r
7820                     this.disabled = true;\r
7821                 }\r
7822         }\r
7823 };\r
7824 \r
7825 Ext.KeyMap = function(el, config, eventName){\r
7826     this.el  = Ext.get(el);\r
7827     this.eventName = eventName || "keydown";\r
7828     this.bindings = [];\r
7829     if(config){\r
7830         this.addBinding(config);\r
7831     }\r
7832     this.enable();\r
7833 };\r
7834 \r
7835 Ext.KeyMap.prototype = {\r
7836     \r
7837     stopEvent : false,\r
7838 \r
7839     \r
7840         addBinding : function(config){\r
7841         if(Ext.isArray(config)){\r
7842             for(var i = 0, len = config.length; i < len; i++){\r
7843                 this.addBinding(config[i]);\r
7844             }\r
7845             return;\r
7846         }\r
7847         var keyCode = config.key,\r
7848             shift = config.shift,\r
7849             ctrl = config.ctrl,\r
7850             alt = config.alt,\r
7851             fn = config.fn || config.handler,\r
7852             scope = config.scope;\r
7853         \r
7854         if (config.stopEvent) {\r
7855             this.stopEvent = config.stopEvent;    \r
7856         }       \r
7857 \r
7858         if(typeof keyCode == "string"){\r
7859             var ks = [];\r
7860             var keyString = keyCode.toUpperCase();\r
7861             for(var j = 0, len = keyString.length; j < len; j++){\r
7862                 ks.push(keyString.charCodeAt(j));\r
7863             }\r
7864             keyCode = ks;\r
7865         }\r
7866         var keyArray = Ext.isArray(keyCode);\r
7867         \r
7868         var handler = function(e){\r
7869             if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){\r
7870                 var k = e.getKey();\r
7871                 if(keyArray){\r
7872                     for(var i = 0, len = keyCode.length; i < len; i++){\r
7873                         if(keyCode[i] == k){\r
7874                           if(this.stopEvent){\r
7875                               e.stopEvent();\r
7876                           }\r
7877                           fn.call(scope || window, k, e);\r
7878                           return;\r
7879                         }\r
7880                     }\r
7881                 }else{\r
7882                     if(k == keyCode){\r
7883                         if(this.stopEvent){\r
7884                            e.stopEvent();\r
7885                         }\r
7886                         fn.call(scope || window, k, e);\r
7887                     }\r
7888                 }\r
7889             }\r
7890         };\r
7891         this.bindings.push(handler);\r
7892         },\r
7893 \r
7894     \r
7895     on : function(key, fn, scope){\r
7896         var keyCode, shift, ctrl, alt;\r
7897         if(typeof key == "object" && !Ext.isArray(key)){\r
7898             keyCode = key.key;\r
7899             shift = key.shift;\r
7900             ctrl = key.ctrl;\r
7901             alt = key.alt;\r
7902         }else{\r
7903             keyCode = key;\r
7904         }\r
7905         this.addBinding({\r
7906             key: keyCode,\r
7907             shift: shift,\r
7908             ctrl: ctrl,\r
7909             alt: alt,\r
7910             fn: fn,\r
7911             scope: scope\r
7912         })\r
7913     },\r
7914 \r
7915     // private\r
7916     handleKeyDown : function(e){\r
7917             if(this.enabled){ //just in case\r
7918             var b = this.bindings;\r
7919             for(var i = 0, len = b.length; i < len; i++){\r
7920                 b[i].call(this, e);\r
7921             }\r
7922             }\r
7923         },\r
7924 \r
7925         \r
7926         isEnabled : function(){\r
7927             return this.enabled;\r
7928         },\r
7929 \r
7930         \r
7931         enable: function(){\r
7932                 if(!this.enabled){\r
7933                     this.el.on(this.eventName, this.handleKeyDown, this);\r
7934                     this.enabled = true;\r
7935                 }\r
7936         },\r
7937 \r
7938         \r
7939         disable: function(){\r
7940                 if(this.enabled){\r
7941                     this.el.removeListener(this.eventName, this.handleKeyDown, this);\r
7942                     this.enabled = false;\r
7943                 }\r
7944         }\r
7945 };\r
7946 \r
7947 Ext.util.TextMetrics = function(){\r
7948     var shared;\r
7949     return {\r
7950         \r
7951         measure : function(el, text, fixedWidth){\r
7952             if(!shared){\r
7953                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);\r
7954             }\r
7955             shared.bind(el);\r
7956             shared.setFixedWidth(fixedWidth || 'auto');\r
7957             return shared.getSize(text);\r
7958         },\r
7959 \r
7960         \r
7961         createInstance : function(el, fixedWidth){\r
7962             return Ext.util.TextMetrics.Instance(el, fixedWidth);\r
7963         }\r
7964     };\r
7965 }();\r
7966 \r
7967 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){\r
7968     var ml = new Ext.Element(document.createElement('div'));\r
7969     document.body.appendChild(ml.dom);\r
7970     ml.position('absolute');\r
7971     ml.setLeftTop(-1000, -1000);\r
7972     ml.hide();\r
7973 \r
7974     if(fixedWidth){\r
7975         ml.setWidth(fixedWidth);\r
7976     }\r
7977 \r
7978     var instance = {\r
7979         \r
7980         getSize : function(text){\r
7981             ml.update(text);\r
7982             var s = ml.getSize();\r
7983             ml.update('');\r
7984             return s;\r
7985         },\r
7986 \r
7987         \r
7988         bind : function(el){\r
7989             ml.setStyle(\r
7990                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')\r
7991             );\r
7992         },\r
7993 \r
7994         \r
7995         setFixedWidth : function(width){\r
7996             ml.setWidth(width);\r
7997         },\r
7998 \r
7999         \r
8000         getWidth : function(text){\r
8001             ml.dom.style.width = 'auto';\r
8002             return this.getSize(text).width;\r
8003         },\r
8004 \r
8005         \r
8006         getHeight : function(text){\r
8007             return this.getSize(text).height;\r
8008         }\r
8009     };\r
8010 \r
8011     instance.bind(bindTo);\r
8012 \r
8013     return instance;\r
8014 };\r
8015 \r
8016 // backwards compat\r
8017 Ext.Element.measureText = Ext.util.TextMetrics.measure;\r
8018 \r
8019 \r
8020 (function() {\r
8021 \r
8022 var Event=Ext.EventManager;\r
8023 var Dom=Ext.lib.Dom;\r
8024 \r
8025 \r
8026 Ext.dd.DragDrop = function(id, sGroup, config) {\r
8027     if(id) {\r
8028         this.init(id, sGroup, config);\r
8029     }\r
8030 };\r
8031 \r
8032 Ext.dd.DragDrop.prototype = {\r
8033 \r
8034     \r
8035     id: null,\r
8036 \r
8037     \r
8038     config: null,\r
8039 \r
8040     \r
8041     dragElId: null,\r
8042 \r
8043     \r
8044     handleElId: null,\r
8045 \r
8046     \r
8047     invalidHandleTypes: null,\r
8048 \r
8049     \r
8050     invalidHandleIds: null,\r
8051 \r
8052     \r
8053     invalidHandleClasses: null,\r
8054 \r
8055     \r
8056     startPageX: 0,\r
8057 \r
8058     \r
8059     startPageY: 0,\r
8060 \r
8061     \r
8062     groups: null,\r
8063 \r
8064     \r
8065     locked: false,\r
8066 \r
8067     \r
8068     lock: function() { this.locked = true; },\r
8069 \r
8070     \r
8071     moveOnly: false,\r
8072 \r
8073     \r
8074     unlock: function() { this.locked = false; },\r
8075 \r
8076     \r
8077     isTarget: true,\r
8078 \r
8079     \r
8080     padding: null,\r
8081 \r
8082     \r
8083     _domRef: null,\r
8084 \r
8085     \r
8086     __ygDragDrop: true,\r
8087 \r
8088     \r
8089     constrainX: false,\r
8090 \r
8091     \r
8092     constrainY: false,\r
8093 \r
8094     \r
8095     minX: 0,\r
8096 \r
8097     \r
8098     maxX: 0,\r
8099 \r
8100     \r
8101     minY: 0,\r
8102 \r
8103     \r
8104     maxY: 0,\r
8105 \r
8106     \r
8107     maintainOffset: false,\r
8108 \r
8109     \r
8110     xTicks: null,\r
8111 \r
8112     \r
8113     yTicks: null,\r
8114 \r
8115     \r
8116     primaryButtonOnly: true,\r
8117 \r
8118     \r
8119     available: false,\r
8120 \r
8121     \r
8122     hasOuterHandles: false,\r
8123 \r
8124     \r
8125     b4StartDrag: function(x, y) { },\r
8126 \r
8127     \r
8128     startDrag: function(x, y) {  },\r
8129 \r
8130     \r
8131     b4Drag: function(e) { },\r
8132 \r
8133     \r
8134     onDrag: function(e) {  },\r
8135 \r
8136     \r
8137     onDragEnter: function(e, id) {  },\r
8138 \r
8139     \r
8140     b4DragOver: function(e) { },\r
8141 \r
8142     \r
8143     onDragOver: function(e, id) {  },\r
8144 \r
8145     \r
8146     b4DragOut: function(e) { },\r
8147 \r
8148     \r
8149     onDragOut: function(e, id) {  },\r
8150 \r
8151     \r
8152     b4DragDrop: function(e) { },\r
8153 \r
8154     \r
8155     onDragDrop: function(e, id) {  },\r
8156 \r
8157     \r
8158     onInvalidDrop: function(e) {  },\r
8159 \r
8160     \r
8161     b4EndDrag: function(e) { },\r
8162 \r
8163     \r
8164     endDrag: function(e) {  },\r
8165 \r
8166     \r
8167     b4MouseDown: function(e) {  },\r
8168 \r
8169     \r
8170     onMouseDown: function(e) {  },\r
8171 \r
8172     \r
8173     onMouseUp: function(e) {  },\r
8174 \r
8175     \r
8176     onAvailable: function () {\r
8177     },\r
8178 \r
8179     \r
8180     defaultPadding : {left:0, right:0, top:0, bottom:0},\r
8181 \r
8182     \r
8183     constrainTo : function(constrainTo, pad, inContent){\r
8184         if(typeof pad == "number"){\r
8185             pad = {left: pad, right:pad, top:pad, bottom:pad};\r
8186         }\r
8187         pad = pad || this.defaultPadding;\r
8188         var b = Ext.get(this.getEl()).getBox();\r
8189         var ce = Ext.get(constrainTo);\r
8190         var s = ce.getScroll();\r
8191         var c, cd = ce.dom;\r
8192         if(cd == document.body){\r
8193             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};\r
8194         }else{\r
8195             var xy = ce.getXY();\r
8196             c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};\r
8197         }\r
8198 \r
8199 \r
8200         var topSpace = b.y - c.y;\r
8201         var leftSpace = b.x - c.x;\r
8202 \r
8203         this.resetConstraints();\r
8204         this.setXConstraint(leftSpace - (pad.left||0), // left\r
8205                 c.width - leftSpace - b.width - (pad.right||0), //right\r
8206                                 this.xTickSize\r
8207         );\r
8208         this.setYConstraint(topSpace - (pad.top||0), //top\r
8209                 c.height - topSpace - b.height - (pad.bottom||0), //bottom\r
8210                                 this.yTickSize\r
8211         );\r
8212     },\r
8213 \r
8214     \r
8215     getEl: function() {\r
8216         if (!this._domRef) {\r
8217             this._domRef = Ext.getDom(this.id);\r
8218         }\r
8219 \r
8220         return this._domRef;\r
8221     },\r
8222 \r
8223     \r
8224     getDragEl: function() {\r
8225         return Ext.getDom(this.dragElId);\r
8226     },\r
8227 \r
8228     \r
8229     init: function(id, sGroup, config) {\r
8230         this.initTarget(id, sGroup, config);\r
8231         Event.on(this.id, "mousedown", this.handleMouseDown, this);\r
8232         // Event.on(this.id, "selectstart", Event.preventDefault);\r
8233     },\r
8234 \r
8235     \r
8236     initTarget: function(id, sGroup, config) {\r
8237 \r
8238         // configuration attributes\r
8239         this.config = config || {};\r
8240 \r
8241         // create a local reference to the drag and drop manager\r
8242         this.DDM = Ext.dd.DDM;\r
8243         // initialize the groups array\r
8244         this.groups = {};\r
8245 \r
8246         // assume that we have an element reference instead of an id if the\r
8247         // parameter is not a string\r
8248         if (typeof id !== "string") {\r
8249             id = Ext.id(id);\r
8250         }\r
8251 \r
8252         // set the id\r
8253         this.id = id;\r
8254 \r
8255         // add to an interaction group\r
8256         this.addToGroup((sGroup) ? sGroup : "default");\r
8257 \r
8258         // We don't want to register this as the handle with the manager\r
8259         // so we just set the id rather than calling the setter.\r
8260         this.handleElId = id;\r
8261 \r
8262         // the linked element is the element that gets dragged by default\r
8263         this.setDragElId(id);\r
8264 \r
8265         // by default, clicked anchors will not start drag operations.\r
8266         this.invalidHandleTypes = { A: "A" };\r
8267         this.invalidHandleIds = {};\r
8268         this.invalidHandleClasses = [];\r
8269 \r
8270         this.applyConfig();\r
8271 \r
8272         this.handleOnAvailable();\r
8273     },\r
8274 \r
8275     \r
8276     applyConfig: function() {\r
8277 \r
8278         // configurable properties:\r
8279         //    padding, isTarget, maintainOffset, primaryButtonOnly\r
8280         this.padding           = this.config.padding || [0, 0, 0, 0];\r
8281         this.isTarget          = (this.config.isTarget !== false);\r
8282         this.maintainOffset    = (this.config.maintainOffset);\r
8283         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);\r
8284 \r
8285     },\r
8286 \r
8287     \r
8288     handleOnAvailable: function() {\r
8289         this.available = true;\r
8290         this.resetConstraints();\r
8291         this.onAvailable();\r
8292     },\r
8293 \r
8294      \r
8295     setPadding: function(iTop, iRight, iBot, iLeft) {\r
8296         // this.padding = [iLeft, iRight, iTop, iBot];\r
8297         if (!iRight && 0 !== iRight) {\r
8298             this.padding = [iTop, iTop, iTop, iTop];\r
8299         } else if (!iBot && 0 !== iBot) {\r
8300             this.padding = [iTop, iRight, iTop, iRight];\r
8301         } else {\r
8302             this.padding = [iTop, iRight, iBot, iLeft];\r
8303         }\r
8304     },\r
8305 \r
8306     \r
8307     setInitPosition: function(diffX, diffY) {\r
8308         var el = this.getEl();\r
8309 \r
8310         if (!this.DDM.verifyEl(el)) {\r
8311             return;\r
8312         }\r
8313 \r
8314         var dx = diffX || 0;\r
8315         var dy = diffY || 0;\r
8316 \r
8317         var p = Dom.getXY( el );\r
8318 \r
8319         this.initPageX = p[0] - dx;\r
8320         this.initPageY = p[1] - dy;\r
8321 \r
8322         this.lastPageX = p[0];\r
8323         this.lastPageY = p[1];\r
8324 \r
8325 \r
8326         this.setStartPosition(p);\r
8327     },\r
8328 \r
8329     \r
8330     setStartPosition: function(pos) {\r
8331         var p = pos || Dom.getXY( this.getEl() );\r
8332         this.deltaSetXY = null;\r
8333 \r
8334         this.startPageX = p[0];\r
8335         this.startPageY = p[1];\r
8336     },\r
8337 \r
8338     \r
8339     addToGroup: function(sGroup) {\r
8340         this.groups[sGroup] = true;\r
8341         this.DDM.regDragDrop(this, sGroup);\r
8342     },\r
8343 \r
8344     \r
8345     removeFromGroup: function(sGroup) {\r
8346         if (this.groups[sGroup]) {\r
8347             delete this.groups[sGroup];\r
8348         }\r
8349 \r
8350         this.DDM.removeDDFromGroup(this, sGroup);\r
8351     },\r
8352 \r
8353     \r
8354     setDragElId: function(id) {\r
8355         this.dragElId = id;\r
8356     },\r
8357 \r
8358     \r
8359     setHandleElId: function(id) {\r
8360         if (typeof id !== "string") {\r
8361             id = Ext.id(id);\r
8362         }\r
8363         this.handleElId = id;\r
8364         this.DDM.regHandle(this.id, id);\r
8365     },\r
8366 \r
8367     \r
8368     setOuterHandleElId: function(id) {\r
8369         if (typeof id !== "string") {\r
8370             id = Ext.id(id);\r
8371         }\r
8372         Event.on(id, "mousedown",\r
8373                 this.handleMouseDown, this);\r
8374         this.setHandleElId(id);\r
8375 \r
8376         this.hasOuterHandles = true;\r
8377     },\r
8378 \r
8379     \r
8380     unreg: function() {\r
8381         Event.un(this.id, "mousedown",\r
8382                 this.handleMouseDown);\r
8383         this._domRef = null;\r
8384         this.DDM._remove(this);\r
8385     },\r
8386 \r
8387     destroy : function(){\r
8388         this.unreg();\r
8389     },\r
8390 \r
8391     \r
8392     isLocked: function() {\r
8393         return (this.DDM.isLocked() || this.locked);\r
8394     },\r
8395 \r
8396     \r
8397     handleMouseDown: function(e, oDD){\r
8398         if (this.primaryButtonOnly && e.button != 0) {\r
8399             return;\r
8400         }\r
8401 \r
8402         if (this.isLocked()) {\r
8403             return;\r
8404         }\r
8405 \r
8406         this.DDM.refreshCache(this.groups);\r
8407 \r
8408         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));\r
8409         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {\r
8410         } else {\r
8411             if (this.clickValidator(e)) {\r
8412 \r
8413                 // set the initial element position\r
8414                 this.setStartPosition();\r
8415 \r
8416 \r
8417                 this.b4MouseDown(e);\r
8418                 this.onMouseDown(e);\r
8419 \r
8420                 this.DDM.handleMouseDown(e, this);\r
8421 \r
8422                 this.DDM.stopEvent(e);\r
8423             } else {\r
8424 \r
8425 \r
8426             }\r
8427         }\r
8428     },\r
8429 \r
8430     clickValidator: function(e) {\r
8431         var target = e.getTarget();\r
8432         return ( this.isValidHandleChild(target) &&\r
8433                     (this.id == this.handleElId ||\r
8434                         this.DDM.handleWasClicked(target, this.id)) );\r
8435     },\r
8436 \r
8437     \r
8438     addInvalidHandleType: function(tagName) {\r
8439         var type = tagName.toUpperCase();\r
8440         this.invalidHandleTypes[type] = type;\r
8441     },\r
8442 \r
8443     \r
8444     addInvalidHandleId: function(id) {\r
8445         if (typeof id !== "string") {\r
8446             id = Ext.id(id);\r
8447         }\r
8448         this.invalidHandleIds[id] = id;\r
8449     },\r
8450 \r
8451     \r
8452     addInvalidHandleClass: function(cssClass) {\r
8453         this.invalidHandleClasses.push(cssClass);\r
8454     },\r
8455 \r
8456     \r
8457     removeInvalidHandleType: function(tagName) {\r
8458         var type = tagName.toUpperCase();\r
8459         // this.invalidHandleTypes[type] = null;\r
8460         delete this.invalidHandleTypes[type];\r
8461     },\r
8462 \r
8463     \r
8464     removeInvalidHandleId: function(id) {\r
8465         if (typeof id !== "string") {\r
8466             id = Ext.id(id);\r
8467         }\r
8468         delete this.invalidHandleIds[id];\r
8469     },\r
8470 \r
8471     \r
8472     removeInvalidHandleClass: function(cssClass) {\r
8473         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {\r
8474             if (this.invalidHandleClasses[i] == cssClass) {\r
8475                 delete this.invalidHandleClasses[i];\r
8476             }\r
8477         }\r
8478     },\r
8479 \r
8480     \r
8481     isValidHandleChild: function(node) {\r
8482 \r
8483         var valid = true;\r
8484         // var n = (node.nodeName == "#text") ? node.parentNode : node;\r
8485         var nodeName;\r
8486         try {\r
8487             nodeName = node.nodeName.toUpperCase();\r
8488         } catch(e) {\r
8489             nodeName = node.nodeName;\r
8490         }\r
8491         valid = valid && !this.invalidHandleTypes[nodeName];\r
8492         valid = valid && !this.invalidHandleIds[node.id];\r
8493 \r
8494         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {\r
8495             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);\r
8496         }\r
8497 \r
8498 \r
8499         return valid;\r
8500 \r
8501     },\r
8502 \r
8503     \r
8504     setXTicks: function(iStartX, iTickSize) {\r
8505         this.xTicks = [];\r
8506         this.xTickSize = iTickSize;\r
8507 \r
8508         var tickMap = {};\r
8509 \r
8510         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {\r
8511             if (!tickMap[i]) {\r
8512                 this.xTicks[this.xTicks.length] = i;\r
8513                 tickMap[i] = true;\r
8514             }\r
8515         }\r
8516 \r
8517         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {\r
8518             if (!tickMap[i]) {\r
8519                 this.xTicks[this.xTicks.length] = i;\r
8520                 tickMap[i] = true;\r
8521             }\r
8522         }\r
8523 \r
8524         this.xTicks.sort(this.DDM.numericSort) ;\r
8525     },\r
8526 \r
8527     \r
8528     setYTicks: function(iStartY, iTickSize) {\r
8529         this.yTicks = [];\r
8530         this.yTickSize = iTickSize;\r
8531 \r
8532         var tickMap = {};\r
8533 \r
8534         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {\r
8535             if (!tickMap[i]) {\r
8536                 this.yTicks[this.yTicks.length] = i;\r
8537                 tickMap[i] = true;\r
8538             }\r
8539         }\r
8540 \r
8541         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {\r
8542             if (!tickMap[i]) {\r
8543                 this.yTicks[this.yTicks.length] = i;\r
8544                 tickMap[i] = true;\r
8545             }\r
8546         }\r
8547 \r
8548         this.yTicks.sort(this.DDM.numericSort) ;\r
8549     },\r
8550 \r
8551     \r
8552     setXConstraint: function(iLeft, iRight, iTickSize) {\r
8553         this.leftConstraint = iLeft;\r
8554         this.rightConstraint = iRight;\r
8555 \r
8556         this.minX = this.initPageX - iLeft;\r
8557         this.maxX = this.initPageX + iRight;\r
8558         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }\r
8559 \r
8560         this.constrainX = true;\r
8561     },\r
8562 \r
8563     \r
8564     clearConstraints: function() {\r
8565         this.constrainX = false;\r
8566         this.constrainY = false;\r
8567         this.clearTicks();\r
8568     },\r
8569 \r
8570     \r
8571     clearTicks: function() {\r
8572         this.xTicks = null;\r
8573         this.yTicks = null;\r
8574         this.xTickSize = 0;\r
8575         this.yTickSize = 0;\r
8576     },\r
8577 \r
8578     \r
8579     setYConstraint: function(iUp, iDown, iTickSize) {\r
8580         this.topConstraint = iUp;\r
8581         this.bottomConstraint = iDown;\r
8582 \r
8583         this.minY = this.initPageY - iUp;\r
8584         this.maxY = this.initPageY + iDown;\r
8585         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }\r
8586 \r
8587         this.constrainY = true;\r
8588 \r
8589     },\r
8590 \r
8591     \r
8592     resetConstraints: function() {\r
8593 \r
8594 \r
8595         // Maintain offsets if necessary\r
8596         if (this.initPageX || this.initPageX === 0) {\r
8597             // figure out how much this thing has moved\r
8598             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;\r
8599             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;\r
8600 \r
8601             this.setInitPosition(dx, dy);\r
8602 \r
8603         // This is the first time we have detected the element's position\r
8604         } else {\r
8605             this.setInitPosition();\r
8606         }\r
8607 \r
8608         if (this.constrainX) {\r
8609             this.setXConstraint( this.leftConstraint,\r
8610                                  this.rightConstraint,\r
8611                                  this.xTickSize        );\r
8612         }\r
8613 \r
8614         if (this.constrainY) {\r
8615             this.setYConstraint( this.topConstraint,\r
8616                                  this.bottomConstraint,\r
8617                                  this.yTickSize         );\r
8618         }\r
8619     },\r
8620 \r
8621     \r
8622     getTick: function(val, tickArray) {\r
8623 \r
8624         if (!tickArray) {\r
8625             // If tick interval is not defined, it is effectively 1 pixel,\r
8626             // so we return the value passed to us.\r
8627             return val;\r
8628         } else if (tickArray[0] >= val) {\r
8629             // The value is lower than the first tick, so we return the first\r
8630             // tick.\r
8631             return tickArray[0];\r
8632         } else {\r
8633             for (var i=0, len=tickArray.length; i<len; ++i) {\r
8634                 var next = i + 1;\r
8635                 if (tickArray[next] && tickArray[next] >= val) {\r
8636                     var diff1 = val - tickArray[i];\r
8637                     var diff2 = tickArray[next] - val;\r
8638                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];\r
8639                 }\r
8640             }\r
8641 \r
8642             // The value is larger than the last tick, so we return the last\r
8643             // tick.\r
8644             return tickArray[tickArray.length - 1];\r
8645         }\r
8646     },\r
8647 \r
8648     \r
8649     toString: function() {\r
8650         return ("DragDrop " + this.id);\r
8651     }\r
8652 \r
8653 };\r
8654 \r
8655 })();\r
8656 \r
8657 \r
8658 // Only load the library once.  Rewriting the manager class would orphan\r
8659 // existing drag and drop instances.\r
8660 if (!Ext.dd.DragDropMgr) {\r
8661 \r
8662 \r
8663 Ext.dd.DragDropMgr = function() {\r
8664 \r
8665     var Event = Ext.EventManager;\r
8666 \r
8667     return {\r
8668 \r
8669         \r
8670         ids: {},\r
8671 \r
8672         \r
8673         handleIds: {},\r
8674 \r
8675         \r
8676         dragCurrent: null,\r
8677 \r
8678         \r
8679         dragOvers: {},\r
8680 \r
8681         \r
8682         deltaX: 0,\r
8683 \r
8684         \r
8685         deltaY: 0,\r
8686 \r
8687         \r
8688         preventDefault: true,\r
8689 \r
8690         \r
8691         stopPropagation: true,\r
8692 \r
8693         \r
8694         initialized: false,\r
8695 \r
8696         \r
8697         locked: false,\r
8698 \r
8699         \r
8700         init: function() {\r
8701             this.initialized = true;\r
8702         },\r
8703 \r
8704         \r
8705         POINT: 0,\r
8706 \r
8707         \r
8708         INTERSECT: 1,\r
8709 \r
8710         \r
8711         mode: 0,\r
8712 \r
8713         \r
8714         _execOnAll: function(sMethod, args) {\r
8715             for (var i in this.ids) {\r
8716                 for (var j in this.ids[i]) {\r
8717                     var oDD = this.ids[i][j];\r
8718                     if (! this.isTypeOfDD(oDD)) {\r
8719                         continue;\r
8720                     }\r
8721                     oDD[sMethod].apply(oDD, args);\r
8722                 }\r
8723             }\r
8724         },\r
8725 \r
8726         \r
8727         _onLoad: function() {\r
8728 \r
8729             this.init();\r
8730 \r
8731 \r
8732             Event.on(document, "mouseup",   this.handleMouseUp, this, true);\r
8733             Event.on(document, "mousemove", this.handleMouseMove, this, true);\r
8734             Event.on(window,   "unload",    this._onUnload, this, true);\r
8735             Event.on(window,   "resize",    this._onResize, this, true);\r
8736             // Event.on(window,   "mouseout",    this._test);\r
8737 \r
8738         },\r
8739 \r
8740         \r
8741         _onResize: function(e) {\r
8742             this._execOnAll("resetConstraints", []);\r
8743         },\r
8744 \r
8745         \r
8746         lock: function() { this.locked = true; },\r
8747 \r
8748         \r
8749         unlock: function() { this.locked = false; },\r
8750 \r
8751         \r
8752         isLocked: function() { return this.locked; },\r
8753 \r
8754         \r
8755         locationCache: {},\r
8756 \r
8757         \r
8758         useCache: true,\r
8759 \r
8760         \r
8761         clickPixelThresh: 3,\r
8762 \r
8763         \r
8764         clickTimeThresh: 350,\r
8765 \r
8766         \r
8767         dragThreshMet: false,\r
8768 \r
8769         \r
8770         clickTimeout: null,\r
8771 \r
8772         \r
8773         startX: 0,\r
8774 \r
8775         \r
8776         startY: 0,\r
8777 \r
8778         \r
8779         regDragDrop: function(oDD, sGroup) {\r
8780             if (!this.initialized) { this.init(); }\r
8781 \r
8782             if (!this.ids[sGroup]) {\r
8783                 this.ids[sGroup] = {};\r
8784             }\r
8785             this.ids[sGroup][oDD.id] = oDD;\r
8786         },\r
8787 \r
8788         \r
8789         removeDDFromGroup: function(oDD, sGroup) {\r
8790             if (!this.ids[sGroup]) {\r
8791                 this.ids[sGroup] = {};\r
8792             }\r
8793 \r
8794             var obj = this.ids[sGroup];\r
8795             if (obj && obj[oDD.id]) {\r
8796                 delete obj[oDD.id];\r
8797             }\r
8798         },\r
8799 \r
8800         \r
8801         _remove: function(oDD) {\r
8802             for (var g in oDD.groups) {\r
8803                 if (g && this.ids[g] && this.ids[g][oDD.id]) {\r
8804                     delete this.ids[g][oDD.id];\r
8805                 }\r
8806             }\r
8807             delete this.handleIds[oDD.id];\r
8808         },\r
8809 \r
8810         \r
8811         regHandle: function(sDDId, sHandleId) {\r
8812             if (!this.handleIds[sDDId]) {\r
8813                 this.handleIds[sDDId] = {};\r
8814             }\r
8815             this.handleIds[sDDId][sHandleId] = sHandleId;\r
8816         },\r
8817 \r
8818         \r
8819         isDragDrop: function(id) {\r
8820             return ( this.getDDById(id) ) ? true : false;\r
8821         },\r
8822 \r
8823         \r
8824         getRelated: function(p_oDD, bTargetsOnly) {\r
8825             var oDDs = [];\r
8826             for (var i in p_oDD.groups) {\r
8827                 for (j in this.ids[i]) {\r
8828                     var dd = this.ids[i][j];\r
8829                     if (! this.isTypeOfDD(dd)) {\r
8830                         continue;\r
8831                     }\r
8832                     if (!bTargetsOnly || dd.isTarget) {\r
8833                         oDDs[oDDs.length] = dd;\r
8834                     }\r
8835                 }\r
8836             }\r
8837 \r
8838             return oDDs;\r
8839         },\r
8840 \r
8841         \r
8842         isLegalTarget: function (oDD, oTargetDD) {\r
8843             var targets = this.getRelated(oDD, true);\r
8844             for (var i=0, len=targets.length;i<len;++i) {\r
8845                 if (targets[i].id == oTargetDD.id) {\r
8846                     return true;\r
8847                 }\r
8848             }\r
8849 \r
8850             return false;\r
8851         },\r
8852 \r
8853         \r
8854         isTypeOfDD: function (oDD) {\r
8855             return (oDD && oDD.__ygDragDrop);\r
8856         },\r
8857 \r
8858         \r
8859         isHandle: function(sDDId, sHandleId) {\r
8860             return ( this.handleIds[sDDId] &&\r
8861                             this.handleIds[sDDId][sHandleId] );\r
8862         },\r
8863 \r
8864         \r
8865         getDDById: function(id) {\r
8866             for (var i in this.ids) {\r
8867                 if (this.ids[i][id]) {\r
8868                     return this.ids[i][id];\r
8869                 }\r
8870             }\r
8871             return null;\r
8872         },\r
8873 \r
8874         \r
8875         handleMouseDown: function(e, oDD) {\r
8876             if(Ext.QuickTips){\r
8877                 Ext.QuickTips.disable();\r
8878             }\r
8879             if(this.dragCurrent){\r
8880                 // the original browser mouseup wasn't handled (e.g. outside FF browser window)\r
8881                 // so clean up first to avoid breaking the next drag\r
8882                 this.handleMouseUp(e);\r
8883             }\r
8884             \r
8885             this.currentTarget = e.getTarget();\r
8886             this.dragCurrent = oDD;\r
8887 \r
8888             var el = oDD.getEl();\r
8889 \r
8890             // track start position\r
8891             this.startX = e.getPageX();\r
8892             this.startY = e.getPageY();\r
8893 \r
8894             this.deltaX = this.startX - el.offsetLeft;\r
8895             this.deltaY = this.startY - el.offsetTop;\r
8896 \r
8897             this.dragThreshMet = false;\r
8898 \r
8899             this.clickTimeout = setTimeout(\r
8900                     function() {\r
8901                         var DDM = Ext.dd.DDM;\r
8902                         DDM.startDrag(DDM.startX, DDM.startY);\r
8903                     },\r
8904                     this.clickTimeThresh );\r
8905         },\r
8906 \r
8907         \r
8908         startDrag: function(x, y) {\r
8909             clearTimeout(this.clickTimeout);\r
8910             if (this.dragCurrent) {\r
8911                 this.dragCurrent.b4StartDrag(x, y);\r
8912                 this.dragCurrent.startDrag(x, y);\r
8913             }\r
8914             this.dragThreshMet = true;\r
8915         },\r
8916 \r
8917         \r
8918         handleMouseUp: function(e) {\r
8919 \r
8920             if(Ext.QuickTips){\r
8921                 Ext.QuickTips.enable();\r
8922             }\r
8923             if (! this.dragCurrent) {\r
8924                 return;\r
8925             }\r
8926 \r
8927             clearTimeout(this.clickTimeout);\r
8928 \r
8929             if (this.dragThreshMet) {\r
8930                 this.fireEvents(e, true);\r
8931             } else {\r
8932             }\r
8933 \r
8934             this.stopDrag(e);\r
8935 \r
8936             this.stopEvent(e);\r
8937         },\r
8938 \r
8939         \r
8940         stopEvent: function(e){\r
8941             if(this.stopPropagation) {\r
8942                 e.stopPropagation();\r
8943             }\r
8944 \r
8945             if (this.preventDefault) {\r
8946                 e.preventDefault();\r
8947             }\r
8948         },\r
8949 \r
8950         \r
8951         stopDrag: function(e) {\r
8952             // Fire the drag end event for the item that was dragged\r
8953             if (this.dragCurrent) {\r
8954                 if (this.dragThreshMet) {\r
8955                     this.dragCurrent.b4EndDrag(e);\r
8956                     this.dragCurrent.endDrag(e);\r
8957                 }\r
8958 \r
8959                 this.dragCurrent.onMouseUp(e);\r
8960             }\r
8961 \r
8962             this.dragCurrent = null;\r
8963             this.dragOvers = {};\r
8964         },\r
8965 \r
8966         \r
8967         handleMouseMove: function(e) {\r
8968             if (! this.dragCurrent) {\r
8969                 return true;\r
8970             }\r
8971 \r
8972             // var button = e.which || e.button;\r
8973 \r
8974             // check for IE mouseup outside of page boundary\r
8975             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {\r
8976                 this.stopEvent(e);\r
8977                 return this.handleMouseUp(e);\r
8978             }\r
8979 \r
8980             if (!this.dragThreshMet) {\r
8981                 var diffX = Math.abs(this.startX - e.getPageX());\r
8982                 var diffY = Math.abs(this.startY - e.getPageY());\r
8983                 if (diffX > this.clickPixelThresh ||\r
8984                             diffY > this.clickPixelThresh) {\r
8985                     this.startDrag(this.startX, this.startY);\r
8986                 }\r
8987             }\r
8988 \r
8989             if (this.dragThreshMet) {\r
8990                 this.dragCurrent.b4Drag(e);\r
8991                 this.dragCurrent.onDrag(e);\r
8992                 if(!this.dragCurrent.moveOnly){\r
8993                     this.fireEvents(e, false);\r
8994                 }\r
8995             }\r
8996 \r
8997             this.stopEvent(e);\r
8998 \r
8999             return true;\r
9000         },\r
9001 \r
9002         \r
9003         fireEvents: function(e, isDrop) {\r
9004             var dc = this.dragCurrent;\r
9005 \r
9006             // If the user did the mouse up outside of the window, we could\r
9007             // get here even though we have ended the drag.\r
9008             if (!dc || dc.isLocked()) {\r
9009                 return;\r
9010             }\r
9011 \r
9012             var pt = e.getPoint();\r
9013 \r
9014             // cache the previous dragOver array\r
9015             var oldOvers = [];\r
9016 \r
9017             var outEvts   = [];\r
9018             var overEvts  = [];\r
9019             var dropEvts  = [];\r
9020             var enterEvts = [];\r
9021 \r
9022             // Check to see if the object(s) we were hovering over is no longer\r
9023             // being hovered over so we can fire the onDragOut event\r
9024             for (var i in this.dragOvers) {\r
9025 \r
9026                 var ddo = this.dragOvers[i];\r
9027 \r
9028                 if (! this.isTypeOfDD(ddo)) {\r
9029                     continue;\r
9030                 }\r
9031 \r
9032                 if (! this.isOverTarget(pt, ddo, this.mode)) {\r
9033                     outEvts.push( ddo );\r
9034                 }\r
9035 \r
9036                 oldOvers[i] = true;\r
9037                 delete this.dragOvers[i];\r
9038             }\r
9039 \r
9040             for (var sGroup in dc.groups) {\r
9041 \r
9042                 if ("string" != typeof sGroup) {\r
9043                     continue;\r
9044                 }\r
9045 \r
9046                 for (i in this.ids[sGroup]) {\r
9047                     var oDD = this.ids[sGroup][i];\r
9048                     if (! this.isTypeOfDD(oDD)) {\r
9049                         continue;\r
9050                     }\r
9051 \r
9052                     if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {\r
9053                         if (this.isOverTarget(pt, oDD, this.mode)) {\r
9054                             // look for drop interactions\r
9055                             if (isDrop) {\r
9056                                 dropEvts.push( oDD );\r
9057                             // look for drag enter and drag over interactions\r
9058                             } else {\r
9059 \r
9060                                 // initial drag over: dragEnter fires\r
9061                                 if (!oldOvers[oDD.id]) {\r
9062                                     enterEvts.push( oDD );\r
9063                                 // subsequent drag overs: dragOver fires\r
9064                                 } else {\r
9065                                     overEvts.push( oDD );\r
9066                                 }\r
9067 \r
9068                                 this.dragOvers[oDD.id] = oDD;\r
9069                             }\r
9070                         }\r
9071                     }\r
9072                 }\r
9073             }\r
9074 \r
9075             if (this.mode) {\r
9076                 if (outEvts.length) {\r
9077                     dc.b4DragOut(e, outEvts);\r
9078                     dc.onDragOut(e, outEvts);\r
9079                 }\r
9080 \r
9081                 if (enterEvts.length) {\r
9082                     dc.onDragEnter(e, enterEvts);\r
9083                 }\r
9084 \r
9085                 if (overEvts.length) {\r
9086                     dc.b4DragOver(e, overEvts);\r
9087                     dc.onDragOver(e, overEvts);\r
9088                 }\r
9089 \r
9090                 if (dropEvts.length) {\r
9091                     dc.b4DragDrop(e, dropEvts);\r
9092                     dc.onDragDrop(e, dropEvts);\r
9093                 }\r
9094 \r
9095             } else {\r
9096                 // fire dragout events\r
9097                 var len = 0;\r
9098                 for (i=0, len=outEvts.length; i<len; ++i) {\r
9099                     dc.b4DragOut(e, outEvts[i].id);\r
9100                     dc.onDragOut(e, outEvts[i].id);\r
9101                 }\r
9102 \r
9103                 // fire enter events\r
9104                 for (i=0,len=enterEvts.length; i<len; ++i) {\r
9105                     // dc.b4DragEnter(e, oDD.id);\r
9106                     dc.onDragEnter(e, enterEvts[i].id);\r
9107                 }\r
9108 \r
9109                 // fire over events\r
9110                 for (i=0,len=overEvts.length; i<len; ++i) {\r
9111                     dc.b4DragOver(e, overEvts[i].id);\r
9112                     dc.onDragOver(e, overEvts[i].id);\r
9113                 }\r
9114 \r
9115                 // fire drop events\r
9116                 for (i=0, len=dropEvts.length; i<len; ++i) {\r
9117                     dc.b4DragDrop(e, dropEvts[i].id);\r
9118                     dc.onDragDrop(e, dropEvts[i].id);\r
9119                 }\r
9120 \r
9121             }\r
9122 \r
9123             // notify about a drop that did not find a target\r
9124             if (isDrop && !dropEvts.length) {\r
9125                 dc.onInvalidDrop(e);\r
9126             }\r
9127 \r
9128         },\r
9129 \r
9130         \r
9131         getBestMatch: function(dds) {\r
9132             var winner = null;\r
9133             // Return null if the input is not what we expect\r
9134             //if (!dds || !dds.length || dds.length == 0) {\r
9135                // winner = null;\r
9136             // If there is only one item, it wins\r
9137             //} else if (dds.length == 1) {\r
9138 \r
9139             var len = dds.length;\r
9140 \r
9141             if (len == 1) {\r
9142                 winner = dds[0];\r
9143             } else {\r
9144                 // Loop through the targeted items\r
9145                 for (var i=0; i<len; ++i) {\r
9146                     var dd = dds[i];\r
9147                     // If the cursor is over the object, it wins.  If the\r
9148                     // cursor is over multiple matches, the first one we come\r
9149                     // to wins.\r
9150                     if (dd.cursorIsOver) {\r
9151                         winner = dd;\r
9152                         break;\r
9153                     // Otherwise the object with the most overlap wins\r
9154                     } else {\r
9155                         if (!winner ||\r
9156                             winner.overlap.getArea() < dd.overlap.getArea()) {\r
9157                             winner = dd;\r
9158                         }\r
9159                     }\r
9160                 }\r
9161             }\r
9162 \r
9163             return winner;\r
9164         },\r
9165 \r
9166         \r
9167         refreshCache: function(groups) {\r
9168             for (var sGroup in groups) {\r
9169                 if ("string" != typeof sGroup) {\r
9170                     continue;\r
9171                 }\r
9172                 for (var i in this.ids[sGroup]) {\r
9173                     var oDD = this.ids[sGroup][i];\r
9174 \r
9175                     if (this.isTypeOfDD(oDD)) {\r
9176                     // if (this.isTypeOfDD(oDD) && oDD.isTarget) {\r
9177                         var loc = this.getLocation(oDD);\r
9178                         if (loc) {\r
9179                             this.locationCache[oDD.id] = loc;\r
9180                         } else {\r
9181                             delete this.locationCache[oDD.id];\r
9182                             // this will unregister the drag and drop object if\r
9183                             // the element is not in a usable state\r
9184                             // oDD.unreg();\r
9185                         }\r
9186                     }\r
9187                 }\r
9188             }\r
9189         },\r
9190 \r
9191         \r
9192         verifyEl: function(el) {\r
9193             if (el) {\r
9194                 var parent;\r
9195                 if(Ext.isIE){\r
9196                     try{\r
9197                         parent = el.offsetParent;\r
9198                     }catch(e){}\r
9199                 }else{\r
9200                     parent = el.offsetParent;\r
9201                 }\r
9202                 if (parent) {\r
9203                     return true;\r
9204                 }\r
9205             }\r
9206 \r
9207             return false;\r
9208         },\r
9209 \r
9210         \r
9211         getLocation: function(oDD) {\r
9212             if (! this.isTypeOfDD(oDD)) {\r
9213                 return null;\r
9214             }\r
9215 \r
9216             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;\r
9217 \r
9218             try {\r
9219                 pos= Ext.lib.Dom.getXY(el);\r
9220             } catch (e) { }\r
9221 \r
9222             if (!pos) {\r
9223                 return null;\r
9224             }\r
9225 \r
9226             x1 = pos[0];\r
9227             x2 = x1 + el.offsetWidth;\r
9228             y1 = pos[1];\r
9229             y2 = y1 + el.offsetHeight;\r
9230 \r
9231             t = y1 - oDD.padding[0];\r
9232             r = x2 + oDD.padding[1];\r
9233             b = y2 + oDD.padding[2];\r
9234             l = x1 - oDD.padding[3];\r
9235 \r
9236             return new Ext.lib.Region( t, r, b, l );\r
9237         },\r
9238 \r
9239         \r
9240         isOverTarget: function(pt, oTarget, intersect) {\r
9241             // use cache if available\r
9242             var loc = this.locationCache[oTarget.id];\r
9243             if (!loc || !this.useCache) {\r
9244                 loc = this.getLocation(oTarget);\r
9245                 this.locationCache[oTarget.id] = loc;\r
9246 \r
9247             }\r
9248 \r
9249             if (!loc) {\r
9250                 return false;\r
9251             }\r
9252 \r
9253             oTarget.cursorIsOver = loc.contains( pt );\r
9254 \r
9255             // DragDrop is using this as a sanity check for the initial mousedown\r
9256             // in this case we are done.  In POINT mode, if the drag obj has no\r
9257             // contraints, we are also done. Otherwise we need to evaluate the\r
9258             // location of the target as related to the actual location of the\r
9259             // dragged element.\r
9260             var dc = this.dragCurrent;\r
9261             if (!dc || !dc.getTargetCoord ||\r
9262                     (!intersect && !dc.constrainX && !dc.constrainY)) {\r
9263                 return oTarget.cursorIsOver;\r
9264             }\r
9265 \r
9266             oTarget.overlap = null;\r
9267 \r
9268             // Get the current location of the drag element, this is the\r
9269             // location of the mouse event less the delta that represents\r
9270             // where the original mousedown happened on the element.  We\r
9271             // need to consider constraints and ticks as well.\r
9272             var pos = dc.getTargetCoord(pt.x, pt.y);\r
9273 \r
9274             var el = dc.getDragEl();\r
9275             var curRegion = new Ext.lib.Region( pos.y,\r
9276                                                    pos.x + el.offsetWidth,\r
9277                                                    pos.y + el.offsetHeight,\r
9278                                                    pos.x );\r
9279 \r
9280             var overlap = curRegion.intersect(loc);\r
9281 \r
9282             if (overlap) {\r
9283                 oTarget.overlap = overlap;\r
9284                 return (intersect) ? true : oTarget.cursorIsOver;\r
9285             } else {\r
9286                 return false;\r
9287             }\r
9288         },\r
9289 \r
9290         \r
9291         _onUnload: function(e, me) {\r
9292             Ext.dd.DragDropMgr.unregAll();\r
9293         },\r
9294 \r
9295         \r
9296         unregAll: function() {\r
9297 \r
9298             if (this.dragCurrent) {\r
9299                 this.stopDrag();\r
9300                 this.dragCurrent = null;\r
9301             }\r
9302 \r
9303             this._execOnAll("unreg", []);\r
9304 \r
9305             for (var i in this.elementCache) {\r
9306                 delete this.elementCache[i];\r
9307             }\r
9308 \r
9309             this.elementCache = {};\r
9310             this.ids = {};\r
9311         },\r
9312 \r
9313         \r
9314         elementCache: {},\r
9315 \r
9316         \r
9317         getElWrapper: function(id) {\r
9318             var oWrapper = this.elementCache[id];\r
9319             if (!oWrapper || !oWrapper.el) {\r
9320                 oWrapper = this.elementCache[id] =\r
9321                     new this.ElementWrapper(Ext.getDom(id));\r
9322             }\r
9323             return oWrapper;\r
9324         },\r
9325 \r
9326         \r
9327         getElement: function(id) {\r
9328             return Ext.getDom(id);\r
9329         },\r
9330 \r
9331         \r
9332         getCss: function(id) {\r
9333             var el = Ext.getDom(id);\r
9334             return (el) ? el.style : null;\r
9335         },\r
9336 \r
9337         \r
9338         ElementWrapper: function(el) {\r
9339                 \r
9340                 this.el = el || null;\r
9341                 \r
9342                 this.id = this.el && el.id;\r
9343                 \r
9344                 this.css = this.el && el.style;\r
9345             },\r
9346 \r
9347         \r
9348         getPosX: function(el) {\r
9349             return Ext.lib.Dom.getX(el);\r
9350         },\r
9351 \r
9352         \r
9353         getPosY: function(el) {\r
9354             return Ext.lib.Dom.getY(el);\r
9355         },\r
9356 \r
9357         \r
9358         swapNode: function(n1, n2) {\r
9359             if (n1.swapNode) {\r
9360                 n1.swapNode(n2);\r
9361             } else {\r
9362                 var p = n2.parentNode;\r
9363                 var s = n2.nextSibling;\r
9364 \r
9365                 if (s == n1) {\r
9366                     p.insertBefore(n1, n2);\r
9367                 } else if (n2 == n1.nextSibling) {\r
9368                     p.insertBefore(n2, n1);\r
9369                 } else {\r
9370                     n1.parentNode.replaceChild(n2, n1);\r
9371                     p.insertBefore(n1, s);\r
9372                 }\r
9373             }\r
9374         },\r
9375 \r
9376         \r
9377         getScroll: function () {\r
9378             var t, l, dde=document.documentElement, db=document.body;\r
9379             if (dde && (dde.scrollTop || dde.scrollLeft)) {\r
9380                 t = dde.scrollTop;\r
9381                 l = dde.scrollLeft;\r
9382             } else if (db) {\r
9383                 t = db.scrollTop;\r
9384                 l = db.scrollLeft;\r
9385             } else {\r
9386 \r
9387             }\r
9388             return { top: t, left: l };\r
9389         },\r
9390 \r
9391         \r
9392         getStyle: function(el, styleProp) {\r
9393             return Ext.fly(el).getStyle(styleProp);\r
9394         },\r
9395 \r
9396         \r
9397         getScrollTop: function () { return this.getScroll().top; },\r
9398 \r
9399         \r
9400         getScrollLeft: function () { return this.getScroll().left; },\r
9401 \r
9402         \r
9403         moveToEl: function (moveEl, targetEl) {\r
9404             var aCoord = Ext.lib.Dom.getXY(targetEl);\r
9405             Ext.lib.Dom.setXY(moveEl, aCoord);\r
9406         },\r
9407 \r
9408         \r
9409         numericSort: function(a, b) { return (a - b); },\r
9410 \r
9411         \r
9412         _timeoutCount: 0,\r
9413 \r
9414         \r
9415         _addListeners: function() {\r
9416             var DDM = Ext.dd.DDM;\r
9417             if ( Ext.lib.Event && document ) {\r
9418                 DDM._onLoad();\r
9419             } else {\r
9420                 if (DDM._timeoutCount > 2000) {\r
9421                 } else {\r
9422                     setTimeout(DDM._addListeners, 10);\r
9423                     if (document && document.body) {\r
9424                         DDM._timeoutCount += 1;\r
9425                     }\r
9426                 }\r
9427             }\r
9428         },\r
9429 \r
9430         \r
9431         handleWasClicked: function(node, id) {\r
9432             if (this.isHandle(id, node.id)) {\r
9433                 return true;\r
9434             } else {\r
9435                 // check to see if this is a text node child of the one we want\r
9436                 var p = node.parentNode;\r
9437 \r
9438                 while (p) {\r
9439                     if (this.isHandle(id, p.id)) {\r
9440                         return true;\r
9441                     } else {\r
9442                         p = p.parentNode;\r
9443                     }\r
9444                 }\r
9445             }\r
9446 \r
9447             return false;\r
9448         }\r
9449 \r
9450     };\r
9451 \r
9452 }();\r
9453 \r
9454 // shorter alias, save a few bytes\r
9455 Ext.dd.DDM = Ext.dd.DragDropMgr;\r
9456 Ext.dd.DDM._addListeners();\r
9457 \r
9458 }\r
9459 \r
9460 \r
9461 Ext.dd.DD = function(id, sGroup, config) {\r
9462     if (id) {\r
9463         this.init(id, sGroup, config);\r
9464     }\r
9465 };\r
9466 \r
9467 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {\r
9468 \r
9469     \r
9470     scroll: true,\r
9471 \r
9472     \r
9473     autoOffset: function(iPageX, iPageY) {\r
9474         var x = iPageX - this.startPageX;\r
9475         var y = iPageY - this.startPageY;\r
9476         this.setDelta(x, y);\r
9477     },\r
9478 \r
9479     \r
9480     setDelta: function(iDeltaX, iDeltaY) {\r
9481         this.deltaX = iDeltaX;\r
9482         this.deltaY = iDeltaY;\r
9483     },\r
9484 \r
9485     \r
9486     setDragElPos: function(iPageX, iPageY) {\r
9487         // the first time we do this, we are going to check to make sure\r
9488         // the element has css positioning\r
9489 \r
9490         var el = this.getDragEl();\r
9491         this.alignElWithMouse(el, iPageX, iPageY);\r
9492     },\r
9493 \r
9494     \r
9495     alignElWithMouse: function(el, iPageX, iPageY) {\r
9496         var oCoord = this.getTargetCoord(iPageX, iPageY);\r
9497         var fly = el.dom ? el : Ext.fly(el, '_dd');\r
9498         if (!this.deltaSetXY) {\r
9499             var aCoord = [oCoord.x, oCoord.y];\r
9500             fly.setXY(aCoord);\r
9501             var newLeft = fly.getLeft(true);\r
9502             var newTop  = fly.getTop(true);\r
9503             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];\r
9504         } else {\r
9505             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);\r
9506         }\r
9507 \r
9508         this.cachePosition(oCoord.x, oCoord.y);\r
9509         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);\r
9510         return oCoord;\r
9511     },\r
9512 \r
9513     \r
9514     cachePosition: function(iPageX, iPageY) {\r
9515         if (iPageX) {\r
9516             this.lastPageX = iPageX;\r
9517             this.lastPageY = iPageY;\r
9518         } else {\r
9519             var aCoord = Ext.lib.Dom.getXY(this.getEl());\r
9520             this.lastPageX = aCoord[0];\r
9521             this.lastPageY = aCoord[1];\r
9522         }\r
9523     },\r
9524 \r
9525     \r
9526     autoScroll: function(x, y, h, w) {\r
9527 \r
9528         if (this.scroll) {\r
9529             // The client height\r
9530             var clientH = Ext.lib.Dom.getViewHeight();\r
9531 \r
9532             // The client width\r
9533             var clientW = Ext.lib.Dom.getViewWidth();\r
9534 \r
9535             // The amt scrolled down\r
9536             var st = this.DDM.getScrollTop();\r
9537 \r
9538             // The amt scrolled right\r
9539             var sl = this.DDM.getScrollLeft();\r
9540 \r
9541             // Location of the bottom of the element\r
9542             var bot = h + y;\r
9543 \r
9544             // Location of the right of the element\r
9545             var right = w + x;\r
9546 \r
9547             // The distance from the cursor to the bottom of the visible area,\r
9548             // adjusted so that we don't scroll if the cursor is beyond the\r
9549             // element drag constraints\r
9550             var toBot = (clientH + st - y - this.deltaY);\r
9551 \r
9552             // The distance from the cursor to the right of the visible area\r
9553             var toRight = (clientW + sl - x - this.deltaX);\r
9554 \r
9555 \r
9556             // How close to the edge the cursor must be before we scroll\r
9557             // var thresh = (document.all) ? 100 : 40;\r
9558             var thresh = 40;\r
9559 \r
9560             // How many pixels to scroll per autoscroll op.  This helps to reduce\r
9561             // clunky scrolling. IE is more sensitive about this ... it needs this\r
9562             // value to be higher.\r
9563             var scrAmt = (document.all) ? 80 : 30;\r
9564 \r
9565             // Scroll down if we are near the bottom of the visible page and the\r
9566             // obj extends below the crease\r
9567             if ( bot > clientH && toBot < thresh ) {\r
9568                 window.scrollTo(sl, st + scrAmt);\r
9569             }\r
9570 \r
9571             // Scroll up if the window is scrolled down and the top of the object\r
9572             // goes above the top border\r
9573             if ( y < st && st > 0 && y - st < thresh ) {\r
9574                 window.scrollTo(sl, st - scrAmt);\r
9575             }\r
9576 \r
9577             // Scroll right if the obj is beyond the right border and the cursor is\r
9578             // near the border.\r
9579             if ( right > clientW && toRight < thresh ) {\r
9580                 window.scrollTo(sl + scrAmt, st);\r
9581             }\r
9582 \r
9583             // Scroll left if the window has been scrolled to the right and the obj\r
9584             // extends past the left border\r
9585             if ( x < sl && sl > 0 && x - sl < thresh ) {\r
9586                 window.scrollTo(sl - scrAmt, st);\r
9587             }\r
9588         }\r
9589     },\r
9590 \r
9591     \r
9592     getTargetCoord: function(iPageX, iPageY) {\r
9593 \r
9594 \r
9595         var x = iPageX - this.deltaX;\r
9596         var y = iPageY - this.deltaY;\r
9597 \r
9598         if (this.constrainX) {\r
9599             if (x < this.minX) { x = this.minX; }\r
9600             if (x > this.maxX) { x = this.maxX; }\r
9601         }\r
9602 \r
9603         if (this.constrainY) {\r
9604             if (y < this.minY) { y = this.minY; }\r
9605             if (y > this.maxY) { y = this.maxY; }\r
9606         }\r
9607 \r
9608         x = this.getTick(x, this.xTicks);\r
9609         y = this.getTick(y, this.yTicks);\r
9610 \r
9611 \r
9612         return {x:x, y:y};\r
9613     },\r
9614 \r
9615     \r
9616     applyConfig: function() {\r
9617         Ext.dd.DD.superclass.applyConfig.call(this);\r
9618         this.scroll = (this.config.scroll !== false);\r
9619     },\r
9620 \r
9621     \r
9622     b4MouseDown: function(e) {\r
9623         // this.resetConstraints();\r
9624         this.autoOffset(e.getPageX(),\r
9625                             e.getPageY());\r
9626     },\r
9627 \r
9628     \r
9629     b4Drag: function(e) {\r
9630         this.setDragElPos(e.getPageX(),\r
9631                             e.getPageY());\r
9632     },\r
9633 \r
9634     toString: function() {\r
9635         return ("DD " + this.id);\r
9636     }\r
9637 \r
9638     //////////////////////////////////////////////////////////////////////////\r
9639     // Debugging ygDragDrop events that can be overridden\r
9640     //////////////////////////////////////////////////////////////////////////\r
9641     \r
9642 \r
9643 });\r
9644 \r
9645 Ext.dd.DDProxy = function(id, sGroup, config) {\r
9646     if (id) {\r
9647         this.init(id, sGroup, config);\r
9648         this.initFrame();\r
9649     }\r
9650 };\r
9651 \r
9652 \r
9653 Ext.dd.DDProxy.dragElId = "ygddfdiv";\r
9654 \r
9655 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {\r
9656 \r
9657     \r
9658     resizeFrame: true,\r
9659 \r
9660     \r
9661     centerFrame: false,\r
9662 \r
9663     \r
9664     createFrame: function() {\r
9665         var self = this;\r
9666         var body = document.body;\r
9667 \r
9668         if (!body || !body.firstChild) {\r
9669             setTimeout( function() { self.createFrame(); }, 50 );\r
9670             return;\r
9671         }\r
9672 \r
9673         var div = this.getDragEl();\r
9674 \r
9675         if (!div) {\r
9676             div    = document.createElement("div");\r
9677             div.id = this.dragElId;\r
9678             var s  = div.style;\r
9679 \r
9680             s.position   = "absolute";\r
9681             s.visibility = "hidden";\r
9682             s.cursor     = "move";\r
9683             s.border     = "2px solid #aaa";\r
9684             s.zIndex     = 999;\r
9685 \r
9686             // appendChild can blow up IE if invoked prior to the window load event\r
9687             // while rendering a table.  It is possible there are other scenarios\r
9688             // that would cause this to happen as well.\r
9689             body.insertBefore(div, body.firstChild);\r
9690         }\r
9691     },\r
9692 \r
9693     \r
9694     initFrame: function() {\r
9695         this.createFrame();\r
9696     },\r
9697 \r
9698     applyConfig: function() {\r
9699         Ext.dd.DDProxy.superclass.applyConfig.call(this);\r
9700 \r
9701         this.resizeFrame = (this.config.resizeFrame !== false);\r
9702         this.centerFrame = (this.config.centerFrame);\r
9703         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);\r
9704     },\r
9705 \r
9706     \r
9707     showFrame: function(iPageX, iPageY) {\r
9708         var el = this.getEl();\r
9709         var dragEl = this.getDragEl();\r
9710         var s = dragEl.style;\r
9711 \r
9712         this._resizeProxy();\r
9713 \r
9714         if (this.centerFrame) {\r
9715             this.setDelta( Math.round(parseInt(s.width,  10)/2),\r
9716                            Math.round(parseInt(s.height, 10)/2) );\r
9717         }\r
9718 \r
9719         this.setDragElPos(iPageX, iPageY);\r
9720 \r
9721         Ext.fly(dragEl).show();\r
9722     },\r
9723 \r
9724     \r
9725     _resizeProxy: function() {\r
9726         if (this.resizeFrame) {\r
9727             var el = this.getEl();\r
9728             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);\r
9729         }\r
9730     },\r
9731 \r
9732     // overrides Ext.dd.DragDrop\r
9733     b4MouseDown: function(e) {\r
9734         var x = e.getPageX();\r
9735         var y = e.getPageY();\r
9736         this.autoOffset(x, y);\r
9737         this.setDragElPos(x, y);\r
9738     },\r
9739 \r
9740     // overrides Ext.dd.DragDrop\r
9741     b4StartDrag: function(x, y) {\r
9742         // show the drag frame\r
9743         this.showFrame(x, y);\r
9744     },\r
9745 \r
9746     // overrides Ext.dd.DragDrop\r
9747     b4EndDrag: function(e) {\r
9748         Ext.fly(this.getDragEl()).hide();\r
9749     },\r
9750 \r
9751     // overrides Ext.dd.DragDrop\r
9752     // By default we try to move the element to the last location of the frame.\r
9753     // This is so that the default behavior mirrors that of Ext.dd.DD.\r
9754     endDrag: function(e) {\r
9755 \r
9756         var lel = this.getEl();\r
9757         var del = this.getDragEl();\r
9758 \r
9759         // Show the drag frame briefly so we can get its position\r
9760         del.style.visibility = "";\r
9761 \r
9762         this.beforeMove();\r
9763         // Hide the linked element before the move to get around a Safari\r
9764         // rendering bug.\r
9765         lel.style.visibility = "hidden";\r
9766         Ext.dd.DDM.moveToEl(lel, del);\r
9767         del.style.visibility = "hidden";\r
9768         lel.style.visibility = "";\r
9769 \r
9770         this.afterDrag();\r
9771     },\r
9772 \r
9773     beforeMove : function(){\r
9774 \r
9775     },\r
9776 \r
9777     afterDrag : function(){\r
9778 \r
9779     },\r
9780 \r
9781     toString: function() {\r
9782         return ("DDProxy " + this.id);\r
9783     }\r
9784 \r
9785 });\r
9786 \r
9787 Ext.dd.DDTarget = function(id, sGroup, config) {\r
9788     if (id) {\r
9789         this.initTarget(id, sGroup, config);\r
9790     }\r
9791 };\r
9792 \r
9793 // Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();\r
9794 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {\r
9795     toString: function() {\r
9796         return ("DDTarget " + this.id);\r
9797     }\r
9798 });\r
9799 \r
9800 Ext.dd.DragTracker = function(config){\r
9801     Ext.apply(this, config);\r
9802     this.addEvents(\r
9803         'mousedown',\r
9804         'mouseup',\r
9805         'mousemove',\r
9806         'dragstart',\r
9807         'dragend',\r
9808         'drag'\r
9809     );\r
9810 \r
9811     this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
9812 \r
9813     if(this.el){\r
9814         this.initEl(this.el);\r
9815     }\r
9816 }\r
9817 \r
9818 Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {\r
9819     active: false,\r
9820     tolerance: 5,\r
9821     autoStart: false,\r
9822 \r
9823     initEl: function(el){\r
9824         this.el = Ext.get(el);\r
9825         el.on('mousedown', this.onMouseDown, this,\r
9826                 this.delegate ? {delegate: this.delegate} : undefined);\r
9827     },\r
9828 \r
9829     destroy : function(){\r
9830         this.el.un('mousedown', this.onMouseDown, this);\r
9831     },\r
9832 \r
9833     onMouseDown: function(e, target){\r
9834         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){\r
9835             this.startXY = this.lastXY = e.getXY();\r
9836             this.dragTarget = this.delegate ? target : this.el.dom;\r
9837             e.preventDefault();\r
9838             var doc = Ext.getDoc();\r
9839             doc.on('mouseup', this.onMouseUp, this);\r
9840             doc.on('mousemove', this.onMouseMove, this);\r
9841             doc.on('selectstart', this.stopSelect, this);\r
9842             if(this.autoStart){\r
9843                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);\r
9844             }\r
9845         }\r
9846     },\r
9847 \r
9848     onMouseMove: function(e, target){\r
9849         e.preventDefault();\r
9850         var xy = e.getXY(), s = this.startXY;\r
9851         this.lastXY = xy;\r
9852         if(!this.active){\r
9853             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){\r
9854                 this.triggerStart();\r
9855             }else{\r
9856                 return;\r
9857             }\r
9858         }\r
9859         this.fireEvent('mousemove', this, e);\r
9860         this.onDrag(e);\r
9861         this.fireEvent('drag', this, e);\r
9862     },\r
9863 \r
9864     onMouseUp: function(e){\r
9865         var doc = Ext.getDoc();\r
9866         doc.un('mousemove', this.onMouseMove, this);\r
9867         doc.un('mouseup', this.onMouseUp, this);\r
9868         doc.un('selectstart', this.stopSelect, this);\r
9869         e.preventDefault();\r
9870         this.clearStart();\r
9871         this.active = false;\r
9872         delete this.elRegion;\r
9873         this.fireEvent('mouseup', this, e);\r
9874         this.onEnd(e);\r
9875         this.fireEvent('dragend', this, e);\r
9876     },\r
9877 \r
9878     triggerStart: function(isTimer){\r
9879         this.clearStart();\r
9880         this.active = true;\r
9881         this.onStart(this.startXY);\r
9882         this.fireEvent('dragstart', this, this.startXY);\r
9883     },\r
9884 \r
9885     clearStart : function(){\r
9886         if(this.timer){\r
9887             clearTimeout(this.timer);\r
9888             delete this.timer;\r
9889         }\r
9890     },\r
9891 \r
9892     stopSelect : function(e){\r
9893         e.stopEvent();\r
9894         return false;\r
9895     },\r
9896 \r
9897     onBeforeStart : function(e){\r
9898 \r
9899     },\r
9900 \r
9901     onStart : function(xy){\r
9902 \r
9903     },\r
9904 \r
9905     onDrag : function(e){\r
9906 \r
9907     },\r
9908 \r
9909     onEnd : function(e){\r
9910 \r
9911     },\r
9912 \r
9913     getDragTarget : function(){\r
9914         return this.dragTarget;\r
9915     },\r
9916 \r
9917     getDragCt : function(){\r
9918         return this.el;\r
9919     },\r
9920 \r
9921     getXY : function(constrain){\r
9922         return constrain ?\r
9923                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;\r
9924     },\r
9925 \r
9926     getOffset : function(constrain){\r
9927         var xy = this.getXY(constrain);\r
9928         var s = this.startXY;\r
9929         return [s[0]-xy[0], s[1]-xy[1]];\r
9930     },\r
9931 \r
9932     constrainModes: {\r
9933         'point' : function(xy){\r
9934 \r
9935             if(!this.elRegion){\r
9936                 this.elRegion = this.getDragCt().getRegion();\r
9937             }\r
9938 \r
9939             var dr = this.dragRegion;\r
9940 \r
9941             dr.left = xy[0];\r
9942             dr.top = xy[1];\r
9943             dr.right = xy[0];\r
9944             dr.bottom = xy[1];\r
9945 \r
9946             dr.constrainTo(this.elRegion);\r
9947 \r
9948             return [dr.left, dr.top];\r
9949         }\r
9950     }\r
9951 });\r
9952 \r
9953 Ext.dd.ScrollManager = function(){\r
9954     var ddm = Ext.dd.DragDropMgr;\r
9955     var els = {};\r
9956     var dragEl = null;\r
9957     var proc = {};\r
9958     \r
9959     var onStop = function(e){\r
9960         dragEl = null;\r
9961         clearProc();\r
9962     };\r
9963     \r
9964     var triggerRefresh = function(){\r
9965         if(ddm.dragCurrent){\r
9966              ddm.refreshCache(ddm.dragCurrent.groups);\r
9967         }\r
9968     };\r
9969     \r
9970     var doScroll = function(){\r
9971         if(ddm.dragCurrent){\r
9972             var dds = Ext.dd.ScrollManager;\r
9973             var inc = proc.el.ddScrollConfig ?\r
9974                       proc.el.ddScrollConfig.increment : dds.increment;\r
9975             if(!dds.animate){\r
9976                 if(proc.el.scroll(proc.dir, inc)){\r
9977                     triggerRefresh();\r
9978                 }\r
9979             }else{\r
9980                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);\r
9981             }\r
9982         }\r
9983     };\r
9984     \r
9985     var clearProc = function(){\r
9986         if(proc.id){\r
9987             clearInterval(proc.id);\r
9988         }\r
9989         proc.id = 0;\r
9990         proc.el = null;\r
9991         proc.dir = "";\r
9992     };\r
9993     \r
9994     var startProc = function(el, dir){\r
9995         clearProc();\r
9996         proc.el = el;\r
9997         proc.dir = dir;\r
9998         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? \r
9999                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;\r
10000         proc.id = setInterval(doScroll, freq);\r
10001     };\r
10002     \r
10003     var onFire = function(e, isDrop){\r
10004         if(isDrop || !ddm.dragCurrent){ return; }\r
10005         var dds = Ext.dd.ScrollManager;\r
10006         if(!dragEl || dragEl != ddm.dragCurrent){\r
10007             dragEl = ddm.dragCurrent;\r
10008             // refresh regions on drag start\r
10009             dds.refreshCache();\r
10010         }\r
10011         \r
10012         var xy = Ext.lib.Event.getXY(e);\r
10013         var pt = new Ext.lib.Point(xy[0], xy[1]);\r
10014         for(var id in els){\r
10015             var el = els[id], r = el._region;\r
10016             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;\r
10017             if(r && r.contains(pt) && el.isScrollable()){\r
10018                 if(r.bottom - pt.y <= c.vthresh){\r
10019                     if(proc.el != el){\r
10020                         startProc(el, "down");\r
10021                     }\r
10022                     return;\r
10023                 }else if(r.right - pt.x <= c.hthresh){\r
10024                     if(proc.el != el){\r
10025                         startProc(el, "left");\r
10026                     }\r
10027                     return;\r
10028                 }else if(pt.y - r.top <= c.vthresh){\r
10029                     if(proc.el != el){\r
10030                         startProc(el, "up");\r
10031                     }\r
10032                     return;\r
10033                 }else if(pt.x - r.left <= c.hthresh){\r
10034                     if(proc.el != el){\r
10035                         startProc(el, "right");\r
10036                     }\r
10037                     return;\r
10038                 }\r
10039             }\r
10040         }\r
10041         clearProc();\r
10042     };\r
10043     \r
10044     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);\r
10045     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);\r
10046     \r
10047     return {\r
10048         \r
10049         register : function(el){\r
10050             if(Ext.isArray(el)){\r
10051                 for(var i = 0, len = el.length; i < len; i++) {\r
10052                         this.register(el[i]);\r
10053                 }\r
10054             }else{\r
10055                 el = Ext.get(el);\r
10056                 els[el.id] = el;\r
10057             }\r
10058         },\r
10059         \r
10060         \r
10061         unregister : function(el){\r
10062             if(Ext.isArray(el)){\r
10063                 for(var i = 0, len = el.length; i < len; i++) {\r
10064                         this.unregister(el[i]);\r
10065                 }\r
10066             }else{\r
10067                 el = Ext.get(el);\r
10068                 delete els[el.id];\r
10069             }\r
10070         },\r
10071         \r
10072         \r
10073         vthresh : 25,\r
10074         \r
10075         hthresh : 25,\r
10076 \r
10077         \r
10078         increment : 100,\r
10079         \r
10080         \r
10081         frequency : 500,\r
10082         \r
10083         \r
10084         animate: true,\r
10085         \r
10086         \r
10087         animDuration: .4,\r
10088         \r
10089         \r
10090         refreshCache : function(){\r
10091             for(var id in els){\r
10092                 if(typeof els[id] == 'object'){ // for people extending the object prototype\r
10093                     els[id]._region = els[id].getRegion();\r
10094                 }\r
10095             }\r
10096         }\r
10097     };\r
10098 }();\r
10099 \r
10100 Ext.dd.Registry = function(){\r
10101     var elements = {}; \r
10102     var handles = {}; \r
10103     var autoIdSeed = 0;\r
10104 \r
10105     var getId = function(el, autogen){\r
10106         if(typeof el == "string"){\r
10107             return el;\r
10108         }\r
10109         var id = el.id;\r
10110         if(!id && autogen !== false){\r
10111             id = "extdd-" + (++autoIdSeed);\r
10112             el.id = id;\r
10113         }\r
10114         return id;\r
10115     };\r
10116     \r
10117     return {\r
10118     \r
10119         register : function(el, data){\r
10120             data = data || {};\r
10121             if(typeof el == "string"){\r
10122                 el = document.getElementById(el);\r
10123             }\r
10124             data.ddel = el;\r
10125             elements[getId(el)] = data;\r
10126             if(data.isHandle !== false){\r
10127                 handles[data.ddel.id] = data;\r
10128             }\r
10129             if(data.handles){\r
10130                 var hs = data.handles;\r
10131                 for(var i = 0, len = hs.length; i < len; i++){\r
10132                         handles[getId(hs[i])] = data;\r
10133                 }\r
10134             }\r
10135         },\r
10136 \r
10137     \r
10138         unregister : function(el){\r
10139             var id = getId(el, false);\r
10140             var data = elements[id];\r
10141             if(data){\r
10142                 delete elements[id];\r
10143                 if(data.handles){\r
10144                     var hs = data.handles;\r
10145                     for(var i = 0, len = hs.length; i < len; i++){\r
10146                         delete handles[getId(hs[i], false)];\r
10147                     }\r
10148                 }\r
10149             }\r
10150         },\r
10151 \r
10152     \r
10153         getHandle : function(id){\r
10154             if(typeof id != "string"){ // must be element?\r
10155                 id = id.id;\r
10156             }\r
10157             return handles[id];\r
10158         },\r
10159 \r
10160     \r
10161         getHandleFromEvent : function(e){\r
10162             var t = Ext.lib.Event.getTarget(e);\r
10163             return t ? handles[t.id] : null;\r
10164         },\r
10165 \r
10166     \r
10167         getTarget : function(id){\r
10168             if(typeof id != "string"){ // must be element?\r
10169                 id = id.id;\r
10170             }\r
10171             return elements[id];\r
10172         },\r
10173 \r
10174     \r
10175         getTargetFromEvent : function(e){\r
10176             var t = Ext.lib.Event.getTarget(e);\r
10177             return t ? elements[t.id] || handles[t.id] : null;\r
10178         }\r
10179     };\r
10180 }();\r
10181 \r
10182 Ext.dd.StatusProxy = function(config){\r
10183     Ext.apply(this, config);\r
10184     this.id = this.id || Ext.id();\r
10185     this.el = new Ext.Layer({\r
10186         dh: {\r
10187             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [\r
10188                 {tag: "div", cls: "x-dd-drop-icon"},\r
10189                 {tag: "div", cls: "x-dd-drag-ghost"}\r
10190             ]\r
10191         }, \r
10192         shadow: !config || config.shadow !== false\r
10193     });\r
10194     this.ghost = Ext.get(this.el.dom.childNodes[1]);\r
10195     this.dropStatus = this.dropNotAllowed;\r
10196 };\r
10197 \r
10198 Ext.dd.StatusProxy.prototype = {\r
10199     \r
10200     dropAllowed : "x-dd-drop-ok",\r
10201     \r
10202     dropNotAllowed : "x-dd-drop-nodrop",\r
10203 \r
10204     \r
10205     setStatus : function(cssClass){\r
10206         cssClass = cssClass || this.dropNotAllowed;\r
10207         if(this.dropStatus != cssClass){\r
10208             this.el.replaceClass(this.dropStatus, cssClass);\r
10209             this.dropStatus = cssClass;\r
10210         }\r
10211     },\r
10212 \r
10213     \r
10214     reset : function(clearGhost){\r
10215         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;\r
10216         this.dropStatus = this.dropNotAllowed;\r
10217         if(clearGhost){\r
10218             this.ghost.update("");\r
10219         }\r
10220     },\r
10221 \r
10222     \r
10223     update : function(html){\r
10224         if(typeof html == "string"){\r
10225             this.ghost.update(html);\r
10226         }else{\r
10227             this.ghost.update("");\r
10228             html.style.margin = "0";\r
10229             this.ghost.dom.appendChild(html);\r
10230         }\r
10231         var el = this.ghost.dom.firstChild; \r
10232         if(el){\r
10233             Ext.fly(el).setStyle(Ext.isIE ? 'styleFloat' : 'cssFloat', 'none');\r
10234         }\r
10235     },\r
10236 \r
10237     \r
10238     getEl : function(){\r
10239         return this.el;\r
10240     },\r
10241 \r
10242     \r
10243     getGhost : function(){\r
10244         return this.ghost;\r
10245     },\r
10246 \r
10247     \r
10248     hide : function(clear){\r
10249         this.el.hide();\r
10250         if(clear){\r
10251             this.reset(true);\r
10252         }\r
10253     },\r
10254 \r
10255     \r
10256     stop : function(){\r
10257         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){\r
10258             this.anim.stop();\r
10259         }\r
10260     },\r
10261 \r
10262     \r
10263     show : function(){\r
10264         this.el.show();\r
10265     },\r
10266 \r
10267     \r
10268     sync : function(){\r
10269         this.el.sync();\r
10270     },\r
10271 \r
10272     \r
10273     repair : function(xy, callback, scope){\r
10274         this.callback = callback;\r
10275         this.scope = scope;\r
10276         if(xy && this.animRepair !== false){\r
10277             this.el.addClass("x-dd-drag-repair");\r
10278             this.el.hideUnders(true);\r
10279             this.anim = this.el.shift({\r
10280                 duration: this.repairDuration || .5,\r
10281                 easing: 'easeOut',\r
10282                 xy: xy,\r
10283                 stopFx: true,\r
10284                 callback: this.afterRepair,\r
10285                 scope: this\r
10286             });\r
10287         }else{\r
10288             this.afterRepair();\r
10289         }\r
10290     },\r
10291 \r
10292     // private\r
10293     afterRepair : function(){\r
10294         this.hide(true);\r
10295         if(typeof this.callback == "function"){\r
10296             this.callback.call(this.scope || this);\r
10297         }\r
10298         this.callback = null;\r
10299         this.scope = null;\r
10300     }\r
10301 };\r
10302 \r
10303 Ext.dd.DragSource = function(el, config){\r
10304     this.el = Ext.get(el);\r
10305     if(!this.dragData){\r
10306         this.dragData = {};\r
10307     }\r
10308     \r
10309     Ext.apply(this, config);\r
10310     \r
10311     if(!this.proxy){\r
10312         this.proxy = new Ext.dd.StatusProxy();\r
10313     }\r
10314     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, \r
10315           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});\r
10316     \r
10317     this.dragging = false;\r
10318 };\r
10319 \r
10320 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {\r
10321     \r
10322     \r
10323     dropAllowed : "x-dd-drop-ok",\r
10324     \r
10325     dropNotAllowed : "x-dd-drop-nodrop",\r
10326 \r
10327     \r
10328     getDragData : function(e){\r
10329         return this.dragData;\r
10330     },\r
10331 \r
10332     // private\r
10333     onDragEnter : function(e, id){\r
10334         var target = Ext.dd.DragDropMgr.getDDById(id);\r
10335         this.cachedTarget = target;\r
10336         if(this.beforeDragEnter(target, e, id) !== false){\r
10337             if(target.isNotifyTarget){\r
10338                 var status = target.notifyEnter(this, e, this.dragData);\r
10339                 this.proxy.setStatus(status);\r
10340             }else{\r
10341                 this.proxy.setStatus(this.dropAllowed);\r
10342             }\r
10343             \r
10344             if(this.afterDragEnter){\r
10345                 \r
10346                 this.afterDragEnter(target, e, id);\r
10347             }\r
10348         }\r
10349     },\r
10350 \r
10351     \r
10352     beforeDragEnter : function(target, e, id){\r
10353         return true;\r
10354     },\r
10355 \r
10356     // private\r
10357     alignElWithMouse: function() {\r
10358         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);\r
10359         this.proxy.sync();\r
10360     },\r
10361 \r
10362     // private\r
10363     onDragOver : function(e, id){\r
10364         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
10365         if(this.beforeDragOver(target, e, id) !== false){\r
10366             if(target.isNotifyTarget){\r
10367                 var status = target.notifyOver(this, e, this.dragData);\r
10368                 this.proxy.setStatus(status);\r
10369             }\r
10370 \r
10371             if(this.afterDragOver){\r
10372                 \r
10373                 this.afterDragOver(target, e, id);\r
10374             }\r
10375         }\r
10376     },\r
10377 \r
10378     \r
10379     beforeDragOver : function(target, e, id){\r
10380         return true;\r
10381     },\r
10382 \r
10383     // private\r
10384     onDragOut : function(e, id){\r
10385         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
10386         if(this.beforeDragOut(target, e, id) !== false){\r
10387             if(target.isNotifyTarget){\r
10388                 target.notifyOut(this, e, this.dragData);\r
10389             }\r
10390             this.proxy.reset();\r
10391             if(this.afterDragOut){\r
10392                 \r
10393                 this.afterDragOut(target, e, id);\r
10394             }\r
10395         }\r
10396         this.cachedTarget = null;\r
10397     },\r
10398 \r
10399     \r
10400     beforeDragOut : function(target, e, id){\r
10401         return true;\r
10402     },\r
10403     \r
10404     // private\r
10405     onDragDrop : function(e, id){\r
10406         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
10407         if(this.beforeDragDrop(target, e, id) !== false){\r
10408             if(target.isNotifyTarget){\r
10409                 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?\r
10410                     this.onValidDrop(target, e, id);\r
10411                 }else{\r
10412                     this.onInvalidDrop(target, e, id);\r
10413                 }\r
10414             }else{\r
10415                 this.onValidDrop(target, e, id);\r
10416             }\r
10417             \r
10418             if(this.afterDragDrop){\r
10419                 \r
10420                 this.afterDragDrop(target, e, id);\r
10421             }\r
10422         }\r
10423         delete this.cachedTarget;\r
10424     },\r
10425 \r
10426     \r
10427     beforeDragDrop : function(target, e, id){\r
10428         return true;\r
10429     },\r
10430 \r
10431     // private\r
10432     onValidDrop : function(target, e, id){\r
10433         this.hideProxy();\r
10434         if(this.afterValidDrop){\r
10435             \r
10436             this.afterValidDrop(target, e, id);\r
10437         }\r
10438     },\r
10439 \r
10440     // private\r
10441     getRepairXY : function(e, data){\r
10442         return this.el.getXY();  \r
10443     },\r
10444 \r
10445     // private\r
10446     onInvalidDrop : function(target, e, id){\r
10447         this.beforeInvalidDrop(target, e, id);\r
10448         if(this.cachedTarget){\r
10449             if(this.cachedTarget.isNotifyTarget){\r
10450                 this.cachedTarget.notifyOut(this, e, this.dragData);\r
10451             }\r
10452             this.cacheTarget = null;\r
10453         }\r
10454         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);\r
10455 \r
10456         if(this.afterInvalidDrop){\r
10457             \r
10458             this.afterInvalidDrop(e, id);\r
10459         }\r
10460     },\r
10461 \r
10462     // private\r
10463     afterRepair : function(){\r
10464         if(Ext.enableFx){\r
10465             this.el.highlight(this.hlColor || "c3daf9");\r
10466         }\r
10467         this.dragging = false;\r
10468     },\r
10469 \r
10470     \r
10471     beforeInvalidDrop : function(target, e, id){\r
10472         return true;\r
10473     },\r
10474 \r
10475     // private\r
10476     handleMouseDown : function(e){\r
10477         if(this.dragging) {\r
10478             return;\r
10479         }\r
10480         var data = this.getDragData(e);\r
10481         if(data && this.onBeforeDrag(data, e) !== false){\r
10482             this.dragData = data;\r
10483             this.proxy.stop();\r
10484             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);\r
10485         } \r
10486     },\r
10487 \r
10488     \r
10489     onBeforeDrag : function(data, e){\r
10490         return true;\r
10491     },\r
10492 \r
10493     \r
10494     onStartDrag : Ext.emptyFn,\r
10495 \r
10496     // private override\r
10497     startDrag : function(x, y){\r
10498         this.proxy.reset();\r
10499         this.dragging = true;\r
10500         this.proxy.update("");\r
10501         this.onInitDrag(x, y);\r
10502         this.proxy.show();\r
10503     },\r
10504 \r
10505     // private\r
10506     onInitDrag : function(x, y){\r
10507         var clone = this.el.dom.cloneNode(true);\r
10508         clone.id = Ext.id(); // prevent duplicate ids\r
10509         this.proxy.update(clone);\r
10510         this.onStartDrag(x, y);\r
10511         return true;\r
10512     },\r
10513 \r
10514     \r
10515     getProxy : function(){\r
10516         return this.proxy;  \r
10517     },\r
10518 \r
10519     \r
10520     hideProxy : function(){\r
10521         this.proxy.hide();  \r
10522         this.proxy.reset(true);\r
10523         this.dragging = false;\r
10524     },\r
10525 \r
10526     // private\r
10527     triggerCacheRefresh : function(){\r
10528         Ext.dd.DDM.refreshCache(this.groups);\r
10529     },\r
10530 \r
10531     // private - override to prevent hiding\r
10532     b4EndDrag: function(e) {\r
10533     },\r
10534 \r
10535     // private - override to prevent moving\r
10536     endDrag : function(e){\r
10537         this.onEndDrag(this.dragData, e);\r
10538     },\r
10539 \r
10540     // private\r
10541     onEndDrag : function(data, e){\r
10542     },\r
10543     \r
10544     // private - pin to cursor\r
10545     autoOffset : function(x, y) {\r
10546         this.setDelta(-12, -20);\r
10547     }    \r
10548 });\r
10549 \r
10550 Ext.dd.DropTarget = function(el, config){\r
10551     this.el = Ext.get(el);\r
10552     \r
10553     Ext.apply(this, config);\r
10554     \r
10555     if(this.containerScroll){\r
10556         Ext.dd.ScrollManager.register(this.el);\r
10557     }\r
10558     \r
10559     Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, \r
10560           {isTarget: true});\r
10561 \r
10562 };\r
10563 \r
10564 Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {\r
10565     \r
10566     \r
10567     \r
10568     dropAllowed : "x-dd-drop-ok",\r
10569     \r
10570     dropNotAllowed : "x-dd-drop-nodrop",\r
10571 \r
10572     // private\r
10573     isTarget : true,\r
10574 \r
10575     // private\r
10576     isNotifyTarget : true,\r
10577 \r
10578     \r
10579     notifyEnter : function(dd, e, data){\r
10580         if(this.overClass){\r
10581             this.el.addClass(this.overClass);\r
10582         }\r
10583         return this.dropAllowed;\r
10584     },\r
10585 \r
10586     \r
10587     notifyOver : function(dd, e, data){\r
10588         return this.dropAllowed;\r
10589     },\r
10590 \r
10591     \r
10592     notifyOut : function(dd, e, data){\r
10593         if(this.overClass){\r
10594             this.el.removeClass(this.overClass);\r
10595         }\r
10596     },\r
10597 \r
10598     \r
10599     notifyDrop : function(dd, e, data){\r
10600         return false;\r
10601     }\r
10602 });\r
10603 \r
10604 Ext.dd.DragZone = function(el, config){\r
10605     Ext.dd.DragZone.superclass.constructor.call(this, el, config);\r
10606     if(this.containerScroll){\r
10607         Ext.dd.ScrollManager.register(this.el);\r
10608     }\r
10609 };\r
10610 \r
10611 Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {\r
10612     \r
10613     \r
10614 \r
10615     \r
10616     getDragData : function(e){\r
10617         return Ext.dd.Registry.getHandleFromEvent(e);\r
10618     },\r
10619     \r
10620     \r
10621     onInitDrag : function(x, y){\r
10622         this.proxy.update(this.dragData.ddel.cloneNode(true));\r
10623         this.onStartDrag(x, y);\r
10624         return true;\r
10625     },\r
10626     \r
10627     \r
10628     afterRepair : function(){\r
10629         if(Ext.enableFx){\r
10630             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");\r
10631         }\r
10632         this.dragging = false;\r
10633     },\r
10634 \r
10635     \r
10636     getRepairXY : function(e){\r
10637         return Ext.Element.fly(this.dragData.ddel).getXY();  \r
10638     }\r
10639 });\r
10640 \r
10641 Ext.dd.DropZone = function(el, config){\r
10642     Ext.dd.DropZone.superclass.constructor.call(this, el, config);\r
10643 };\r
10644 \r
10645 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {\r
10646     \r
10647     getTargetFromEvent : function(e){\r
10648         return Ext.dd.Registry.getTargetFromEvent(e);\r
10649     },\r
10650 \r
10651     \r
10652     onNodeEnter : function(n, dd, e, data){\r
10653         \r
10654     },\r
10655 \r
10656     \r
10657     onNodeOver : function(n, dd, e, data){\r
10658         return this.dropAllowed;\r
10659     },\r
10660 \r
10661     \r
10662     onNodeOut : function(n, dd, e, data){\r
10663         \r
10664     },\r
10665 \r
10666     \r
10667     onNodeDrop : function(n, dd, e, data){\r
10668         return false;\r
10669     },\r
10670 \r
10671     \r
10672     onContainerOver : function(dd, e, data){\r
10673         return this.dropNotAllowed;\r
10674     },\r
10675 \r
10676     \r
10677     onContainerDrop : function(dd, e, data){\r
10678         return false;\r
10679     },\r
10680 \r
10681     \r
10682     notifyEnter : function(dd, e, data){\r
10683         return this.dropNotAllowed;\r
10684     },\r
10685 \r
10686     \r
10687     notifyOver : function(dd, e, data){\r
10688         var n = this.getTargetFromEvent(e);\r
10689         if(!n){ // not over valid drop target\r
10690             if(this.lastOverNode){\r
10691                 this.onNodeOut(this.lastOverNode, dd, e, data);\r
10692                 this.lastOverNode = null;\r
10693             }\r
10694             return this.onContainerOver(dd, e, data);\r
10695         }\r
10696         if(this.lastOverNode != n){\r
10697             if(this.lastOverNode){\r
10698                 this.onNodeOut(this.lastOverNode, dd, e, data);\r
10699             }\r
10700             this.onNodeEnter(n, dd, e, data);\r
10701             this.lastOverNode = n;\r
10702         }\r
10703         return this.onNodeOver(n, dd, e, data);\r
10704     },\r
10705 \r
10706     \r
10707     notifyOut : function(dd, e, data){\r
10708         if(this.lastOverNode){\r
10709             this.onNodeOut(this.lastOverNode, dd, e, data);\r
10710             this.lastOverNode = null;\r
10711         }\r
10712     },\r
10713 \r
10714     \r
10715     notifyDrop : function(dd, e, data){\r
10716         if(this.lastOverNode){\r
10717             this.onNodeOut(this.lastOverNode, dd, e, data);\r
10718             this.lastOverNode = null;\r
10719         }\r
10720         var n = this.getTargetFromEvent(e);\r
10721         return n ?\r
10722             this.onNodeDrop(n, dd, e, data) :\r
10723             this.onContainerDrop(dd, e, data);\r
10724     },\r
10725 \r
10726     // private\r
10727     triggerCacheRefresh : function(){\r
10728         Ext.dd.DDM.refreshCache(this.groups);\r
10729     }  \r
10730 });\r
10731 \r
10732 \r
10733 Ext.data.SortTypes = {\r
10734     \r
10735     none : function(s){\r
10736         return s;\r
10737     },\r
10738     \r
10739     \r
10740     stripTagsRE : /<\/?[^>]+>/gi,\r
10741     \r
10742     \r
10743     asText : function(s){\r
10744         return String(s).replace(this.stripTagsRE, "");\r
10745     },\r
10746     \r
10747     \r
10748     asUCText : function(s){\r
10749         return String(s).toUpperCase().replace(this.stripTagsRE, "");\r
10750     },\r
10751     \r
10752     \r
10753     asUCString : function(s) {\r
10754         return String(s).toUpperCase();\r
10755     },\r
10756     \r
10757     \r
10758     asDate : function(s) {\r
10759         if(!s){\r
10760             return 0;\r
10761         }\r
10762         if(Ext.isDate(s)){\r
10763             return s.getTime();\r
10764         }\r
10765         return Date.parse(String(s));\r
10766     },\r
10767     \r
10768     \r
10769     asFloat : function(s) {\r
10770         var val = parseFloat(String(s).replace(/,/g, ""));\r
10771         if(isNaN(val)) val = 0;\r
10772         return val;\r
10773     },\r
10774     \r
10775     \r
10776     asInt : function(s) {\r
10777         var val = parseInt(String(s).replace(/,/g, ""));\r
10778         if(isNaN(val)) val = 0;\r
10779         return val;\r
10780     }\r
10781 };\r
10782 \r
10783 Ext.data.Record = function(data, id){\r
10784     this.id = (id || id === 0) ? id : ++Ext.data.Record.AUTO_ID;\r
10785     this.data = data;\r
10786 };\r
10787 \r
10788 \r
10789 Ext.data.Record.create = function(o){\r
10790     var f = Ext.extend(Ext.data.Record, {});\r
10791     var p = f.prototype;\r
10792     p.fields = new Ext.util.MixedCollection(false, function(field){\r
10793         return field.name;\r
10794     });\r
10795     for(var i = 0, len = o.length; i < len; i++){\r
10796         p.fields.add(new Ext.data.Field(o[i]));\r
10797     }\r
10798     f.getField = function(name){\r
10799         return p.fields.get(name);\r
10800     };\r
10801     return f;\r
10802 };\r
10803 \r
10804 Ext.data.Record.AUTO_ID = 1000;\r
10805 Ext.data.Record.EDIT = 'edit';\r
10806 Ext.data.Record.REJECT = 'reject';\r
10807 Ext.data.Record.COMMIT = 'commit';\r
10808 \r
10809 Ext.data.Record.prototype = {\r
10810     \r
10811     \r
10812     \r
10813     \r
10814     dirty : false,\r
10815     editing : false,\r
10816     error: null,\r
10817     \r
10818     modified: null,\r
10819 \r
10820     // private\r
10821     join : function(store){\r
10822         this.store = store;\r
10823     },\r
10824 \r
10825     \r
10826     set : function(name, value){\r
10827         if(String(this.data[name]) == String(value)){\r
10828             return;\r
10829         }\r
10830         this.dirty = true;\r
10831         if(!this.modified){\r
10832             this.modified = {};\r
10833         }\r
10834         if(typeof this.modified[name] == 'undefined'){\r
10835             this.modified[name] = this.data[name];\r
10836         }\r
10837         this.data[name] = value;\r
10838         if(!this.editing && this.store){\r
10839             this.store.afterEdit(this);\r
10840         }\r
10841     },\r
10842 \r
10843     \r
10844     get : function(name){\r
10845         return this.data[name];\r
10846     },\r
10847 \r
10848     \r
10849     beginEdit : function(){\r
10850         this.editing = true;\r
10851         this.modified = {};\r
10852     },\r
10853 \r
10854     \r
10855     cancelEdit : function(){\r
10856         this.editing = false;\r
10857         delete this.modified;\r
10858     },\r
10859 \r
10860     \r
10861     endEdit : function(){\r
10862         this.editing = false;\r
10863         if(this.dirty && this.store){\r
10864             this.store.afterEdit(this);\r
10865         }\r
10866     },\r
10867 \r
10868     \r
10869     reject : function(silent){\r
10870         var m = this.modified;\r
10871         for(var n in m){\r
10872             if(typeof m[n] != "function"){\r
10873                 this.data[n] = m[n];\r
10874             }\r
10875         }\r
10876         this.dirty = false;\r
10877         delete this.modified;\r
10878         this.editing = false;\r
10879         if(this.store && silent !== true){\r
10880             this.store.afterReject(this);\r
10881         }\r
10882     },\r
10883 \r
10884     \r
10885     commit : function(silent){\r
10886         this.dirty = false;\r
10887         delete this.modified;\r
10888         this.editing = false;\r
10889         if(this.store && silent !== true){\r
10890             this.store.afterCommit(this);\r
10891         }\r
10892     },\r
10893 \r
10894     \r
10895     getChanges : function(){\r
10896         var m = this.modified, cs = {};\r
10897         for(var n in m){\r
10898             if(m.hasOwnProperty(n)){\r
10899                 cs[n] = this.data[n];\r
10900             }\r
10901         }\r
10902         return cs;\r
10903     },\r
10904 \r
10905     // private\r
10906     hasError : function(){\r
10907         return this.error != null;\r
10908     },\r
10909 \r
10910     // private\r
10911     clearError : function(){\r
10912         this.error = null;\r
10913     },\r
10914 \r
10915     \r
10916     copy : function(newId) {\r
10917         return new this.constructor(Ext.apply({}, this.data), newId || this.id);\r
10918     },\r
10919 \r
10920     \r
10921     isModified : function(fieldName){\r
10922         return !!(this.modified && this.modified.hasOwnProperty(fieldName));\r
10923     }\r
10924 };\r
10925 \r
10926 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {\r
10927     \r
10928 \r
10929     \r
10930     register : function(){\r
10931         for(var i = 0, s; s = arguments[i]; i++){\r
10932             this.add(s);\r
10933         }\r
10934     },\r
10935 \r
10936     \r
10937     unregister : function(){\r
10938         for(var i = 0, s; s = arguments[i]; i++){\r
10939             this.remove(this.lookup(s));\r
10940         }\r
10941     },\r
10942 \r
10943     \r
10944     lookup : function(id){\r
10945         return typeof id == "object" ? id : this.get(id);\r
10946     },\r
10947 \r
10948     // getKey implementation for MixedCollection\r
10949     getKey : function(o){\r
10950          return o.storeId || o.id;\r
10951     }\r
10952 });\r
10953 \r
10954 Ext.data.Store = function(config){\r
10955     this.data = new Ext.util.MixedCollection(false);\r
10956     this.data.getKey = function(o){\r
10957         return o.id;\r
10958     };\r
10959     \r
10960     this.baseParams = {};\r
10961     \r
10962     this.paramNames = {\r
10963         "start" : "start",\r
10964         "limit" : "limit",\r
10965         "sort" : "sort",\r
10966         "dir" : "dir"\r
10967     };\r
10968 \r
10969     if(config && config.data){\r
10970         this.inlineData = config.data;\r
10971         delete config.data;\r
10972     }\r
10973 \r
10974     Ext.apply(this, config);\r
10975 \r
10976     if(this.url && !this.proxy){\r
10977         this.proxy = new Ext.data.HttpProxy({url: this.url});\r
10978     }\r
10979 \r
10980     if(this.reader){ // reader passed\r
10981         if(!this.recordType){\r
10982             this.recordType = this.reader.recordType;\r
10983         }\r
10984         if(this.reader.onMetaChange){\r
10985             this.reader.onMetaChange = this.onMetaChange.createDelegate(this);\r
10986         }\r
10987     }\r
10988 \r
10989     \r
10990     if(this.recordType){\r
10991         \r
10992         this.fields = this.recordType.prototype.fields;\r
10993     }\r
10994     this.modified = [];\r
10995 \r
10996     this.addEvents(\r
10997         \r
10998         'datachanged',\r
10999         \r
11000         'metachange',\r
11001         \r
11002         'add',\r
11003         \r
11004         'remove',\r
11005         \r
11006         'update',\r
11007         \r
11008         'clear',\r
11009         \r
11010         'beforeload',\r
11011         \r
11012         'load',\r
11013         \r
11014         'loadexception'\r
11015     );\r
11016 \r
11017     if(this.proxy){\r
11018         this.relayEvents(this.proxy,  ["loadexception"]);\r
11019     }\r
11020 \r
11021     this.sortToggle = {};\r
11022     if(this.sortInfo){\r
11023         this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);\r
11024     }\r
11025 \r
11026     Ext.data.Store.superclass.constructor.call(this);\r
11027 \r
11028     if(this.storeId || this.id){\r
11029         Ext.StoreMgr.register(this);\r
11030     }\r
11031     if(this.inlineData){\r
11032         this.loadData(this.inlineData);\r
11033         delete this.inlineData;\r
11034     }else if(this.autoLoad){\r
11035         this.load.defer(10, this, [\r
11036             typeof this.autoLoad == 'object' ?\r
11037                 this.autoLoad : undefined]);\r
11038     }\r
11039 };\r
11040 Ext.extend(Ext.data.Store, Ext.util.Observable, {\r
11041     \r
11042     \r
11043     \r
11044     \r
11045     \r
11046     \r
11047     \r
11048     \r
11049     \r
11050     remoteSort : false,\r
11051 \r
11052     \r
11053     pruneModifiedRecords : false,\r
11054 \r
11055     \r
11056    lastOptions : null,\r
11057 \r
11058     destroy : function(){\r
11059         if(this.storeId || this.id){\r
11060             Ext.StoreMgr.unregister(this);\r
11061         }\r
11062         this.data = null;\r
11063         this.purgeListeners();\r
11064     },\r
11065 \r
11066     \r
11067     add : function(records){\r
11068         records = [].concat(records);\r
11069         if(records.length < 1){\r
11070             return;\r
11071         }\r
11072         for(var i = 0, len = records.length; i < len; i++){\r
11073             records[i].join(this);\r
11074         }\r
11075         var index = this.data.length;\r
11076         this.data.addAll(records);\r
11077         if(this.snapshot){\r
11078             this.snapshot.addAll(records);\r
11079         }\r
11080         this.fireEvent("add", this, records, index);\r
11081     },\r
11082 \r
11083     \r
11084     addSorted : function(record){\r
11085         var index = this.findInsertIndex(record);\r
11086         this.insert(index, record);\r
11087     },\r
11088 \r
11089     \r
11090     remove : function(record){\r
11091         var index = this.data.indexOf(record);\r
11092         this.data.removeAt(index);\r
11093         if(this.pruneModifiedRecords){\r
11094             this.modified.remove(record);\r
11095         }\r
11096         if(this.snapshot){\r
11097             this.snapshot.remove(record);\r
11098         }\r
11099         this.fireEvent("remove", this, record, index);\r
11100     },\r
11101     \r
11102     \r
11103     removeAt : function(index){\r
11104         this.remove(this.getAt(index));    \r
11105     },\r
11106 \r
11107     \r
11108     removeAll : function(){\r
11109         this.data.clear();\r
11110         if(this.snapshot){\r
11111             this.snapshot.clear();\r
11112         }\r
11113         if(this.pruneModifiedRecords){\r
11114             this.modified = [];\r
11115         }\r
11116         this.fireEvent("clear", this);\r
11117     },\r
11118 \r
11119     \r
11120     insert : function(index, records){\r
11121         records = [].concat(records);\r
11122         for(var i = 0, len = records.length; i < len; i++){\r
11123             this.data.insert(index, records[i]);\r
11124             records[i].join(this);\r
11125         }\r
11126         this.fireEvent("add", this, records, index);\r
11127     },\r
11128 \r
11129     \r
11130     indexOf : function(record){\r
11131         return this.data.indexOf(record);\r
11132     },\r
11133 \r
11134     \r
11135     indexOfId : function(id){\r
11136         return this.data.indexOfKey(id);\r
11137     },\r
11138 \r
11139     \r
11140     getById : function(id){\r
11141         return this.data.key(id);\r
11142     },\r
11143 \r
11144     \r
11145     getAt : function(index){\r
11146         return this.data.itemAt(index);\r
11147     },\r
11148 \r
11149     \r
11150     getRange : function(start, end){\r
11151         return this.data.getRange(start, end);\r
11152     },\r
11153 \r
11154     // private\r
11155     storeOptions : function(o){\r
11156         o = Ext.apply({}, o);\r
11157         delete o.callback;\r
11158         delete o.scope;\r
11159         this.lastOptions = o;\r
11160     },\r
11161 \r
11162     \r
11163     load : function(options){\r
11164         options = options || {};\r
11165         if(this.fireEvent("beforeload", this, options) !== false){\r
11166             this.storeOptions(options);\r
11167             var p = Ext.apply(options.params || {}, this.baseParams);\r
11168             if(this.sortInfo && this.remoteSort){\r
11169                 var pn = this.paramNames;\r
11170                 p[pn["sort"]] = this.sortInfo.field;\r
11171                 p[pn["dir"]] = this.sortInfo.direction;\r
11172             }\r
11173             this.proxy.load(p, this.reader, this.loadRecords, this, options);\r
11174             return true;\r
11175         } else {\r
11176           return false;\r
11177         }\r
11178     },\r
11179 \r
11180     \r
11181     reload : function(options){\r
11182         this.load(Ext.applyIf(options||{}, this.lastOptions));\r
11183     },\r
11184 \r
11185     // private\r
11186     // Called as a callback by the Reader during a load operation.\r
11187     loadRecords : function(o, options, success){\r
11188         if(!o || success === false){\r
11189             if(success !== false){\r
11190                 this.fireEvent("load", this, [], options);\r
11191             }\r
11192             if(options.callback){\r
11193                 options.callback.call(options.scope || this, [], options, false);\r
11194             }\r
11195             return;\r
11196         }\r
11197         var r = o.records, t = o.totalRecords || r.length;\r
11198         if(!options || options.add !== true){\r
11199             if(this.pruneModifiedRecords){\r
11200                 this.modified = [];\r
11201             }\r
11202             for(var i = 0, len = r.length; i < len; i++){\r
11203                 r[i].join(this);\r
11204             }\r
11205             if(this.snapshot){\r
11206                 this.data = this.snapshot;\r
11207                 delete this.snapshot;\r
11208             }\r
11209             this.data.clear();\r
11210             this.data.addAll(r);\r
11211             this.totalLength = t;\r
11212             this.applySort();\r
11213             this.fireEvent("datachanged", this);\r
11214         }else{\r
11215             this.totalLength = Math.max(t, this.data.length+r.length);\r
11216             this.add(r);\r
11217         }\r
11218         this.fireEvent("load", this, r, options);\r
11219         if(options.callback){\r
11220             options.callback.call(options.scope || this, r, options, true);\r
11221         }\r
11222     },\r
11223 \r
11224     \r
11225     loadData : function(o, append){\r
11226         var r = this.reader.readRecords(o);\r
11227         this.loadRecords(r, {add: append}, true);\r
11228     },\r
11229 \r
11230     \r
11231     getCount : function(){\r
11232         return this.data.length || 0;\r
11233     },\r
11234 \r
11235     \r
11236     getTotalCount : function(){\r
11237         return this.totalLength || 0;\r
11238     },\r
11239 \r
11240     \r
11241     getSortState : function(){\r
11242         return this.sortInfo;\r
11243     },\r
11244 \r
11245     // private\r
11246     applySort : function(){\r
11247         if(this.sortInfo && !this.remoteSort){\r
11248             var s = this.sortInfo, f = s.field;\r
11249             this.sortData(f, s.direction);\r
11250         }\r
11251     },\r
11252 \r
11253     // private\r
11254     sortData : function(f, direction){\r
11255         direction = direction || 'ASC';\r
11256         var st = this.fields.get(f).sortType;\r
11257         var fn = function(r1, r2){\r
11258             var v1 = st(r1.data[f]), v2 = st(r2.data[f]);\r
11259             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);\r
11260         };\r
11261         this.data.sort(direction, fn);\r
11262         if(this.snapshot && this.snapshot != this.data){\r
11263             this.snapshot.sort(direction, fn);\r
11264         }\r
11265     },\r
11266 \r
11267     \r
11268     setDefaultSort : function(field, dir){\r
11269         dir = dir ? dir.toUpperCase() : "ASC";\r
11270         this.sortInfo = {field: field, direction: dir};\r
11271         this.sortToggle[field] = dir;\r
11272     },\r
11273 \r
11274     \r
11275     sort : function(fieldName, dir){\r
11276         var f = this.fields.get(fieldName);\r
11277         if(!f){\r
11278             return false;\r
11279         }\r
11280         if(!dir){\r
11281             if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir\r
11282                 dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");\r
11283             }else{\r
11284                 dir = f.sortDir;\r
11285             }\r
11286         }\r
11287         var st = (this.sortToggle) ? this.sortToggle[f.name] : null;\r
11288         var si = (this.sortInfo) ? this.sortInfo : null;\r
11289 \r
11290         this.sortToggle[f.name] = dir;\r
11291         this.sortInfo = {field: f.name, direction: dir};\r
11292         if(!this.remoteSort){\r
11293             this.applySort();\r
11294             this.fireEvent("datachanged", this);\r
11295         }else{\r
11296             if (!this.load(this.lastOptions)) {\r
11297                 if (st) {\r
11298                     this.sortToggle[f.name] = st;\r
11299                 }\r
11300                 if (si) {\r
11301                     this.sortInfo = si;\r
11302                 }\r
11303             }\r
11304         }\r
11305     },\r
11306 \r
11307     \r
11308     each : function(fn, scope){\r
11309         this.data.each(fn, scope);\r
11310     },\r
11311 \r
11312     \r
11313     getModifiedRecords : function(){\r
11314         return this.modified;\r
11315     },\r
11316 \r
11317     // private\r
11318     createFilterFn : function(property, value, anyMatch, caseSensitive){\r
11319         if(Ext.isEmpty(value, false)){\r
11320             return false;\r
11321         }\r
11322         value = this.data.createValueMatcher(value, anyMatch, caseSensitive);\r
11323         return function(r){\r
11324             return value.test(r.data[property]);\r
11325         };\r
11326     },\r
11327 \r
11328     \r
11329     sum : function(property, start, end){\r
11330         var rs = this.data.items, v = 0;\r
11331         start = start || 0;\r
11332         end = (end || end === 0) ? end : rs.length-1;\r
11333 \r
11334         for(var i = start; i <= end; i++){\r
11335             v += (rs[i].data[property] || 0);\r
11336         }\r
11337         return v;\r
11338     },\r
11339 \r
11340     \r
11341     filter : function(property, value, anyMatch, caseSensitive){\r
11342         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);\r
11343         return fn ? this.filterBy(fn) : this.clearFilter();\r
11344     },\r
11345 \r
11346     \r
11347     filterBy : function(fn, scope){\r
11348         this.snapshot = this.snapshot || this.data;\r
11349         this.data = this.queryBy(fn, scope||this);\r
11350         this.fireEvent("datachanged", this);\r
11351     },\r
11352 \r
11353     \r
11354     query : function(property, value, anyMatch, caseSensitive){\r
11355         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);\r
11356         return fn ? this.queryBy(fn) : this.data.clone();\r
11357     },\r
11358 \r
11359     \r
11360     queryBy : function(fn, scope){\r
11361         var data = this.snapshot || this.data;\r
11362         return data.filterBy(fn, scope||this);\r
11363     },\r
11364 \r
11365     \r
11366     find : function(property, value, start, anyMatch, caseSensitive){\r
11367         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);\r
11368         return fn ? this.data.findIndexBy(fn, null, start) : -1;\r
11369     },\r
11370 \r
11371     \r
11372     findBy : function(fn, scope, start){\r
11373         return this.data.findIndexBy(fn, scope, start);\r
11374     },\r
11375 \r
11376     \r
11377     collect : function(dataIndex, allowNull, bypassFilter){\r
11378         var d = (bypassFilter === true && this.snapshot) ?\r
11379                 this.snapshot.items : this.data.items;\r
11380         var v, sv, r = [], l = {};\r
11381         for(var i = 0, len = d.length; i < len; i++){\r
11382             v = d[i].data[dataIndex];\r
11383             sv = String(v);\r
11384             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){\r
11385                 l[sv] = true;\r
11386                 r[r.length] = v;\r
11387             }\r
11388         }\r
11389         return r;\r
11390     },\r
11391 \r
11392     \r
11393     clearFilter : function(suppressEvent){\r
11394         if(this.isFiltered()){\r
11395             this.data = this.snapshot;\r
11396             delete this.snapshot;\r
11397             if(suppressEvent !== true){\r
11398                 this.fireEvent("datachanged", this);\r
11399             }\r
11400         }\r
11401     },\r
11402 \r
11403     \r
11404     isFiltered : function(){\r
11405         return this.snapshot && this.snapshot != this.data;\r
11406     },\r
11407 \r
11408     // private\r
11409     afterEdit : function(record){\r
11410         if(this.modified.indexOf(record) == -1){\r
11411             this.modified.push(record);\r
11412         }\r
11413         this.fireEvent("update", this, record, Ext.data.Record.EDIT);\r
11414     },\r
11415 \r
11416     // private\r
11417     afterReject : function(record){\r
11418         this.modified.remove(record);\r
11419         this.fireEvent("update", this, record, Ext.data.Record.REJECT);\r
11420     },\r
11421 \r
11422     // private\r
11423     afterCommit : function(record){\r
11424         this.modified.remove(record);\r
11425         this.fireEvent("update", this, record, Ext.data.Record.COMMIT);\r
11426     },\r
11427 \r
11428     \r
11429     commitChanges : function(){\r
11430         var m = this.modified.slice(0);\r
11431         this.modified = [];\r
11432         for(var i = 0, len = m.length; i < len; i++){\r
11433             m[i].commit();\r
11434         }\r
11435     },\r
11436 \r
11437     \r
11438     rejectChanges : function(){\r
11439         var m = this.modified.slice(0);\r
11440         this.modified = [];\r
11441         for(var i = 0, len = m.length; i < len; i++){\r
11442             m[i].reject();\r
11443         }\r
11444     },\r
11445 \r
11446     // private\r
11447     onMetaChange : function(meta, rtype, o){\r
11448         this.recordType = rtype;\r
11449         this.fields = rtype.prototype.fields;\r
11450         delete this.snapshot;\r
11451         this.sortInfo = meta.sortInfo;\r
11452         this.modified = [];\r
11453         this.fireEvent('metachange', this, this.reader.meta);\r
11454     },\r
11455 \r
11456     // private\r
11457     findInsertIndex : function(record){\r
11458         this.suspendEvents();\r
11459         var data = this.data.clone();\r
11460         this.data.add(record);\r
11461         this.applySort();\r
11462         var index = this.data.indexOf(record);\r
11463         this.data = data;\r
11464         this.resumeEvents();\r
11465         return index;\r
11466     }\r
11467 });\r
11468 \r
11469 Ext.data.SimpleStore = function(config){\r
11470     Ext.data.SimpleStore.superclass.constructor.call(this, Ext.apply(config, {\r
11471         reader: new Ext.data.ArrayReader({\r
11472                 id: config.id\r
11473             },\r
11474             Ext.data.Record.create(config.fields)\r
11475         )\r
11476     }));\r
11477 };\r
11478 Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {\r
11479     loadData : function(data, append){\r
11480         if(this.expandData === true){\r
11481             var r = [];\r
11482             for(var i = 0, len = data.length; i < len; i++){\r
11483                 r[r.length] = [data[i]];\r
11484             }\r
11485             data = r;\r
11486         }\r
11487         Ext.data.SimpleStore.superclass.loadData.call(this, data, append);\r
11488     }\r
11489 });\r
11490 \r
11491 Ext.data.JsonStore = function(c){\r
11492     \r
11493     \r
11494     Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(c, {\r
11495         proxy: c.proxy || (!c.data ? new Ext.data.HttpProxy({url: c.url}) : undefined),\r
11496         reader: new Ext.data.JsonReader(c, c.fields)\r
11497     }));\r
11498 };\r
11499 Ext.extend(Ext.data.JsonStore, Ext.data.Store);\r
11500 \r
11501 Ext.data.Field = function(config){\r
11502     if(typeof config == "string"){\r
11503         config = {name: config};\r
11504     }\r
11505     Ext.apply(this, config);\r
11506     \r
11507     if(!this.type){\r
11508         this.type = "auto";\r
11509     }\r
11510     \r
11511     var st = Ext.data.SortTypes;\r
11512     // named sortTypes are supported, here we look them up\r
11513     if(typeof this.sortType == "string"){\r
11514         this.sortType = st[this.sortType];\r
11515     }\r
11516     \r
11517     // set default sortType for strings and dates\r
11518     if(!this.sortType){\r
11519         switch(this.type){\r
11520             case "string":\r
11521                 this.sortType = st.asUCString;\r
11522                 break;\r
11523             case "date":\r
11524                 this.sortType = st.asDate;\r
11525                 break;\r
11526             default:\r
11527                 this.sortType = st.none;\r
11528         }\r
11529     }\r
11530 \r
11531     // define once\r
11532     var stripRe = /[\$,%]/g;\r
11533 \r
11534     // prebuilt conversion function for this field, instead of\r
11535     // switching every time we're reading a value\r
11536     if(!this.convert){\r
11537         var cv, dateFormat = this.dateFormat;\r
11538         switch(this.type){\r
11539             case "":\r
11540             case "auto":\r
11541             case undefined:\r
11542                 cv = function(v){ return v; };\r
11543                 break;\r
11544             case "string":\r
11545                 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };\r
11546                 break;\r
11547             case "int":\r
11548                 cv = function(v){\r
11549                     return v !== undefined && v !== null && v !== '' ?\r
11550                            parseInt(String(v).replace(stripRe, ""), 10) : '';\r
11551                     };\r
11552                 break;\r
11553             case "float":\r
11554                 cv = function(v){\r
11555                     return v !== undefined && v !== null && v !== '' ?\r
11556                            parseFloat(String(v).replace(stripRe, ""), 10) : ''; \r
11557                     };\r
11558                 break;\r
11559             case "bool":\r
11560             case "boolean":\r
11561                 cv = function(v){ return v === true || v === "true" || v == 1; };\r
11562                 break;\r
11563             case "date":\r
11564                 cv = function(v){\r
11565                     if(!v){\r
11566                         return '';\r
11567                     }\r
11568                     if(Ext.isDate(v)){\r
11569                         return v;\r
11570                     }\r
11571                     if(dateFormat){\r
11572                         if(dateFormat == "timestamp"){\r
11573                             return new Date(v*1000);\r
11574                         }\r
11575                         if(dateFormat == "time"){\r
11576                             return new Date(parseInt(v, 10));\r
11577                         }\r
11578                         return Date.parseDate(v, dateFormat);\r
11579                     }\r
11580                     var parsed = Date.parse(v);\r
11581                     return parsed ? new Date(parsed) : null;\r
11582                 };\r
11583              break;\r
11584             \r
11585         }\r
11586         this.convert = cv;\r
11587     }\r
11588 };\r
11589 \r
11590 Ext.data.Field.prototype = {\r
11591     \r
11592     \r
11593     \r
11594     \r
11595     dateFormat: null,\r
11596     \r
11597     defaultValue: "",\r
11598     \r
11599     mapping: null,\r
11600     \r
11601     sortType : null,\r
11602     \r
11603     sortDir : "ASC"\r
11604 };\r
11605 \r
11606 Ext.data.DataReader = function(meta, recordType){\r
11607     \r
11608     this.meta = meta;\r
11609     this.recordType = Ext.isArray(recordType) ? \r
11610         Ext.data.Record.create(recordType) : recordType;\r
11611 };\r
11612 \r
11613 Ext.data.DataReader.prototype = {\r
11614     \r
11615 };\r
11616 \r
11617 Ext.data.DataProxy = function(){\r
11618     this.addEvents(\r
11619         \r
11620         'beforeload',\r
11621         \r
11622         'load'\r
11623     );\r
11624     Ext.data.DataProxy.superclass.constructor.call(this);\r
11625 };\r
11626 \r
11627 Ext.extend(Ext.data.DataProxy, Ext.util.Observable);\r
11628 \r
11629 Ext.data.MemoryProxy = function(data){\r
11630     Ext.data.MemoryProxy.superclass.constructor.call(this);\r
11631     this.data = data;\r
11632 };\r
11633 \r
11634 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {\r
11635     \r
11636     \r
11637     \r
11638     load : function(params, reader, callback, scope, arg){\r
11639         params = params || {};\r
11640         var result;\r
11641         try {\r
11642             result = reader.readRecords(this.data);\r
11643         }catch(e){\r
11644             this.fireEvent("loadexception", this, arg, null, e);\r
11645             callback.call(scope, null, arg, false);\r
11646             return;\r
11647         }\r
11648         callback.call(scope, result, arg, true);\r
11649     },\r
11650     \r
11651     // private\r
11652     update : function(params, records){\r
11653         \r
11654     }\r
11655 });\r
11656 \r
11657 Ext.data.HttpProxy = function(conn){\r
11658     Ext.data.HttpProxy.superclass.constructor.call(this);\r
11659     \r
11660     this.conn = conn;\r
11661     this.useAjax = !conn || !conn.events;\r
11662 \r
11663     \r
11664 };\r
11665 \r
11666 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {\r
11667     \r
11668     getConnection : function(){\r
11669         return this.useAjax ? Ext.Ajax : this.conn;\r
11670     },\r
11671 \r
11672     \r
11673     load : function(params, reader, callback, scope, arg){\r
11674         if(this.fireEvent("beforeload", this, params) !== false){\r
11675             var  o = {\r
11676                 params : params || {},\r
11677                 request: {\r
11678                     callback : callback,\r
11679                     scope : scope,\r
11680                     arg : arg\r
11681                 },\r
11682                 reader: reader,\r
11683                 callback : this.loadResponse,\r
11684                 scope: this\r
11685             };\r
11686             if(this.useAjax){\r
11687                 Ext.applyIf(o, this.conn);\r
11688                 if(this.activeRequest){\r
11689                     Ext.Ajax.abort(this.activeRequest);\r
11690                 }\r
11691                 this.activeRequest = Ext.Ajax.request(o);\r
11692             }else{\r
11693                 this.conn.request(o);\r
11694             }\r
11695         }else{\r
11696             callback.call(scope||this, null, arg, false);\r
11697         }\r
11698     },\r
11699 \r
11700     // private\r
11701     loadResponse : function(o, success, response){\r
11702         delete this.activeRequest;\r
11703         if(!success){\r
11704             this.fireEvent("loadexception", this, o, response);\r
11705             o.request.callback.call(o.request.scope, null, o.request.arg, false);\r
11706             return;\r
11707         }\r
11708         var result;\r
11709         try {\r
11710             result = o.reader.read(response);\r
11711         }catch(e){\r
11712             this.fireEvent("loadexception", this, o, response, e);\r
11713             o.request.callback.call(o.request.scope, null, o.request.arg, false);\r
11714             return;\r
11715         }\r
11716         this.fireEvent("load", this, o, o.request.arg);\r
11717         o.request.callback.call(o.request.scope, result, o.request.arg, true);\r
11718     },\r
11719     \r
11720     // private\r
11721     update : function(dataSet){\r
11722         \r
11723     },\r
11724     \r
11725     // private\r
11726     updateResponse : function(dataSet){\r
11727         \r
11728     }\r
11729 });\r
11730 \r
11731 Ext.data.ScriptTagProxy = function(config){\r
11732     Ext.data.ScriptTagProxy.superclass.constructor.call(this);\r
11733     Ext.apply(this, config);\r
11734     this.head = document.getElementsByTagName("head")[0];\r
11735     \r
11736     \r
11737 };\r
11738 \r
11739 Ext.data.ScriptTagProxy.TRANS_ID = 1000;\r
11740 \r
11741 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {\r
11742     \r
11743     \r
11744     timeout : 30000,\r
11745     \r
11746     callbackParam : "callback",\r
11747     \r
11748     nocache : true,\r
11749 \r
11750     \r
11751     load : function(params, reader, callback, scope, arg){\r
11752         if(this.fireEvent("beforeload", this, params) !== false){\r
11753 \r
11754             var p = Ext.urlEncode(Ext.apply(params, this.extraParams));\r
11755 \r
11756             var url = this.url;\r
11757             url += (url.indexOf("?") != -1 ? "&" : "?") + p;\r
11758             if(this.nocache){\r
11759                 url += "&_dc=" + (new Date().getTime());\r
11760             }\r
11761             var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;\r
11762             var trans = {\r
11763                 id : transId,\r
11764                 cb : "stcCallback"+transId,\r
11765                 scriptId : "stcScript"+transId,\r
11766                 params : params,\r
11767                 arg : arg,\r
11768                 url : url,\r
11769                 callback : callback,\r
11770                 scope : scope,\r
11771                 reader : reader\r
11772             };\r
11773             var conn = this;\r
11774 \r
11775             window[trans.cb] = function(o){\r
11776                 conn.handleResponse(o, trans);\r
11777             };\r
11778 \r
11779             url += String.format("&{0}={1}", this.callbackParam, trans.cb);\r
11780 \r
11781             if(this.autoAbort !== false){\r
11782                 this.abort();\r
11783             }\r
11784 \r
11785             trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);\r
11786 \r
11787             var script = document.createElement("script");\r
11788             script.setAttribute("src", url);\r
11789             script.setAttribute("type", "text/javascript");\r
11790             script.setAttribute("id", trans.scriptId);\r
11791             this.head.appendChild(script);\r
11792 \r
11793             this.trans = trans;\r
11794         }else{\r
11795             callback.call(scope||this, null, arg, false);\r
11796         }\r
11797     },\r
11798 \r
11799     // private\r
11800     isLoading : function(){\r
11801         return this.trans ? true : false;\r
11802     },\r
11803 \r
11804     \r
11805     abort : function(){\r
11806         if(this.isLoading()){\r
11807             this.destroyTrans(this.trans);\r
11808         }\r
11809     },\r
11810 \r
11811     // private\r
11812     destroyTrans : function(trans, isLoaded){\r
11813         this.head.removeChild(document.getElementById(trans.scriptId));\r
11814         clearTimeout(trans.timeoutId);\r
11815         if(isLoaded){\r
11816             window[trans.cb] = undefined;\r
11817             try{\r
11818                 delete window[trans.cb];\r
11819             }catch(e){}\r
11820         }else{\r
11821             // if hasn't been loaded, wait for load to remove it to prevent script error\r
11822             window[trans.cb] = function(){\r
11823                 window[trans.cb] = undefined;\r
11824                 try{\r
11825                     delete window[trans.cb];\r
11826                 }catch(e){}\r
11827             };\r
11828         }\r
11829     },\r
11830 \r
11831     // private\r
11832     handleResponse : function(o, trans){\r
11833         this.trans = false;\r
11834         this.destroyTrans(trans, true);\r
11835         var result;\r
11836         try {\r
11837             result = trans.reader.readRecords(o);\r
11838         }catch(e){\r
11839             this.fireEvent("loadexception", this, o, trans.arg, e);\r
11840             trans.callback.call(trans.scope||window, null, trans.arg, false);\r
11841             return;\r
11842         }\r
11843         this.fireEvent("load", this, o, trans.arg);\r
11844         trans.callback.call(trans.scope||window, result, trans.arg, true);\r
11845     },\r
11846 \r
11847     // private\r
11848     handleFailure : function(trans){\r
11849         this.trans = false;\r
11850         this.destroyTrans(trans, false);\r
11851         this.fireEvent("loadexception", this, null, trans.arg);\r
11852         trans.callback.call(trans.scope||window, null, trans.arg, false);\r
11853     }\r
11854 });\r
11855 \r
11856 Ext.data.JsonReader = function(meta, recordType){\r
11857     meta = meta || {};\r
11858     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);\r
11859 };\r
11860 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {\r
11861     \r
11862     \r
11863     read : function(response){\r
11864         var json = response.responseText;\r
11865         var o = eval("("+json+")");\r
11866         if(!o) {\r
11867             throw {message: "JsonReader.read: Json object not found"};\r
11868         }\r
11869         return this.readRecords(o);\r
11870     },\r
11871 \r
11872     // private function a store will implement\r
11873     onMetaChange : function(meta, recordType, o){\r
11874 \r
11875     },\r
11876 \r
11877     \r
11878     simpleAccess: function(obj, subsc) {\r
11879         return obj[subsc];\r
11880     },\r
11881 \r
11882         \r
11883     getJsonAccessor: function(){\r
11884         var re = /[\[\.]/;\r
11885         return function(expr) {\r
11886             try {\r
11887                 return(re.test(expr))\r
11888                     ? new Function("obj", "return obj." + expr)\r
11889                     : function(obj){\r
11890                         return obj[expr];\r
11891                     };\r
11892             } catch(e){}\r
11893             return Ext.emptyFn;\r
11894         };\r
11895     }(),\r
11896 \r
11897     \r
11898     readRecords : function(o){\r
11899         \r
11900         this.jsonData = o;\r
11901         if(o.metaData){\r
11902             delete this.ef;\r
11903             this.meta = o.metaData;\r
11904             this.recordType = Ext.data.Record.create(o.metaData.fields);\r
11905             this.onMetaChange(this.meta, this.recordType, o);\r
11906         }\r
11907         var s = this.meta, Record = this.recordType,\r
11908             f = Record.prototype.fields, fi = f.items, fl = f.length;\r
11909 \r
11910 //      Generate extraction functions for the totalProperty, the root, the id, and for each field\r
11911         if (!this.ef) {\r
11912             if(s.totalProperty) {\r
11913                     this.getTotal = this.getJsonAccessor(s.totalProperty);\r
11914                 }\r
11915                 if(s.successProperty) {\r
11916                     this.getSuccess = this.getJsonAccessor(s.successProperty);\r
11917                 }\r
11918                 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};\r
11919                 if (s.id) {\r
11920                         var g = this.getJsonAccessor(s.id);\r
11921                         this.getId = function(rec) {\r
11922                                 var r = g(rec);\r
11923                                 return (r === undefined || r === "") ? null : r;\r
11924                         };\r
11925                 } else {\r
11926                         this.getId = function(){return null;};\r
11927                 }\r
11928             this.ef = [];\r
11929             for(var i = 0; i < fl; i++){\r
11930                 f = fi[i];\r
11931                 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;\r
11932                 this.ef[i] = this.getJsonAccessor(map);\r
11933             }\r
11934         }\r
11935 \r
11936         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;\r
11937         if(s.totalProperty){\r
11938             var v = parseInt(this.getTotal(o), 10);\r
11939             if(!isNaN(v)){\r
11940                 totalRecords = v;\r
11941             }\r
11942         }\r
11943         if(s.successProperty){\r
11944             var v = this.getSuccess(o);\r
11945             if(v === false || v === 'false'){\r
11946                 success = false;\r
11947             }\r
11948         }\r
11949         var records = [];\r
11950             for(var i = 0; i < c; i++){\r
11951                     var n = root[i];\r
11952                 var values = {};\r
11953                 var id = this.getId(n);\r
11954                 for(var j = 0; j < fl; j++){\r
11955                     f = fi[j];\r
11956                 var v = this.ef[j](n);\r
11957                 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);\r
11958                 }\r
11959                 var record = new Record(values, id);\r
11960                 record.json = n;\r
11961                 records[i] = record;\r
11962             }\r
11963             return {\r
11964                 success : success,\r
11965                 records : records,\r
11966                 totalRecords : totalRecords\r
11967             };\r
11968     }\r
11969 });\r
11970 \r
11971 Ext.data.XmlReader = function(meta, recordType){\r
11972     meta = meta || {};\r
11973     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);\r
11974 };\r
11975 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {\r
11976     \r
11977     read : function(response){\r
11978         var doc = response.responseXML;\r
11979         if(!doc) {\r
11980             throw {message: "XmlReader.read: XML Document not available"};\r
11981         }\r
11982         return this.readRecords(doc);\r
11983     },\r
11984 \r
11985     \r
11986     readRecords : function(doc){\r
11987         \r
11988         this.xmlData = doc;\r
11989         var root = doc.documentElement || doc;\r
11990         var q = Ext.DomQuery;\r
11991         var recordType = this.recordType, fields = recordType.prototype.fields;\r
11992         var sid = this.meta.id;\r
11993         var totalRecords = 0, success = true;\r
11994         if(this.meta.totalRecords){\r
11995             totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);\r
11996         }\r
11997 \r
11998         if(this.meta.success){\r
11999             var sv = q.selectValue(this.meta.success, root, true);\r
12000             success = sv !== false && sv !== 'false';\r
12001         }\r
12002         var records = [];\r
12003         var ns = q.select(this.meta.record, root);\r
12004         for(var i = 0, len = ns.length; i < len; i++) {\r
12005                 var n = ns[i];\r
12006                 var values = {};\r
12007                 var id = sid ? q.selectValue(sid, n) : undefined;\r
12008                 for(var j = 0, jlen = fields.length; j < jlen; j++){\r
12009                     var f = fields.items[j];\r
12010                 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);\r
12011                     v = f.convert(v, n);\r
12012                     values[f.name] = v;\r
12013                 }\r
12014                 var record = new recordType(values, id);\r
12015                 record.node = n;\r
12016                 records[records.length] = record;\r
12017             }\r
12018 \r
12019             return {\r
12020                 success : success,\r
12021                 records : records,\r
12022                 totalRecords : totalRecords || records.length\r
12023             };\r
12024     }\r
12025 });\r
12026 \r
12027 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {\r
12028     \r
12029     readRecords : function(o){\r
12030         var sid = this.meta ? this.meta.id : null;\r
12031         var recordType = this.recordType, fields = recordType.prototype.fields;\r
12032         var records = [];\r
12033         var root = o;\r
12034             for(var i = 0; i < root.length; i++){\r
12035                     var n = root[i];\r
12036                 var values = {};\r
12037                 var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);\r
12038                 for(var j = 0, jlen = fields.length; j < jlen; j++){\r
12039                 var f = fields.items[j];\r
12040                 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;\r
12041                 var v = n[k] !== undefined ? n[k] : f.defaultValue;\r
12042                 v = f.convert(v, n);\r
12043                 values[f.name] = v;\r
12044             }\r
12045                 var record = new recordType(values, id);\r
12046                 record.json = n;\r
12047                 records[records.length] = record;\r
12048             }\r
12049             return {\r
12050                 records : records,\r
12051                 totalRecords : records.length\r
12052             };\r
12053     }\r
12054 });\r
12055 \r
12056 Ext.data.Tree = function(root){\r
12057    this.nodeHash = {};\r
12058    \r
12059    this.root = null;\r
12060    if(root){\r
12061        this.setRootNode(root);\r
12062    }\r
12063    this.addEvents(\r
12064        \r
12065        "append",\r
12066        \r
12067        "remove",\r
12068        \r
12069        "move",\r
12070        \r
12071        "insert",\r
12072        \r
12073        "beforeappend",\r
12074        \r
12075        "beforeremove",\r
12076        \r
12077        "beforemove",\r
12078        \r
12079        "beforeinsert"\r
12080    );\r
12081 \r
12082     Ext.data.Tree.superclass.constructor.call(this);\r
12083 };\r
12084 \r
12085 Ext.extend(Ext.data.Tree, Ext.util.Observable, {\r
12086     \r
12087     pathSeparator: "/",\r
12088 \r
12089     // private\r
12090     proxyNodeEvent : function(){\r
12091         return this.fireEvent.apply(this, arguments);\r
12092     },\r
12093 \r
12094     \r
12095     getRootNode : function(){\r
12096         return this.root;\r
12097     },\r
12098 \r
12099     \r
12100     setRootNode : function(node){\r
12101         this.root = node;\r
12102         node.ownerTree = this;\r
12103         node.isRoot = true;\r
12104         this.registerNode(node);\r
12105         return node;\r
12106     },\r
12107 \r
12108     \r
12109     getNodeById : function(id){\r
12110         return this.nodeHash[id];\r
12111     },\r
12112 \r
12113     // private\r
12114     registerNode : function(node){\r
12115         this.nodeHash[node.id] = node;\r
12116     },\r
12117 \r
12118     // private\r
12119     unregisterNode : function(node){\r
12120         delete this.nodeHash[node.id];\r
12121     },\r
12122 \r
12123     toString : function(){\r
12124         return "[Tree"+(this.id?" "+this.id:"")+"]";\r
12125     }\r
12126 });\r
12127 \r
12128 \r
12129 Ext.data.Node = function(attributes){\r
12130     \r
12131     this.attributes = attributes || {};\r
12132     this.leaf = this.attributes.leaf;\r
12133     \r
12134     this.id = this.attributes.id;\r
12135     if(!this.id){\r
12136         this.id = Ext.id(null, "ynode-");\r
12137         this.attributes.id = this.id;\r
12138     }\r
12139     \r
12140     this.childNodes = [];\r
12141     if(!this.childNodes.indexOf){ // indexOf is a must\r
12142         this.childNodes.indexOf = function(o){\r
12143             for(var i = 0, len = this.length; i < len; i++){\r
12144                 if(this[i] == o) return i;\r
12145             }\r
12146             return -1;\r
12147         };\r
12148     }\r
12149     \r
12150     this.parentNode = null;\r
12151     \r
12152     this.firstChild = null;\r
12153     \r
12154     this.lastChild = null;\r
12155     \r
12156     this.previousSibling = null;\r
12157     \r
12158     this.nextSibling = null;\r
12159 \r
12160     this.addEvents({\r
12161        \r
12162        "append" : true,\r
12163        \r
12164        "remove" : true,\r
12165        \r
12166        "move" : true,\r
12167        \r
12168        "insert" : true,\r
12169        \r
12170        "beforeappend" : true,\r
12171        \r
12172        "beforeremove" : true,\r
12173        \r
12174        "beforemove" : true,\r
12175        \r
12176        "beforeinsert" : true\r
12177    });\r
12178     this.listeners = this.attributes.listeners;\r
12179     Ext.data.Node.superclass.constructor.call(this);\r
12180 };\r
12181 \r
12182 Ext.extend(Ext.data.Node, Ext.util.Observable, {\r
12183     // private\r
12184     fireEvent : function(evtName){\r
12185         // first do standard event for this node\r
12186         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){\r
12187             return false;\r
12188         }\r
12189         // then bubble it up to the tree if the event wasn't cancelled\r
12190         var ot = this.getOwnerTree();\r
12191         if(ot){\r
12192             if(ot.proxyNodeEvent.apply(ot, arguments) === false){\r
12193                 return false;\r
12194             }\r
12195         }\r
12196         return true;\r
12197     },\r
12198 \r
12199     \r
12200     isLeaf : function(){\r
12201         return this.leaf === true;\r
12202     },\r
12203 \r
12204     // private\r
12205     setFirstChild : function(node){\r
12206         this.firstChild = node;\r
12207     },\r
12208 \r
12209     //private\r
12210     setLastChild : function(node){\r
12211         this.lastChild = node;\r
12212     },\r
12213 \r
12214 \r
12215     \r
12216     isLast : function(){\r
12217        return (!this.parentNode ? true : this.parentNode.lastChild == this);\r
12218     },\r
12219 \r
12220     \r
12221     isFirst : function(){\r
12222        return (!this.parentNode ? true : this.parentNode.firstChild == this);\r
12223     },\r
12224 \r
12225     \r
12226     hasChildNodes : function(){\r
12227         return !this.isLeaf() && this.childNodes.length > 0;\r
12228     },\r
12229     \r
12230     \r
12231     isExpandable : function(){\r
12232         return this.attributes.expandable || this.hasChildNodes();\r
12233     },\r
12234 \r
12235     \r
12236     appendChild : function(node){\r
12237         var multi = false;\r
12238         if(Ext.isArray(node)){\r
12239             multi = node;\r
12240         }else if(arguments.length > 1){\r
12241             multi = arguments;\r
12242         }\r
12243         // if passed an array or multiple args do them one by one\r
12244         if(multi){\r
12245             for(var i = 0, len = multi.length; i < len; i++) {\r
12246                 this.appendChild(multi[i]);\r
12247             }\r
12248         }else{\r
12249             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){\r
12250                 return false;\r
12251             }\r
12252             var index = this.childNodes.length;\r
12253             var oldParent = node.parentNode;\r
12254             // it's a move, make sure we move it cleanly\r
12255             if(oldParent){\r
12256                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){\r
12257                     return false;\r
12258                 }\r
12259                 oldParent.removeChild(node);\r
12260             }\r
12261             index = this.childNodes.length;\r
12262             if(index == 0){\r
12263                 this.setFirstChild(node);\r
12264             }\r
12265             this.childNodes.push(node);\r
12266             node.parentNode = this;\r
12267             var ps = this.childNodes[index-1];\r
12268             if(ps){\r
12269                 node.previousSibling = ps;\r
12270                 ps.nextSibling = node;\r
12271             }else{\r
12272                 node.previousSibling = null;\r
12273             }\r
12274             node.nextSibling = null;\r
12275             this.setLastChild(node);\r
12276             node.setOwnerTree(this.getOwnerTree());\r
12277             this.fireEvent("append", this.ownerTree, this, node, index);\r
12278             if(oldParent){\r
12279                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);\r
12280             }\r
12281             return node;\r
12282         }\r
12283     },\r
12284 \r
12285     \r
12286     removeChild : function(node){\r
12287         var index = this.childNodes.indexOf(node);\r
12288         if(index == -1){\r
12289             return false;\r
12290         }\r
12291         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){\r
12292             return false;\r
12293         }\r
12294 \r
12295         // remove it from childNodes collection\r
12296         this.childNodes.splice(index, 1);\r
12297 \r
12298         // update siblings\r
12299         if(node.previousSibling){\r
12300             node.previousSibling.nextSibling = node.nextSibling;\r
12301         }\r
12302         if(node.nextSibling){\r
12303             node.nextSibling.previousSibling = node.previousSibling;\r
12304         }\r
12305 \r
12306         // update child refs\r
12307         if(this.firstChild == node){\r
12308             this.setFirstChild(node.nextSibling);\r
12309         }\r
12310         if(this.lastChild == node){\r
12311             this.setLastChild(node.previousSibling);\r
12312         }\r
12313 \r
12314         node.setOwnerTree(null);\r
12315         // clear any references from the node\r
12316         node.parentNode = null;\r
12317         node.previousSibling = null;\r
12318         node.nextSibling = null;\r
12319         this.fireEvent("remove", this.ownerTree, this, node);\r
12320         return node;\r
12321     },\r
12322 \r
12323     \r
12324     insertBefore : function(node, refNode){\r
12325         if(!refNode){ // like standard Dom, refNode can be null for append\r
12326             return this.appendChild(node);\r
12327         }\r
12328         // nothing to do\r
12329         if(node == refNode){\r
12330             return false;\r
12331         }\r
12332 \r
12333         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){\r
12334             return false;\r
12335         }\r
12336         var index = this.childNodes.indexOf(refNode);\r
12337         var oldParent = node.parentNode;\r
12338         var refIndex = index;\r
12339 \r
12340         // when moving internally, indexes will change after remove\r
12341         if(oldParent == this && this.childNodes.indexOf(node) < index){\r
12342             refIndex--;\r
12343         }\r
12344 \r
12345         // it's a move, make sure we move it cleanly\r
12346         if(oldParent){\r
12347             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){\r
12348                 return false;\r
12349             }\r
12350             oldParent.removeChild(node);\r
12351         }\r
12352         if(refIndex == 0){\r
12353             this.setFirstChild(node);\r
12354         }\r
12355         this.childNodes.splice(refIndex, 0, node);\r
12356         node.parentNode = this;\r
12357         var ps = this.childNodes[refIndex-1];\r
12358         if(ps){\r
12359             node.previousSibling = ps;\r
12360             ps.nextSibling = node;\r
12361         }else{\r
12362             node.previousSibling = null;\r
12363         }\r
12364         node.nextSibling = refNode;\r
12365         refNode.previousSibling = node;\r
12366         node.setOwnerTree(this.getOwnerTree());\r
12367         this.fireEvent("insert", this.ownerTree, this, node, refNode);\r
12368         if(oldParent){\r
12369             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);\r
12370         }\r
12371         return node;\r
12372     },\r
12373 \r
12374     \r
12375     remove : function(){\r
12376         this.parentNode.removeChild(this);\r
12377         return this;\r
12378     },\r
12379 \r
12380     \r
12381     item : function(index){\r
12382         return this.childNodes[index];\r
12383     },\r
12384 \r
12385     \r
12386     replaceChild : function(newChild, oldChild){\r
12387         var s = oldChild ? oldChild.nextSibling : null;\r
12388         this.removeChild(oldChild);\r
12389         this.insertBefore(newChild, s);\r
12390         return oldChild;\r
12391     },\r
12392 \r
12393     \r
12394     indexOf : function(child){\r
12395         return this.childNodes.indexOf(child);\r
12396     },\r
12397 \r
12398     \r
12399     getOwnerTree : function(){\r
12400         // if it doesn't have one, look for one\r
12401         if(!this.ownerTree){\r
12402             var p = this;\r
12403             while(p){\r
12404                 if(p.ownerTree){\r
12405                     this.ownerTree = p.ownerTree;\r
12406                     break;\r
12407                 }\r
12408                 p = p.parentNode;\r
12409             }\r
12410         }\r
12411         return this.ownerTree;\r
12412     },\r
12413 \r
12414     \r
12415     getDepth : function(){\r
12416         var depth = 0;\r
12417         var p = this;\r
12418         while(p.parentNode){\r
12419             ++depth;\r
12420             p = p.parentNode;\r
12421         }\r
12422         return depth;\r
12423     },\r
12424 \r
12425     // private\r
12426     setOwnerTree : function(tree){\r
12427         // if it's move, we need to update everyone\r
12428         if(tree != this.ownerTree){\r
12429             if(this.ownerTree){\r
12430                 this.ownerTree.unregisterNode(this);\r
12431             }\r
12432             this.ownerTree = tree;\r
12433             var cs = this.childNodes;\r
12434             for(var i = 0, len = cs.length; i < len; i++) {\r
12435                 cs[i].setOwnerTree(tree);\r
12436             }\r
12437             if(tree){\r
12438                 tree.registerNode(this);\r
12439             }\r
12440         }\r
12441     },\r
12442 \r
12443     \r
12444     getPath : function(attr){\r
12445         attr = attr || "id";\r
12446         var p = this.parentNode;\r
12447         var b = [this.attributes[attr]];\r
12448         while(p){\r
12449             b.unshift(p.attributes[attr]);\r
12450             p = p.parentNode;\r
12451         }\r
12452         var sep = this.getOwnerTree().pathSeparator;\r
12453         return sep + b.join(sep);\r
12454     },\r
12455 \r
12456     \r
12457     bubble : function(fn, scope, args){\r
12458         var p = this;\r
12459         while(p){\r
12460             if(fn.apply(scope || p, args || [p]) === false){\r
12461                 break;\r
12462             }\r
12463             p = p.parentNode;\r
12464         }\r
12465     },\r
12466 \r
12467     \r
12468     cascade : function(fn, scope, args){\r
12469         if(fn.apply(scope || this, args || [this]) !== false){\r
12470             var cs = this.childNodes;\r
12471             for(var i = 0, len = cs.length; i < len; i++) {\r
12472                 cs[i].cascade(fn, scope, args);\r
12473             }\r
12474         }\r
12475     },\r
12476 \r
12477     \r
12478     eachChild : function(fn, scope, args){\r
12479         var cs = this.childNodes;\r
12480         for(var i = 0, len = cs.length; i < len; i++) {\r
12481                 if(fn.apply(scope || this, args || [cs[i]]) === false){\r
12482                     break;\r
12483                 }\r
12484         }\r
12485     },\r
12486 \r
12487     \r
12488     findChild : function(attribute, value){\r
12489         var cs = this.childNodes;\r
12490         for(var i = 0, len = cs.length; i < len; i++) {\r
12491                 if(cs[i].attributes[attribute] == value){\r
12492                     return cs[i];\r
12493                 }\r
12494         }\r
12495         return null;\r
12496     },\r
12497 \r
12498     \r
12499     findChildBy : function(fn, scope){\r
12500         var cs = this.childNodes;\r
12501         for(var i = 0, len = cs.length; i < len; i++) {\r
12502                 if(fn.call(scope||cs[i], cs[i]) === true){\r
12503                     return cs[i];\r
12504                 }\r
12505         }\r
12506         return null;\r
12507     },\r
12508 \r
12509     \r
12510     sort : function(fn, scope){\r
12511         var cs = this.childNodes;\r
12512         var len = cs.length;\r
12513         if(len > 0){\r
12514             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;\r
12515             cs.sort(sortFn);\r
12516             for(var i = 0; i < len; i++){\r
12517                 var n = cs[i];\r
12518                 n.previousSibling = cs[i-1];\r
12519                 n.nextSibling = cs[i+1];\r
12520                 if(i == 0){\r
12521                     this.setFirstChild(n);\r
12522                 }\r
12523                 if(i == len-1){\r
12524                     this.setLastChild(n);\r
12525                 }\r
12526             }\r
12527         }\r
12528     },\r
12529 \r
12530     \r
12531     contains : function(node){\r
12532         return node.isAncestor(this);\r
12533     },\r
12534 \r
12535     \r
12536     isAncestor : function(node){\r
12537         var p = this.parentNode;\r
12538         while(p){\r
12539             if(p == node){\r
12540                 return true;\r
12541             }\r
12542             p = p.parentNode;\r
12543         }\r
12544         return false;\r
12545     },\r
12546 \r
12547     toString : function(){\r
12548         return "[Node"+(this.id?" "+this.id:"")+"]";\r
12549     }\r
12550 });\r
12551 \r
12552 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {\r
12553     \r
12554     \r
12555     remoteGroup : false,\r
12556     \r
12557     groupOnSort:false,\r
12558 \r
12559     \r
12560     clearGrouping : function(){\r
12561         this.groupField = false;\r
12562         if(this.remoteGroup){\r
12563             if(this.baseParams){\r
12564                 delete this.baseParams.groupBy;\r
12565             }\r
12566             this.reload();\r
12567         }else{\r
12568             this.applySort();\r
12569             this.fireEvent('datachanged', this);\r
12570         }\r
12571     },\r
12572 \r
12573     \r
12574     groupBy : function(field, forceRegroup){\r
12575         if(this.groupField == field && !forceRegroup){\r
12576             return; // already grouped by this field\r
12577         }\r
12578         this.groupField = field;\r
12579         if(this.remoteGroup){\r
12580             if(!this.baseParams){\r
12581                 this.baseParams = {};\r
12582             }\r
12583             this.baseParams['groupBy'] = field;\r
12584         }\r
12585         if(this.groupOnSort){\r
12586             this.sort(field);\r
12587             return;\r
12588         }\r
12589         if(this.remoteGroup){\r
12590             this.reload();\r
12591         }else{\r
12592             var si = this.sortInfo || {};\r
12593             if(si.field != field){\r
12594                 this.applySort();\r
12595             }else{\r
12596                 this.sortData(field);\r
12597             }\r
12598             this.fireEvent('datachanged', this);\r
12599         }\r
12600     },\r
12601 \r
12602     // private\r
12603     applySort : function(){\r
12604         Ext.data.GroupingStore.superclass.applySort.call(this);\r
12605         if(!this.groupOnSort && !this.remoteGroup){\r
12606             var gs = this.getGroupState();\r
12607             if(gs && gs != this.sortInfo.field){\r
12608                 this.sortData(this.groupField);\r
12609             }\r
12610         }\r
12611     },\r
12612 \r
12613     // private\r
12614     applyGrouping : function(alwaysFireChange){\r
12615         if(this.groupField !== false){\r
12616             this.groupBy(this.groupField, true);\r
12617             return true;\r
12618         }else{\r
12619             if(alwaysFireChange === true){\r
12620                 this.fireEvent('datachanged', this);\r
12621             }\r
12622             return false;\r
12623         }\r
12624     },\r
12625 \r
12626     // private\r
12627     getGroupState : function(){\r
12628         return this.groupOnSort && this.groupField !== false ?\r
12629                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;\r
12630     }\r
12631 });\r
12632 \r
12633 Ext.ComponentMgr = function(){\r
12634     var all = new Ext.util.MixedCollection();\r
12635     var types = {};\r
12636 \r
12637     return {\r
12638         \r
12639         register : function(c){\r
12640             all.add(c);\r
12641         },\r
12642 \r
12643         \r
12644         unregister : function(c){\r
12645             all.remove(c);\r
12646         },\r
12647 \r
12648         \r
12649         get : function(id){\r
12650             return all.get(id);\r
12651         },\r
12652 \r
12653         \r
12654         onAvailable : function(id, fn, scope){\r
12655             all.on("add", function(index, o){\r
12656                 if(o.id == id){\r
12657                     fn.call(scope || o, o);\r
12658                     all.un("add", fn, scope);\r
12659                 }\r
12660             });\r
12661         },\r
12662 \r
12663         \r
12664         all : all,\r
12665 \r
12666         \r
12667         registerType : function(xtype, cls){\r
12668             types[xtype] = cls;\r
12669             cls.xtype = xtype;\r
12670         },\r
12671 \r
12672         \r
12673         create : function(config, defaultType){\r
12674             return new types[config.xtype || defaultType](config);\r
12675         }\r
12676     };\r
12677 }();\r
12678 \r
12679 \r
12680 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down\r
12681 \r
12682 Ext.Component = function(config){\r
12683     config = config || {};\r
12684     if(config.initialConfig){\r
12685         if(config.isAction){           // actions\r
12686             this.baseAction = config;\r
12687         }\r
12688         config = config.initialConfig; // component cloning / action set up\r
12689     }else if(config.tagName || config.dom || typeof config == "string"){ // element object\r
12690         config = {applyTo: config, id: config.id || config};\r
12691     }\r
12692 \r
12693     \r
12694     this.initialConfig = config;\r
12695 \r
12696     Ext.apply(this, config);\r
12697     this.addEvents(\r
12698         \r
12699         'disable',\r
12700         \r
12701         'enable',\r
12702         \r
12703         'beforeshow',\r
12704         \r
12705         'show',\r
12706         \r
12707         'beforehide',\r
12708         \r
12709         'hide',\r
12710         \r
12711         'beforerender',\r
12712         \r
12713         'render',\r
12714         \r
12715         'beforedestroy',\r
12716         \r
12717         'destroy',\r
12718         \r
12719         'beforestaterestore',\r
12720         \r
12721         'staterestore',\r
12722         \r
12723         'beforestatesave',\r
12724         \r
12725         'statesave'\r
12726     );\r
12727     this.getId();\r
12728     Ext.ComponentMgr.register(this);\r
12729     Ext.Component.superclass.constructor.call(this);\r
12730 \r
12731     if(this.baseAction){\r
12732         this.baseAction.addComponent(this);\r
12733     }\r
12734 \r
12735     this.initComponent();\r
12736 \r
12737     if(this.plugins){\r
12738         if(Ext.isArray(this.plugins)){\r
12739             for(var i = 0, len = this.plugins.length; i < len; i++){\r
12740                 this.plugins[i] = this.initPlugin(this.plugins[i]);\r
12741             }\r
12742         }else{\r
12743             this.plugins = this.initPlugin(this.plugins);\r
12744         }\r
12745     }\r
12746 \r
12747     if(this.stateful !== false){\r
12748         this.initState(config);\r
12749     }\r
12750 \r
12751     if(this.applyTo){\r
12752         this.applyToMarkup(this.applyTo);\r
12753         delete this.applyTo;\r
12754     }else if(this.renderTo){\r
12755         this.render(this.renderTo);\r
12756         delete this.renderTo;\r
12757     }\r
12758 };\r
12759 \r
12760 // private\r
12761 Ext.Component.AUTO_ID = 1000;\r
12762 \r
12763 Ext.extend(Ext.Component, Ext.util.Observable, {\r
12764     // Configs below are used for all Components when rendered by FormLayout.\r
12765     \r
12766     \r
12767     \r
12768     \r
12769     \r
12770     \r
12771 \r
12772     \r
12773     \r
12774     \r
12775     \r
12776     \r
12777     \r
12778     \r
12779     \r
12780     \r
12781     \r
12782     \r
12783     \r
12784 \r
12785     \r
12786     \r
12787     \r
12788 \r
12789     \r
12790     disabledClass : "x-item-disabled",\r
12791         \r
12792     allowDomMove : true,\r
12793         \r
12794     autoShow : false,\r
12795     \r
12796     hideMode: 'display',\r
12797     \r
12798     hideParent: false,\r
12799 \r
12800     \r
12801     \r
12802     hidden : false,\r
12803     \r
12804     disabled : false,\r
12805     \r
12806     rendered : false,\r
12807 \r
12808     // private\r
12809     ctype : "Ext.Component",\r
12810 \r
12811     // private\r
12812     actionMode : "el",\r
12813 \r
12814     // private\r
12815     getActionEl : function(){\r
12816         return this[this.actionMode];\r
12817     },\r
12818 \r
12819     initPlugin : function(p){\r
12820         p.init(this);\r
12821         return p;\r
12822     },\r
12823 \r
12824     \r
12825     initComponent : Ext.emptyFn,\r
12826 \r
12827     \r
12828     render : function(container, position){\r
12829         if(!this.rendered && this.fireEvent("beforerender", this) !== false){\r
12830             if(!container && this.el){\r
12831                 this.el = Ext.get(this.el);\r
12832                 container = this.el.dom.parentNode;\r
12833                 this.allowDomMove = false;\r
12834             }\r
12835             this.container = Ext.get(container);\r
12836             if(this.ctCls){\r
12837                 this.container.addClass(this.ctCls);\r
12838             }\r
12839             this.rendered = true;\r
12840             if(position !== undefined){\r
12841                 if(typeof position == 'number'){\r
12842                     position = this.container.dom.childNodes[position];\r
12843                 }else{\r
12844                     position = Ext.getDom(position);\r
12845                 }\r
12846             }\r
12847             this.onRender(this.container, position || null);\r
12848             if(this.autoShow){\r
12849                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);\r
12850             }\r
12851             if(this.cls){\r
12852                 this.el.addClass(this.cls);\r
12853                 delete this.cls;\r
12854             }\r
12855             if(this.style){\r
12856                 this.el.applyStyles(this.style);\r
12857                 delete this.style;\r
12858             }\r
12859             if(this.overCls){\r
12860                 this.el.addClassOnOver(this.overCls);\r
12861             }\r
12862             this.fireEvent("render", this);\r
12863             this.afterRender(this.container);\r
12864             if(this.hidden){\r
12865                 this.hide();\r
12866             }\r
12867             if(this.disabled){\r
12868                 this.disable();\r
12869             }\r
12870 \r
12871             if(this.stateful !== false){\r
12872                 this.initStateEvents();\r
12873             }\r
12874         }\r
12875         return this;\r
12876     },\r
12877 \r
12878     // private\r
12879     initState : function(config){\r
12880         if(Ext.state.Manager){\r
12881             var id = this.getStateId();\r
12882             if(id){\r
12883                 var state = Ext.state.Manager.get(id);\r
12884                 if(state){\r
12885                     if(this.fireEvent('beforestaterestore', this, state) !== false){\r
12886                         this.applyState(state);\r
12887                         this.fireEvent('staterestore', this, state);\r
12888                     }\r
12889                 }\r
12890             }\r
12891         }\r
12892     },\r
12893 \r
12894     // private\r
12895     getStateId : function(){\r
12896         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);\r
12897     },\r
12898 \r
12899     // private\r
12900     initStateEvents : function(){\r
12901         if(this.stateEvents){\r
12902             for(var i = 0, e; e = this.stateEvents[i]; i++){\r
12903                 this.on(e, this.saveState, this, {delay:100});\r
12904             }\r
12905         }\r
12906     },\r
12907 \r
12908     // private\r
12909     applyState : function(state, config){\r
12910         if(state){\r
12911             Ext.apply(this, state);\r
12912         }\r
12913     },\r
12914 \r
12915     // private\r
12916     getState : function(){\r
12917         return null;\r
12918     },\r
12919 \r
12920     // private\r
12921     saveState : function(){\r
12922         if(Ext.state.Manager){\r
12923             var id = this.getStateId();\r
12924             if(id){\r
12925                 var state = this.getState();\r
12926                 if(this.fireEvent('beforestatesave', this, state) !== false){\r
12927                     Ext.state.Manager.set(id, state);\r
12928                     this.fireEvent('statesave', this, state);\r
12929                 }\r
12930             }\r
12931         }\r
12932     },\r
12933 \r
12934     \r
12935     applyToMarkup : function(el){\r
12936         this.allowDomMove = false;\r
12937         this.el = Ext.get(el);\r
12938         this.render(this.el.dom.parentNode);\r
12939     },\r
12940 \r
12941     \r
12942     addClass : function(cls){\r
12943         if(this.el){\r
12944             this.el.addClass(cls);\r
12945         }else{\r
12946             this.cls = this.cls ? this.cls + ' ' + cls : cls;\r
12947         }\r
12948     },\r
12949 \r
12950     \r
12951     removeClass : function(cls){\r
12952         if(this.el){\r
12953             this.el.removeClass(cls);\r
12954         }else if(this.cls){\r
12955             this.cls = this.cls.split(' ').remove(cls).join(' ');\r
12956         }\r
12957     },\r
12958 \r
12959     // private\r
12960     // default function is not really useful\r
12961     onRender : function(ct, position){\r
12962         if(this.autoEl){\r
12963             if(typeof this.autoEl == 'string'){\r
12964                 this.el = document.createElement(this.autoEl);\r
12965             }else{\r
12966                 var div = document.createElement('div');\r
12967                 Ext.DomHelper.overwrite(div, this.autoEl);\r
12968                 this.el = div.firstChild;\r
12969             }\r
12970             if (!this.el.id) {\r
12971                 this.el.id = this.getId();\r
12972             }\r
12973         }\r
12974         if(this.el){\r
12975             this.el = Ext.get(this.el);\r
12976             if(this.allowDomMove !== false){\r
12977                 ct.dom.insertBefore(this.el.dom, position);\r
12978             }\r
12979         }\r
12980     },\r
12981 \r
12982     // private\r
12983     getAutoCreate : function(){\r
12984         var cfg = typeof this.autoCreate == "object" ?\r
12985                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);\r
12986         if(this.id && !cfg.id){\r
12987             cfg.id = this.id;\r
12988         }\r
12989         return cfg;\r
12990     },\r
12991 \r
12992     // private\r
12993     afterRender : Ext.emptyFn,\r
12994 \r
12995     \r
12996     destroy : function(){\r
12997         if(this.fireEvent("beforedestroy", this) !== false){\r
12998             this.beforeDestroy();\r
12999             if(this.rendered){\r
13000                 this.el.removeAllListeners();\r
13001                 this.el.remove();\r
13002                 if(this.actionMode == "container"){\r
13003                     this.container.remove();\r
13004                 }\r
13005             }\r
13006             this.onDestroy();\r
13007             Ext.ComponentMgr.unregister(this);\r
13008             this.fireEvent("destroy", this);\r
13009             this.purgeListeners();\r
13010         }\r
13011     },\r
13012 \r
13013         // private\r
13014     beforeDestroy : Ext.emptyFn,\r
13015 \r
13016         // private\r
13017     onDestroy  : Ext.emptyFn,\r
13018 \r
13019     \r
13020     getEl : function(){\r
13021         return this.el;\r
13022     },\r
13023 \r
13024     \r
13025     getId : function(){\r
13026         return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));\r
13027     },\r
13028 \r
13029     \r
13030     getItemId : function(){\r
13031         return this.itemId || this.getId();\r
13032     },\r
13033 \r
13034     \r
13035     focus : function(selectText, delay){\r
13036         if(delay){\r
13037             this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);\r
13038             return;\r
13039         }\r
13040         if(this.rendered){\r
13041             this.el.focus();\r
13042             if(selectText === true){\r
13043                 this.el.dom.select();\r
13044             }\r
13045         }\r
13046         return this;\r
13047     },\r
13048 \r
13049     // private\r
13050     blur : function(){\r
13051         if(this.rendered){\r
13052             this.el.blur();\r
13053         }\r
13054         return this;\r
13055     },\r
13056 \r
13057     \r
13058     disable : function(){\r
13059         if(this.rendered){\r
13060             this.onDisable();\r
13061         }\r
13062         this.disabled = true;\r
13063         this.fireEvent("disable", this);\r
13064         return this;\r
13065     },\r
13066 \r
13067         // private\r
13068     onDisable : function(){\r
13069         this.getActionEl().addClass(this.disabledClass);\r
13070         this.el.dom.disabled = true;\r
13071     },\r
13072 \r
13073     \r
13074     enable : function(){\r
13075         if(this.rendered){\r
13076             this.onEnable();\r
13077         }\r
13078         this.disabled = false;\r
13079         this.fireEvent("enable", this);\r
13080         return this;\r
13081     },\r
13082 \r
13083         // private\r
13084     onEnable : function(){\r
13085         this.getActionEl().removeClass(this.disabledClass);\r
13086         this.el.dom.disabled = false;\r
13087     },\r
13088 \r
13089     \r
13090     setDisabled : function(disabled){\r
13091         this[disabled ? "disable" : "enable"]();\r
13092     },\r
13093 \r
13094     \r
13095     show: function(){\r
13096         if(this.fireEvent("beforeshow", this) !== false){\r
13097             this.hidden = false;\r
13098             if(this.autoRender){\r
13099                 this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);\r
13100             }\r
13101             if(this.rendered){\r
13102                 this.onShow();\r
13103             }\r
13104             this.fireEvent("show", this);\r
13105         }\r
13106         return this;\r
13107     },\r
13108 \r
13109     // private\r
13110     onShow : function(){\r
13111         if(this.hideParent){\r
13112             this.container.removeClass('x-hide-' + this.hideMode);\r
13113         }else{\r
13114             this.getActionEl().removeClass('x-hide-' + this.hideMode);\r
13115         }\r
13116 \r
13117     },\r
13118 \r
13119     \r
13120     hide: function(){\r
13121         if(this.fireEvent("beforehide", this) !== false){\r
13122             this.hidden = true;\r
13123             if(this.rendered){\r
13124                 this.onHide();\r
13125             }\r
13126             this.fireEvent("hide", this);\r
13127         }\r
13128         return this;\r
13129     },\r
13130 \r
13131     // private\r
13132     onHide : function(){\r
13133         if(this.hideParent){\r
13134             this.container.addClass('x-hide-' + this.hideMode);\r
13135         }else{\r
13136             this.getActionEl().addClass('x-hide-' + this.hideMode);\r
13137         }\r
13138     },\r
13139 \r
13140     \r
13141     setVisible: function(visible){\r
13142         if(visible) {\r
13143             this.show();\r
13144         }else{\r
13145             this.hide();\r
13146         }\r
13147         return this;\r
13148     },\r
13149 \r
13150     \r
13151     isVisible : function(){\r
13152         return this.rendered && this.getActionEl().isVisible();\r
13153     },\r
13154 \r
13155     \r
13156     cloneConfig : function(overrides){\r
13157         overrides = overrides || {};\r
13158         var id = overrides.id || Ext.id();\r
13159         var cfg = Ext.applyIf(overrides, this.initialConfig);\r
13160         cfg.id = id; // prevent dup id\r
13161         return new this.constructor(cfg);\r
13162     },\r
13163 \r
13164     \r
13165     getXType : function(){\r
13166         return this.constructor.xtype;\r
13167     },\r
13168 \r
13169     \r
13170     isXType : function(xtype, shallow){\r
13171         //assume a string by default\r
13172         if (typeof xtype == 'function'){\r
13173             xtype = xtype.xtype; //handle being passed the class, eg. Ext.Component\r
13174         }else if (typeof xtype == 'object'){\r
13175             xtype = xtype.constructor.xtype; //handle being passed an instance\r
13176         }\r
13177             \r
13178         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;\r
13179     },\r
13180 \r
13181     \r
13182     getXTypes : function(){\r
13183         var tc = this.constructor;\r
13184         if(!tc.xtypes){\r
13185             var c = [], sc = this;\r
13186             while(sc && sc.constructor.xtype){\r
13187                 c.unshift(sc.constructor.xtype);\r
13188                 sc = sc.constructor.superclass;\r
13189             }\r
13190             tc.xtypeChain = c;\r
13191             tc.xtypes = c.join('/');\r
13192         }\r
13193         return tc.xtypes;\r
13194     },\r
13195 \r
13196     \r
13197     findParentBy: function(fn) {\r
13198         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);\r
13199         return p || null;\r
13200     },\r
13201 \r
13202     \r
13203     findParentByType: function(xtype) {\r
13204         return typeof xtype == 'function' ?\r
13205             this.findParentBy(function(p){\r
13206                 return p.constructor === xtype;\r
13207             }) :\r
13208             this.findParentBy(function(p){\r
13209                 return p.constructor.xtype === xtype;\r
13210             });\r
13211     },\r
13212 \r
13213     // internal function for auto removal of assigned event handlers on destruction\r
13214     mon : function(item, ename, fn, scope, opt){\r
13215         if(!this.mons){\r
13216             this.mons = [];\r
13217             this.on('beforedestroy', function(){\r
13218                 for(var i= 0, len = this.mons.length; i < len; i++){\r
13219                     var m = this.mons[i];\r
13220                     m.item.un(m.ename, m.fn, m.scope);\r
13221                 }\r
13222             }, this);\r
13223         }\r
13224         this.mons.push({\r
13225             item: item, ename: ename, fn: fn, scope: scope\r
13226         });\r
13227         item.on(ename, fn, scope, opt);\r
13228     }\r
13229 });\r
13230 \r
13231 Ext.reg('component', Ext.Component);\r
13232 \r
13233 \r
13234 Ext.Action = function(config){\r
13235     this.initialConfig = config;\r
13236     this.items = [];\r
13237 }\r
13238 \r
13239 Ext.Action.prototype = {\r
13240     \r
13241     \r
13242     \r
13243     \r
13244     \r
13245     \r
13246 \r
13247     // private\r
13248     isAction : true,\r
13249 \r
13250     \r
13251     setText : function(text){\r
13252         this.initialConfig.text = text;\r
13253         this.callEach('setText', [text]);\r
13254     },\r
13255 \r
13256     \r
13257     getText : function(){\r
13258         return this.initialConfig.text;\r
13259     },\r
13260 \r
13261     \r
13262     setIconClass : function(cls){\r
13263         this.initialConfig.iconCls = cls;\r
13264         this.callEach('setIconClass', [cls]);\r
13265     },\r
13266 \r
13267     \r
13268     getIconClass : function(){\r
13269         return this.initialConfig.iconCls;\r
13270     },\r
13271 \r
13272     \r
13273     setDisabled : function(v){\r
13274         this.initialConfig.disabled = v;\r
13275         this.callEach('setDisabled', [v]);\r
13276     },\r
13277 \r
13278     \r
13279     enable : function(){\r
13280         this.setDisabled(false);\r
13281     },\r
13282 \r
13283     \r
13284     disable : function(){\r
13285         this.setDisabled(true);\r
13286     },\r
13287 \r
13288     \r
13289     isDisabled : function(){\r
13290         return this.initialConfig.disabled;\r
13291     },\r
13292 \r
13293     \r
13294     setHidden : function(v){\r
13295         this.initialConfig.hidden = v;\r
13296         this.callEach('setVisible', [!v]);\r
13297     },\r
13298 \r
13299     \r
13300     show : function(){\r
13301         this.setHidden(false);\r
13302     },\r
13303 \r
13304     \r
13305     hide : function(){\r
13306         this.setHidden(true);\r
13307     },\r
13308 \r
13309     \r
13310     isHidden : function(){\r
13311         return this.initialConfig.hidden;\r
13312     },\r
13313 \r
13314     \r
13315     setHandler : function(fn, scope){\r
13316         this.initialConfig.handler = fn;\r
13317         this.initialConfig.scope = scope;\r
13318         this.callEach('setHandler', [fn, scope]);\r
13319     },\r
13320 \r
13321     \r
13322     each : function(fn, scope){\r
13323         Ext.each(this.items, fn, scope);\r
13324     },\r
13325 \r
13326     // private\r
13327     callEach : function(fnName, args){\r
13328         var cs = this.items;\r
13329         for(var i = 0, len = cs.length; i < len; i++){\r
13330             cs[i][fnName].apply(cs[i], args);\r
13331         }\r
13332     },\r
13333 \r
13334     // private\r
13335     addComponent : function(comp){\r
13336         this.items.push(comp);\r
13337         comp.on('destroy', this.removeComponent, this);\r
13338     },\r
13339 \r
13340     // private\r
13341     removeComponent : function(comp){\r
13342         this.items.remove(comp);\r
13343     },\r
13344 \r
13345     \r
13346     execute : function(){\r
13347         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
13348     }\r
13349 };\r
13350 \r
13351 (function(){\r
13352 Ext.Layer = function(config, existingEl){\r
13353     config = config || {};\r
13354     var dh = Ext.DomHelper;\r
13355     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;\r
13356     if(existingEl){\r
13357         this.dom = Ext.getDom(existingEl);\r
13358     }\r
13359     if(!this.dom){\r
13360         var o = config.dh || {tag: "div", cls: "x-layer"};\r
13361         this.dom = dh.append(pel, o);\r
13362     }\r
13363     if(config.cls){\r
13364         this.addClass(config.cls);\r
13365     }\r
13366     this.constrain = config.constrain !== false;\r
13367     this.visibilityMode = Ext.Element.VISIBILITY;\r
13368     if(config.id){\r
13369         this.id = this.dom.id = config.id;\r
13370     }else{\r
13371         this.id = Ext.id(this.dom);\r
13372     }\r
13373     this.zindex = config.zindex || this.getZIndex();\r
13374     this.position("absolute", this.zindex);\r
13375     if(config.shadow){\r
13376         this.shadowOffset = config.shadowOffset || 4;\r
13377         this.shadow = new Ext.Shadow({\r
13378             offset : this.shadowOffset,\r
13379             mode : config.shadow\r
13380         });\r
13381     }else{\r
13382         this.shadowOffset = 0;\r
13383     }\r
13384     this.useShim = config.shim !== false && Ext.useShims;\r
13385     this.useDisplay = config.useDisplay;\r
13386     this.hide();\r
13387 };\r
13388 \r
13389 var supr = Ext.Element.prototype;\r
13390 \r
13391 // shims are shared among layer to keep from having 100 iframes\r
13392 var shims = [];\r
13393 \r
13394 Ext.extend(Ext.Layer, Ext.Element, {\r
13395 \r
13396     getZIndex : function(){\r
13397         return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;\r
13398     },\r
13399 \r
13400     getShim : function(){\r
13401         if(!this.useShim){\r
13402             return null;\r
13403         }\r
13404         if(this.shim){\r
13405             return this.shim;\r
13406         }\r
13407         var shim = shims.shift();\r
13408         if(!shim){\r
13409             shim = this.createShim();\r
13410             shim.enableDisplayMode('block');\r
13411             shim.dom.style.display = 'none';\r
13412             shim.dom.style.visibility = 'visible';\r
13413         }\r
13414         var pn = this.dom.parentNode;\r
13415         if(shim.dom.parentNode != pn){\r
13416             pn.insertBefore(shim.dom, this.dom);\r
13417         }\r
13418         shim.setStyle('z-index', this.getZIndex()-2);\r
13419         this.shim = shim;\r
13420         return shim;\r
13421     },\r
13422 \r
13423     hideShim : function(){\r
13424         if(this.shim){\r
13425             this.shim.setDisplayed(false);\r
13426             shims.push(this.shim);\r
13427             delete this.shim;\r
13428         }\r
13429     },\r
13430 \r
13431     disableShadow : function(){\r
13432         if(this.shadow){\r
13433             this.shadowDisabled = true;\r
13434             this.shadow.hide();\r
13435             this.lastShadowOffset = this.shadowOffset;\r
13436             this.shadowOffset = 0;\r
13437         }\r
13438     },\r
13439 \r
13440     enableShadow : function(show){\r
13441         if(this.shadow){\r
13442             this.shadowDisabled = false;\r
13443             this.shadowOffset = this.lastShadowOffset;\r
13444             delete this.lastShadowOffset;\r
13445             if(show){\r
13446                 this.sync(true);\r
13447             }\r
13448         }\r
13449     },\r
13450 \r
13451     // private\r
13452     // this code can execute repeatedly in milliseconds (i.e. during a drag) so\r
13453     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)\r
13454     sync : function(doShow){\r
13455         var sw = this.shadow;\r
13456         if(!this.updating && this.isVisible() && (sw || this.useShim)){\r
13457             var sh = this.getShim();\r
13458 \r
13459             var w = this.getWidth(),\r
13460                 h = this.getHeight();\r
13461 \r
13462             var l = this.getLeft(true),\r
13463                 t = this.getTop(true);\r
13464 \r
13465             if(sw && !this.shadowDisabled){\r
13466                 if(doShow && !sw.isVisible()){\r
13467                     sw.show(this);\r
13468                 }else{\r
13469                     sw.realign(l, t, w, h);\r
13470                 }\r
13471                 if(sh){\r
13472                     if(doShow){\r
13473                        sh.show();\r
13474                     }\r
13475                     // fit the shim behind the shadow, so it is shimmed too\r
13476                     var a = sw.adjusts, s = sh.dom.style;\r
13477                     s.left = (Math.min(l, l+a.l))+"px";\r
13478                     s.top = (Math.min(t, t+a.t))+"px";\r
13479                     s.width = (w+a.w)+"px";\r
13480                     s.height = (h+a.h)+"px";\r
13481                 }\r
13482             }else if(sh){\r
13483                 if(doShow){\r
13484                    sh.show();\r
13485                 }\r
13486                 sh.setSize(w, h);\r
13487                 sh.setLeftTop(l, t);\r
13488             }\r
13489 \r
13490         }\r
13491     },\r
13492 \r
13493     // private\r
13494     destroy : function(){\r
13495         this.hideShim();\r
13496         if(this.shadow){\r
13497             this.shadow.hide();\r
13498         }\r
13499         this.removeAllListeners();\r
13500         Ext.removeNode(this.dom);\r
13501         Ext.Element.uncache(this.id);\r
13502     },\r
13503 \r
13504     remove : function(){\r
13505         this.destroy();\r
13506     },\r
13507 \r
13508     // private\r
13509     beginUpdate : function(){\r
13510         this.updating = true;\r
13511     },\r
13512 \r
13513     // private\r
13514     endUpdate : function(){\r
13515         this.updating = false;\r
13516         this.sync(true);\r
13517     },\r
13518 \r
13519     // private\r
13520     hideUnders : function(negOffset){\r
13521         if(this.shadow){\r
13522             this.shadow.hide();\r
13523         }\r
13524         this.hideShim();\r
13525     },\r
13526 \r
13527     // private\r
13528     constrainXY : function(){\r
13529         if(this.constrain){\r
13530             var vw = Ext.lib.Dom.getViewWidth(),\r
13531                 vh = Ext.lib.Dom.getViewHeight();\r
13532             var s = Ext.getDoc().getScroll();\r
13533 \r
13534             var xy = this.getXY();\r
13535             var x = xy[0], y = xy[1];\r
13536             var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;\r
13537             // only move it if it needs it\r
13538             var moved = false;\r
13539             // first validate right/bottom\r
13540             if((x + w) > vw+s.left){\r
13541                 x = vw - w - this.shadowOffset;\r
13542                 moved = true;\r
13543             }\r
13544             if((y + h) > vh+s.top){\r
13545                 y = vh - h - this.shadowOffset;\r
13546                 moved = true;\r
13547             }\r
13548             // then make sure top/left isn't negative\r
13549             if(x < s.left){\r
13550                 x = s.left;\r
13551                 moved = true;\r
13552             }\r
13553             if(y < s.top){\r
13554                 y = s.top;\r
13555                 moved = true;\r
13556             }\r
13557             if(moved){\r
13558                 if(this.avoidY){\r
13559                     var ay = this.avoidY;\r
13560                     if(y <= ay && (y+h) >= ay){\r
13561                         y = ay-h-5;\r
13562                     }\r
13563                 }\r
13564                 xy = [x, y];\r
13565                 this.storeXY(xy);\r
13566                 supr.setXY.call(this, xy);\r
13567                 this.sync();\r
13568             }\r
13569         }\r
13570     },\r
13571 \r
13572     isVisible : function(){\r
13573         return this.visible;\r
13574     },\r
13575 \r
13576     // private\r
13577     showAction : function(){\r
13578         this.visible = true; // track visibility to prevent getStyle calls\r
13579         if(this.useDisplay === true){\r
13580             this.setDisplayed("");\r
13581         }else if(this.lastXY){\r
13582             supr.setXY.call(this, this.lastXY);\r
13583         }else if(this.lastLT){\r
13584             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);\r
13585         }\r
13586     },\r
13587 \r
13588     // private\r
13589     hideAction : function(){\r
13590         this.visible = false;\r
13591         if(this.useDisplay === true){\r
13592             this.setDisplayed(false);\r
13593         }else{\r
13594             this.setLeftTop(-10000,-10000);\r
13595         }\r
13596     },\r
13597 \r
13598     // overridden Element method\r
13599     setVisible : function(v, a, d, c, e){\r
13600         if(v){\r
13601             this.showAction();\r
13602         }\r
13603         if(a && v){\r
13604             var cb = function(){\r
13605                 this.sync(true);\r
13606                 if(c){\r
13607                     c();\r
13608                 }\r
13609             }.createDelegate(this);\r
13610             supr.setVisible.call(this, true, true, d, cb, e);\r
13611         }else{\r
13612             if(!v){\r
13613                 this.hideUnders(true);\r
13614             }\r
13615             var cb = c;\r
13616             if(a){\r
13617                 cb = function(){\r
13618                     this.hideAction();\r
13619                     if(c){\r
13620                         c();\r
13621                     }\r
13622                 }.createDelegate(this);\r
13623             }\r
13624             supr.setVisible.call(this, v, a, d, cb, e);\r
13625             if(v){\r
13626                 this.sync(true);\r
13627             }else if(!a){\r
13628                 this.hideAction();\r
13629             }\r
13630         }\r
13631     },\r
13632 \r
13633     storeXY : function(xy){\r
13634         delete this.lastLT;\r
13635         this.lastXY = xy;\r
13636     },\r
13637 \r
13638     storeLeftTop : function(left, top){\r
13639         delete this.lastXY;\r
13640         this.lastLT = [left, top];\r
13641     },\r
13642 \r
13643     // private\r
13644     beforeFx : function(){\r
13645         this.beforeAction();\r
13646         return Ext.Layer.superclass.beforeFx.apply(this, arguments);\r
13647     },\r
13648 \r
13649     // private\r
13650     afterFx : function(){\r
13651         Ext.Layer.superclass.afterFx.apply(this, arguments);\r
13652         this.sync(this.isVisible());\r
13653     },\r
13654 \r
13655     // private\r
13656     beforeAction : function(){\r
13657         if(!this.updating && this.shadow){\r
13658             this.shadow.hide();\r
13659         }\r
13660     },\r
13661 \r
13662     // overridden Element method\r
13663     setLeft : function(left){\r
13664         this.storeLeftTop(left, this.getTop(true));\r
13665         supr.setLeft.apply(this, arguments);\r
13666         this.sync();\r
13667     },\r
13668 \r
13669     setTop : function(top){\r
13670         this.storeLeftTop(this.getLeft(true), top);\r
13671         supr.setTop.apply(this, arguments);\r
13672         this.sync();\r
13673     },\r
13674 \r
13675     setLeftTop : function(left, top){\r
13676         this.storeLeftTop(left, top);\r
13677         supr.setLeftTop.apply(this, arguments);\r
13678         this.sync();\r
13679     },\r
13680 \r
13681     setXY : function(xy, a, d, c, e){\r
13682         this.fixDisplay();\r
13683         this.beforeAction();\r
13684         this.storeXY(xy);\r
13685         var cb = this.createCB(c);\r
13686         supr.setXY.call(this, xy, a, d, cb, e);\r
13687         if(!a){\r
13688             cb();\r
13689         }\r
13690     },\r
13691 \r
13692     // private\r
13693     createCB : function(c){\r
13694         var el = this;\r
13695         return function(){\r
13696             el.constrainXY();\r
13697             el.sync(true);\r
13698             if(c){\r
13699                 c();\r
13700             }\r
13701         };\r
13702     },\r
13703 \r
13704     // overridden Element method\r
13705     setX : function(x, a, d, c, e){\r
13706         this.setXY([x, this.getY()], a, d, c, e);\r
13707     },\r
13708 \r
13709     // overridden Element method\r
13710     setY : function(y, a, d, c, e){\r
13711         this.setXY([this.getX(), y], a, d, c, e);\r
13712     },\r
13713 \r
13714     // overridden Element method\r
13715     setSize : function(w, h, a, d, c, e){\r
13716         this.beforeAction();\r
13717         var cb = this.createCB(c);\r
13718         supr.setSize.call(this, w, h, a, d, cb, e);\r
13719         if(!a){\r
13720             cb();\r
13721         }\r
13722     },\r
13723 \r
13724     // overridden Element method\r
13725     setWidth : function(w, a, d, c, e){\r
13726         this.beforeAction();\r
13727         var cb = this.createCB(c);\r
13728         supr.setWidth.call(this, w, a, d, cb, e);\r
13729         if(!a){\r
13730             cb();\r
13731         }\r
13732     },\r
13733 \r
13734     // overridden Element method\r
13735     setHeight : function(h, a, d, c, e){\r
13736         this.beforeAction();\r
13737         var cb = this.createCB(c);\r
13738         supr.setHeight.call(this, h, a, d, cb, e);\r
13739         if(!a){\r
13740             cb();\r
13741         }\r
13742     },\r
13743 \r
13744     // overridden Element method\r
13745     setBounds : function(x, y, w, h, a, d, c, e){\r
13746         this.beforeAction();\r
13747         var cb = this.createCB(c);\r
13748         if(!a){\r
13749             this.storeXY([x, y]);\r
13750             supr.setXY.call(this, [x, y]);\r
13751             supr.setSize.call(this, w, h, a, d, cb, e);\r
13752             cb();\r
13753         }else{\r
13754             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);\r
13755         }\r
13756         return this;\r
13757     },\r
13758 \r
13759     \r
13760     setZIndex : function(zindex){\r
13761         this.zindex = zindex;\r
13762         this.setStyle("z-index", zindex + 2);\r
13763         if(this.shadow){\r
13764             this.shadow.setZIndex(zindex + 1);\r
13765         }\r
13766         if(this.shim){\r
13767             this.shim.setStyle("z-index", zindex);\r
13768         }\r
13769     }\r
13770 });\r
13771 })();\r
13772 \r
13773 Ext.Shadow = function(config){\r
13774     Ext.apply(this, config);\r
13775     if(typeof this.mode != "string"){\r
13776         this.mode = this.defaultMode;\r
13777     }\r
13778     var o = this.offset, a = {h: 0};\r
13779     var rad = Math.floor(this.offset/2);\r
13780     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows\r
13781         case "drop":\r
13782             a.w = 0;\r
13783             a.l = a.t = o;\r
13784             a.t -= 1;\r
13785             if(Ext.isIE){\r
13786                 a.l -= this.offset + rad;\r
13787                 a.t -= this.offset + rad;\r
13788                 a.w -= rad;\r
13789                 a.h -= rad;\r
13790                 a.t += 1;\r
13791             }\r
13792         break;\r
13793         case "sides":\r
13794             a.w = (o*2);\r
13795             a.l = -o;\r
13796             a.t = o-1;\r
13797             if(Ext.isIE){\r
13798                 a.l -= (this.offset - rad);\r
13799                 a.t -= this.offset + rad;\r
13800                 a.l += 1;\r
13801                 a.w -= (this.offset - rad)*2;\r
13802                 a.w -= rad + 1;\r
13803                 a.h -= 1;\r
13804             }\r
13805         break;\r
13806         case "frame":\r
13807             a.w = a.h = (o*2);\r
13808             a.l = a.t = -o;\r
13809             a.t += 1;\r
13810             a.h -= 2;\r
13811             if(Ext.isIE){\r
13812                 a.l -= (this.offset - rad);\r
13813                 a.t -= (this.offset - rad);\r
13814                 a.l += 1;\r
13815                 a.w -= (this.offset + rad + 1);\r
13816                 a.h -= (this.offset + rad);\r
13817                 a.h += 1;\r
13818             }\r
13819         break;\r
13820     };\r
13821 \r
13822     this.adjusts = a;\r
13823 };\r
13824 \r
13825 Ext.Shadow.prototype = {\r
13826     \r
13827     \r
13828     offset: 4,\r
13829 \r
13830     // private\r
13831     defaultMode: "drop",\r
13832 \r
13833     \r
13834     show : function(target){\r
13835         target = Ext.get(target);\r
13836         if(!this.el){\r
13837             this.el = Ext.Shadow.Pool.pull();\r
13838             if(this.el.dom.nextSibling != target.dom){\r
13839                 this.el.insertBefore(target);\r
13840             }\r
13841         }\r
13842         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);\r
13843         if(Ext.isIE){\r
13844             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";\r
13845         }\r
13846         this.realign(\r
13847             target.getLeft(true),\r
13848             target.getTop(true),\r
13849             target.getWidth(),\r
13850             target.getHeight()\r
13851         );\r
13852         this.el.dom.style.display = "block";\r
13853     },\r
13854 \r
13855     \r
13856     isVisible : function(){\r
13857         return this.el ? true : false;  \r
13858     },\r
13859 \r
13860     \r
13861     realign : function(l, t, w, h){\r
13862         if(!this.el){\r
13863             return;\r
13864         }\r
13865         var a = this.adjusts, d = this.el.dom, s = d.style;\r
13866         var iea = 0;\r
13867         s.left = (l+a.l)+"px";\r
13868         s.top = (t+a.t)+"px";\r
13869         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";\r
13870         if(s.width != sws || s.height != shs){\r
13871             s.width = sws;\r
13872             s.height = shs;\r
13873             if(!Ext.isIE){\r
13874                 var cn = d.childNodes;\r
13875                 var sww = Math.max(0, (sw-12))+"px";\r
13876                 cn[0].childNodes[1].style.width = sww;\r
13877                 cn[1].childNodes[1].style.width = sww;\r
13878                 cn[2].childNodes[1].style.width = sww;\r
13879                 cn[1].style.height = Math.max(0, (sh-12))+"px";\r
13880             }\r
13881         }\r
13882     },\r
13883 \r
13884     \r
13885     hide : function(){\r
13886         if(this.el){\r
13887             this.el.dom.style.display = "none";\r
13888             Ext.Shadow.Pool.push(this.el);\r
13889             delete this.el;\r
13890         }\r
13891     },\r
13892 \r
13893     \r
13894     setZIndex : function(z){\r
13895         this.zIndex = z;\r
13896         if(this.el){\r
13897             this.el.setStyle("z-index", z);\r
13898         }\r
13899     }\r
13900 };\r
13901 \r
13902 // Private utility class that manages the internal Shadow cache\r
13903 Ext.Shadow.Pool = function(){\r
13904     var p = [];\r
13905     var markup = Ext.isIE ?\r
13906                  '<div class="x-ie-shadow"></div>' :\r
13907                  '<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>';\r
13908     return {\r
13909         pull : function(){\r
13910             var sh = p.shift();\r
13911             if(!sh){\r
13912                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));\r
13913                 sh.autoBoxAdjust = false;\r
13914             }\r
13915             return sh;\r
13916         },\r
13917 \r
13918         push : function(sh){\r
13919             p.push(sh);\r
13920         }\r
13921     };\r
13922 }();\r
13923 \r
13924 Ext.BoxComponent = Ext.extend(Ext.Component, {\r
13925     \r
13926     \r
13927     \r
13928     \r
13929     \r
13930     \r
13931     \r
13932     \r
13933 \r
13934     \r
13935 \r
13936         // private\r
13937     initComponent : function(){\r
13938         Ext.BoxComponent.superclass.initComponent.call(this);\r
13939         this.addEvents(\r
13940             \r
13941             'resize',\r
13942             \r
13943             'move'\r
13944         );\r
13945     },\r
13946 \r
13947     // private, set in afterRender to signify that the component has been rendered\r
13948     boxReady : false,\r
13949     // private, used to defer height settings to subclasses\r
13950     deferHeight: false,\r
13951 \r
13952     \r
13953     setSize : function(w, h){\r
13954         // support for standard size objects\r
13955         if(typeof w == 'object'){\r
13956             h = w.height;\r
13957             w = w.width;\r
13958         }\r
13959         // not rendered\r
13960         if(!this.boxReady){\r
13961             this.width = w;\r
13962             this.height = h;\r
13963             return this;\r
13964         }\r
13965 \r
13966         // prevent recalcs when not needed\r
13967         if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){\r
13968             return this;\r
13969         }\r
13970         this.lastSize = {width: w, height: h};\r
13971         var adj = this.adjustSize(w, h);\r
13972         var aw = adj.width, ah = adj.height;\r
13973         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters\r
13974             var rz = this.getResizeEl();\r
13975             if(!this.deferHeight && aw !== undefined && ah !== undefined){\r
13976                 rz.setSize(aw, ah);\r
13977             }else if(!this.deferHeight && ah !== undefined){\r
13978                 rz.setHeight(ah);\r
13979             }else if(aw !== undefined){\r
13980                 rz.setWidth(aw);\r
13981             }\r
13982             this.onResize(aw, ah, w, h);\r
13983             this.fireEvent('resize', this, aw, ah, w, h);\r
13984         }\r
13985         return this;\r
13986     },\r
13987 \r
13988     \r
13989     setWidth : function(width){\r
13990         return this.setSize(width);\r
13991     },\r
13992 \r
13993     \r
13994     setHeight : function(height){\r
13995         return this.setSize(undefined, height);\r
13996     },\r
13997 \r
13998     \r
13999     getSize : function(){\r
14000         return this.el.getSize();\r
14001     },\r
14002 \r
14003     \r
14004     getPosition : function(local){\r
14005         if(local === true){\r
14006             return [this.el.getLeft(true), this.el.getTop(true)];\r
14007         }\r
14008         return this.xy || this.el.getXY();\r
14009     },\r
14010 \r
14011     \r
14012     getBox : function(local){\r
14013         var s = this.el.getSize();\r
14014         if(local === true){\r
14015             s.x = this.el.getLeft(true);\r
14016             s.y = this.el.getTop(true);\r
14017         }else{\r
14018             var xy = this.xy || this.el.getXY();\r
14019             s.x = xy[0];\r
14020             s.y = xy[1];\r
14021         }\r
14022         return s;\r
14023     },\r
14024 \r
14025     \r
14026     updateBox : function(box){\r
14027         this.setSize(box.width, box.height);\r
14028         this.setPagePosition(box.x, box.y);\r
14029         return this;\r
14030     },\r
14031 \r
14032     // protected\r
14033     getResizeEl : function(){\r
14034         return this.resizeEl || this.el;\r
14035     },\r
14036 \r
14037     // protected\r
14038     getPositionEl : function(){\r
14039         return this.positionEl || this.el;\r
14040     },\r
14041 \r
14042     \r
14043     setPosition : function(x, y){\r
14044         if(x && typeof x[1] == 'number'){\r
14045             y = x[1];\r
14046             x = x[0];\r
14047         }\r
14048         this.x = x;\r
14049         this.y = y;\r
14050         if(!this.boxReady){\r
14051             return this;\r
14052         }\r
14053         var adj = this.adjustPosition(x, y);\r
14054         var ax = adj.x, ay = adj.y;\r
14055 \r
14056         var el = this.getPositionEl();\r
14057         if(ax !== undefined || ay !== undefined){\r
14058             if(ax !== undefined && ay !== undefined){\r
14059                 el.setLeftTop(ax, ay);\r
14060             }else if(ax !== undefined){\r
14061                 el.setLeft(ax);\r
14062             }else if(ay !== undefined){\r
14063                 el.setTop(ay);\r
14064             }\r
14065             this.onPosition(ax, ay);\r
14066             this.fireEvent('move', this, ax, ay);\r
14067         }\r
14068         return this;\r
14069     },\r
14070 \r
14071     \r
14072     setPagePosition : function(x, y){\r
14073         if(x && typeof x[1] == 'number'){\r
14074             y = x[1];\r
14075             x = x[0];\r
14076         }\r
14077         this.pageX = x;\r
14078         this.pageY = y;\r
14079         if(!this.boxReady){\r
14080             return;\r
14081         }\r
14082         if(x === undefined || y === undefined){ // cannot translate undefined points\r
14083             return;\r
14084         }\r
14085         var p = this.el.translatePoints(x, y);\r
14086         this.setPosition(p.left, p.top);\r
14087         return this;\r
14088     },\r
14089 \r
14090     // private\r
14091     onRender : function(ct, position){\r
14092         Ext.BoxComponent.superclass.onRender.call(this, ct, position);\r
14093         if(this.resizeEl){\r
14094             this.resizeEl = Ext.get(this.resizeEl);\r
14095         }\r
14096         if(this.positionEl){\r
14097             this.positionEl = Ext.get(this.positionEl);\r
14098         }\r
14099     },\r
14100 \r
14101     // private\r
14102     afterRender : function(){\r
14103         Ext.BoxComponent.superclass.afterRender.call(this);\r
14104         this.boxReady = true;\r
14105         this.setSize(this.width, this.height);\r
14106         if(this.x || this.y){\r
14107             this.setPosition(this.x, this.y);\r
14108         }else if(this.pageX || this.pageY){\r
14109             this.setPagePosition(this.pageX, this.pageY);\r
14110         }\r
14111     },\r
14112 \r
14113     \r
14114     syncSize : function(){\r
14115         delete this.lastSize;\r
14116         this.setSize(this.autoWidth ? undefined : this.el.getWidth(), this.autoHeight ? undefined : this.el.getHeight());\r
14117         return this;\r
14118     },\r
14119 \r
14120     \r
14121     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){\r
14122 \r
14123     },\r
14124 \r
14125     \r
14126     onPosition : function(x, y){\r
14127 \r
14128     },\r
14129 \r
14130     // private\r
14131     adjustSize : function(w, h){\r
14132         if(this.autoWidth){\r
14133             w = 'auto';\r
14134         }\r
14135         if(this.autoHeight){\r
14136             h = 'auto';\r
14137         }\r
14138         return {width : w, height: h};\r
14139     },\r
14140 \r
14141     // private\r
14142     adjustPosition : function(x, y){\r
14143         return {x : x, y: y};\r
14144     }\r
14145 });\r
14146 Ext.reg('box', Ext.BoxComponent);\r
14147 \r
14148 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
14149     \r
14150     \r
14151     this.el = Ext.get(dragElement, true);\r
14152     this.el.dom.unselectable = "on";\r
14153     \r
14154     this.resizingEl = Ext.get(resizingElement, true);\r
14155 \r
14156     \r
14157     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
14158     \r
14159     \r
14160     this.minSize = 0;\r
14161     \r
14162     \r
14163     this.maxSize = 2000;\r
14164     \r
14165     \r
14166     this.animate = false;\r
14167     \r
14168     \r
14169     this.useShim = false;\r
14170     \r
14171     \r
14172     this.shim = null;\r
14173     \r
14174     if(!existingProxy){\r
14175         \r
14176         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
14177     }else{\r
14178         this.proxy = Ext.get(existingProxy).dom;\r
14179     }\r
14180     \r
14181     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
14182     \r
14183     \r
14184     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
14185     \r
14186     \r
14187     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
14188     \r
14189     \r
14190     this.dragSpecs = {};\r
14191     \r
14192     \r
14193     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
14194     this.adapter.init(this);\r
14195     \r
14196     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
14197         \r
14198         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
14199         this.el.addClass("x-splitbar-h");\r
14200     }else{\r
14201         \r
14202         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
14203         this.el.addClass("x-splitbar-v");\r
14204     }\r
14205     \r
14206     this.addEvents(\r
14207         \r
14208         "resize",\r
14209         \r
14210         "moved",\r
14211         \r
14212         "beforeresize",\r
14213 \r
14214         "beforeapply"\r
14215     );\r
14216 \r
14217     Ext.SplitBar.superclass.constructor.call(this);\r
14218 };\r
14219 \r
14220 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
14221     onStartProxyDrag : function(x, y){\r
14222         this.fireEvent("beforeresize", this);\r
14223         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
14224         this.overlay.unselectable();\r
14225         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
14226         this.overlay.show();\r
14227         Ext.get(this.proxy).setDisplayed("block");\r
14228         var size = this.adapter.getElementSize(this);\r
14229         this.activeMinSize = this.getMinimumSize();\r
14230         this.activeMaxSize = this.getMaximumSize();\r
14231         var c1 = size - this.activeMinSize;\r
14232         var c2 = Math.max(this.activeMaxSize - size, 0);\r
14233         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
14234             this.dd.resetConstraints();\r
14235             this.dd.setXConstraint(\r
14236                 this.placement == Ext.SplitBar.LEFT ? c1 : c2, \r
14237                 this.placement == Ext.SplitBar.LEFT ? c2 : c1\r
14238             );\r
14239             this.dd.setYConstraint(0, 0);\r
14240         }else{\r
14241             this.dd.resetConstraints();\r
14242             this.dd.setXConstraint(0, 0);\r
14243             this.dd.setYConstraint(\r
14244                 this.placement == Ext.SplitBar.TOP ? c1 : c2, \r
14245                 this.placement == Ext.SplitBar.TOP ? c2 : c1\r
14246             );\r
14247          }\r
14248         this.dragSpecs.startSize = size;\r
14249         this.dragSpecs.startPoint = [x, y];\r
14250         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
14251     },\r
14252     \r
14253     \r
14254     onEndProxyDrag : function(e){\r
14255         Ext.get(this.proxy).setDisplayed(false);\r
14256         var endPoint = Ext.lib.Event.getXY(e);\r
14257         if(this.overlay){\r
14258             Ext.destroy(this.overlay);\r
14259             delete this.overlay;\r
14260         }\r
14261         var newSize;\r
14262         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
14263             newSize = this.dragSpecs.startSize + \r
14264                 (this.placement == Ext.SplitBar.LEFT ?\r
14265                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
14266                     this.dragSpecs.startPoint[0] - endPoint[0]\r
14267                 );\r
14268         }else{\r
14269             newSize = this.dragSpecs.startSize + \r
14270                 (this.placement == Ext.SplitBar.TOP ?\r
14271                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
14272                     this.dragSpecs.startPoint[1] - endPoint[1]\r
14273                 );\r
14274         }\r
14275         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
14276         if(newSize != this.dragSpecs.startSize){\r
14277             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
14278                 this.adapter.setElementSize(this, newSize);\r
14279                 this.fireEvent("moved", this, newSize);\r
14280                 this.fireEvent("resize", this, newSize);\r
14281             }\r
14282         }\r
14283     },\r
14284     \r
14285     \r
14286     getAdapter : function(){\r
14287         return this.adapter;\r
14288     },\r
14289     \r
14290     \r
14291     setAdapter : function(adapter){\r
14292         this.adapter = adapter;\r
14293         this.adapter.init(this);\r
14294     },\r
14295     \r
14296     \r
14297     getMinimumSize : function(){\r
14298         return this.minSize;\r
14299     },\r
14300     \r
14301     \r
14302     setMinimumSize : function(minSize){\r
14303         this.minSize = minSize;\r
14304     },\r
14305     \r
14306     \r
14307     getMaximumSize : function(){\r
14308         return this.maxSize;\r
14309     },\r
14310     \r
14311     \r
14312     setMaximumSize : function(maxSize){\r
14313         this.maxSize = maxSize;\r
14314     },\r
14315     \r
14316     \r
14317     setCurrentSize : function(size){\r
14318         var oldAnimate = this.animate;\r
14319         this.animate = false;\r
14320         this.adapter.setElementSize(this, size);\r
14321         this.animate = oldAnimate;\r
14322     },\r
14323     \r
14324     \r
14325     destroy : function(removeEl){\r
14326         if(this.shim){\r
14327             this.shim.remove();\r
14328         }\r
14329         this.dd.unreg();\r
14330         Ext.destroy(Ext.get(this.proxy));\r
14331         if(removeEl){\r
14332             this.el.remove();\r
14333         }\r
14334     }\r
14335 });\r
14336 \r
14337 \r
14338 Ext.SplitBar.createProxy = function(dir){\r
14339     var proxy = new Ext.Element(document.createElement("div"));\r
14340     proxy.unselectable();\r
14341     var cls = 'x-splitbar-proxy';\r
14342     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
14343     document.body.appendChild(proxy.dom);\r
14344     return proxy.dom;\r
14345 };\r
14346 \r
14347 \r
14348 Ext.SplitBar.BasicLayoutAdapter = function(){\r
14349 };\r
14350 \r
14351 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
14352     // do nothing for now\r
14353     init : function(s){\r
14354     \r
14355     },\r
14356     \r
14357      getElementSize : function(s){\r
14358         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
14359             return s.resizingEl.getWidth();\r
14360         }else{\r
14361             return s.resizingEl.getHeight();\r
14362         }\r
14363     },\r
14364     \r
14365     \r
14366     setElementSize : function(s, newSize, onComplete){\r
14367         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
14368             if(!s.animate){\r
14369                 s.resizingEl.setWidth(newSize);\r
14370                 if(onComplete){\r
14371                     onComplete(s, newSize);\r
14372                 }\r
14373             }else{\r
14374                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
14375             }\r
14376         }else{\r
14377             \r
14378             if(!s.animate){\r
14379                 s.resizingEl.setHeight(newSize);\r
14380                 if(onComplete){\r
14381                     onComplete(s, newSize);\r
14382                 }\r
14383             }else{\r
14384                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
14385             }\r
14386         }\r
14387     }\r
14388 };\r
14389 \r
14390 \r
14391 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
14392     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
14393     this.container = Ext.get(container);\r
14394 };\r
14395 \r
14396 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
14397     init : function(s){\r
14398         this.basic.init(s);\r
14399     },\r
14400     \r
14401     getElementSize : function(s){\r
14402         return this.basic.getElementSize(s);\r
14403     },\r
14404     \r
14405     setElementSize : function(s, newSize, onComplete){\r
14406         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
14407     },\r
14408     \r
14409     moveSplitter : function(s){\r
14410         var yes = Ext.SplitBar;\r
14411         switch(s.placement){\r
14412             case yes.LEFT:\r
14413                 s.el.setX(s.resizingEl.getRight());\r
14414                 break;\r
14415             case yes.RIGHT:\r
14416                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
14417                 break;\r
14418             case yes.TOP:\r
14419                 s.el.setY(s.resizingEl.getBottom());\r
14420                 break;\r
14421             case yes.BOTTOM:\r
14422                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
14423                 break;\r
14424         }\r
14425     }\r
14426 };\r
14427 \r
14428 \r
14429 Ext.SplitBar.VERTICAL = 1;\r
14430 \r
14431 \r
14432 Ext.SplitBar.HORIZONTAL = 2;\r
14433 \r
14434 \r
14435 Ext.SplitBar.LEFT = 1;\r
14436 \r
14437 \r
14438 Ext.SplitBar.RIGHT = 2;\r
14439 \r
14440 \r
14441 Ext.SplitBar.TOP = 3;\r
14442 \r
14443 \r
14444 Ext.SplitBar.BOTTOM = 4;\r
14445 \r
14446 \r
14447 Ext.Container = Ext.extend(Ext.BoxComponent, {\r
14448     \r
14449     \r
14450     \r
14451     \r
14452     \r
14453     \r
14454     \r
14455 \r
14456     \r
14457     autoDestroy: true,\r
14458     \r
14459     \r
14460     defaultType: 'panel',\r
14461 \r
14462     // private\r
14463     initComponent : function(){\r
14464         Ext.Container.superclass.initComponent.call(this);\r
14465 \r
14466         this.addEvents(\r
14467             \r
14468             'afterlayout',\r
14469             \r
14470             'beforeadd',\r
14471             \r
14472             'beforeremove',\r
14473             \r
14474             'add',\r
14475             \r
14476             'remove'\r
14477         );\r
14478 \r
14479         \r
14480         var items = this.items;\r
14481         if(items){\r
14482             delete this.items;\r
14483             if(Ext.isArray(items) && items.length > 0){\r
14484                 this.add.apply(this, items);\r
14485             }else{\r
14486                 this.add(items);\r
14487             }\r
14488         }\r
14489     },\r
14490 \r
14491     // private\r
14492     initItems : function(){\r
14493         if(!this.items){\r
14494             this.items = new Ext.util.MixedCollection(false, this.getComponentId);\r
14495             this.getLayout(); // initialize the layout\r
14496         }\r
14497     },\r
14498 \r
14499     // private\r
14500     setLayout : function(layout){\r
14501         if(this.layout && this.layout != layout){\r
14502             this.layout.setContainer(null);\r
14503         }\r
14504         this.initItems();\r
14505         this.layout = layout;\r
14506         layout.setContainer(this);\r
14507     },\r
14508 \r
14509     // private\r
14510     render : function(){\r
14511         Ext.Container.superclass.render.apply(this, arguments);\r
14512         if(this.layout){\r
14513             if(typeof this.layout == 'string'){\r
14514                 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);\r
14515             }\r
14516             this.setLayout(this.layout);\r
14517 \r
14518             if(this.activeItem !== undefined){\r
14519                 var item = this.activeItem;\r
14520                 delete this.activeItem;\r
14521                 this.layout.setActiveItem(item);\r
14522                 return;\r
14523             }\r
14524         }\r
14525         if(!this.ownerCt){\r
14526             this.doLayout();\r
14527         }\r
14528         if(this.monitorResize === true){\r
14529             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);\r
14530         }\r
14531     },\r
14532 \r
14533     \r
14534     getLayoutTarget : function(){\r
14535         return this.el;\r
14536     },\r
14537 \r
14538     // private - used as the key lookup function for the items collection\r
14539     getComponentId : function(comp){\r
14540         return comp.itemId || comp.id;\r
14541     },\r
14542 \r
14543     \r
14544     add : function(comp){\r
14545         if(!this.items){\r
14546             this.initItems();\r
14547         }\r
14548         var a = arguments, len = a.length;\r
14549         if(len > 1){\r
14550             for(var i = 0; i < len; i++) {\r
14551                 this.add(a[i]);\r
14552             }\r
14553             return;\r
14554         }\r
14555         var c = this.lookupComponent(this.applyDefaults(comp));\r
14556         var pos = this.items.length;\r
14557         if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){\r
14558             this.items.add(c);\r
14559             c.ownerCt = this;\r
14560             this.fireEvent('add', this, c, pos);\r
14561         }\r
14562         return c;\r
14563     },\r
14564 \r
14565     \r
14566     insert : function(index, comp){\r
14567         if(!this.items){\r
14568             this.initItems();\r
14569         }\r
14570         var a = arguments, len = a.length;\r
14571         if(len > 2){\r
14572             for(var i = len-1; i >= 1; --i) {\r
14573                 this.insert(index, a[i]);\r
14574             }\r
14575             return;\r
14576         }\r
14577         var c = this.lookupComponent(this.applyDefaults(comp));\r
14578 \r
14579         if(c.ownerCt == this && this.items.indexOf(c) < index){\r
14580             --index;\r
14581         }\r
14582 \r
14583         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){\r
14584             this.items.insert(index, c);\r
14585             c.ownerCt = this;\r
14586             this.fireEvent('add', this, c, index);\r
14587         }\r
14588         return c;\r
14589     },\r
14590 \r
14591     // private\r
14592     applyDefaults : function(c){\r
14593         if(this.defaults){\r
14594             if(typeof c == 'string'){\r
14595                 c = Ext.ComponentMgr.get(c);\r
14596                 Ext.apply(c, this.defaults);\r
14597             }else if(!c.events){\r
14598                 Ext.applyIf(c, this.defaults);\r
14599             }else{\r
14600                 Ext.apply(c, this.defaults);\r
14601             }\r
14602         }\r
14603         return c;\r
14604     },\r
14605 \r
14606     // private\r
14607     onBeforeAdd : function(item){\r
14608         if(item.ownerCt){\r
14609             item.ownerCt.remove(item, false);\r
14610         }\r
14611         if(this.hideBorders === true){\r
14612             item.border = (item.border === true);\r
14613         }\r
14614     },\r
14615 \r
14616     \r
14617     remove : function(comp, autoDestroy){\r
14618         var c = this.getComponent(comp);\r
14619         if(c && this.fireEvent('beforeremove', this, c) !== false){\r
14620             this.items.remove(c);\r
14621             delete c.ownerCt;\r
14622             if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){\r
14623                 c.destroy();\r
14624             }\r
14625             if(this.layout && this.layout.activeItem == c){\r
14626                 delete this.layout.activeItem;\r
14627             }\r
14628             this.fireEvent('remove', this, c);\r
14629         }\r
14630         return c;\r
14631     },\r
14632     \r
14633     \r
14634     removeAll: function(autoDestroy){\r
14635         var item, items = [];\r
14636         while((item = this.items.last())){\r
14637             items.unshift(this.remove(item, autoDestroy));\r
14638         }\r
14639         return items;\r
14640     },\r
14641 \r
14642     \r
14643     getComponent : function(comp){\r
14644         if(typeof comp == 'object'){\r
14645             return comp;\r
14646         }\r
14647         return this.items.get(comp);\r
14648     },\r
14649 \r
14650     // private\r
14651     lookupComponent : function(comp){\r
14652         if(typeof comp == 'string'){\r
14653             return Ext.ComponentMgr.get(comp);\r
14654         }else if(!comp.events){\r
14655             return this.createComponent(comp);\r
14656         }\r
14657         return comp;\r
14658     },\r
14659 \r
14660     // private\r
14661     createComponent : function(config){\r
14662         return Ext.ComponentMgr.create(config, this.defaultType);\r
14663     },\r
14664 \r
14665     \r
14666     doLayout : function(shallow){\r
14667         if(this.rendered && this.layout){\r
14668             this.layout.layout();\r
14669         }\r
14670         if(shallow !== false && this.items){\r
14671             var cs = this.items.items;\r
14672             for(var i = 0, len = cs.length; i < len; i++) {\r
14673                 var c  = cs[i];\r
14674                 if(c.doLayout){\r
14675                     c.doLayout();\r
14676                 }\r
14677             }\r
14678         }\r
14679     },\r
14680 \r
14681     \r
14682     getLayout : function(){\r
14683         if(!this.layout){\r
14684             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);\r
14685             this.setLayout(layout);\r
14686         }\r
14687         return this.layout;\r
14688     },\r
14689 \r
14690     // private\r
14691     beforeDestroy : function(){\r
14692         if(this.items){\r
14693             Ext.destroy.apply(Ext, this.items.items);\r
14694         }\r
14695         if(this.monitorResize){\r
14696             Ext.EventManager.removeResizeListener(this.doLayout, this);\r
14697         }\r
14698         if (this.layout && this.layout.destroy) {\r
14699             this.layout.destroy();\r
14700         }\r
14701         Ext.Container.superclass.beforeDestroy.call(this);\r
14702     },\r
14703 \r
14704     \r
14705     bubble : function(fn, scope, args){\r
14706         var p = this;\r
14707         while(p){\r
14708             if(fn.apply(scope || p, args || [p]) === false){\r
14709                 break;\r
14710             }\r
14711             p = p.ownerCt;\r
14712         }\r
14713     },\r
14714 \r
14715     \r
14716     cascade : function(fn, scope, args){\r
14717         if(fn.apply(scope || this, args || [this]) !== false){\r
14718             if(this.items){\r
14719                 var cs = this.items.items;\r
14720                 for(var i = 0, len = cs.length; i < len; i++){\r
14721                     if(cs[i].cascade){\r
14722                         cs[i].cascade(fn, scope, args);\r
14723                     }else{\r
14724                         fn.apply(scope || cs[i], args || [cs[i]]);\r
14725                     }\r
14726                 }\r
14727             }\r
14728         }\r
14729     },\r
14730 \r
14731     \r
14732     findById : function(id){\r
14733         var m, ct = this;\r
14734         this.cascade(function(c){\r
14735             if(ct != c && c.id === id){\r
14736                 m = c;\r
14737                 return false;\r
14738             }\r
14739         });\r
14740         return m || null;\r
14741     },\r
14742 \r
14743     \r
14744     findByType : function(xtype, shallow){\r
14745         return this.findBy(function(c){\r
14746             return c.isXType(xtype, shallow);\r
14747         });\r
14748     },\r
14749 \r
14750     \r
14751     find : function(prop, value){\r
14752         return this.findBy(function(c){\r
14753             return c[prop] === value;\r
14754         });\r
14755     },\r
14756 \r
14757     \r
14758     findBy : function(fn, scope){\r
14759         var m = [], ct = this;\r
14760         this.cascade(function(c){\r
14761             if(ct != c && fn.call(scope || c, c, ct) === true){\r
14762                 m.push(c);\r
14763             }\r
14764         });\r
14765         return m;\r
14766     }\r
14767 });\r
14768 \r
14769 Ext.Container.LAYOUTS = {};\r
14770 Ext.reg('container', Ext.Container);\r
14771 \r
14772 Ext.layout.ContainerLayout = function(config){\r
14773     Ext.apply(this, config);\r
14774 };\r
14775 \r
14776 Ext.layout.ContainerLayout.prototype = {\r
14777     \r
14778     \r
14779 \r
14780     \r
14781 \r
14782     // private\r
14783     monitorResize:false,\r
14784     // private\r
14785     activeItem : null,\r
14786 \r
14787     // private\r
14788     layout : function(){\r
14789         var target = this.container.getLayoutTarget();\r
14790         this.onLayout(this.container, target);\r
14791         this.container.fireEvent('afterlayout', this.container, this);\r
14792     },\r
14793 \r
14794     // private\r
14795     onLayout : function(ct, target){\r
14796         this.renderAll(ct, target);\r
14797     },\r
14798 \r
14799     // private\r
14800     isValidParent : function(c, target){\r
14801                 var el = c.getPositionEl ? c.getPositionEl() : c.getEl();\r
14802                 return el.dom.parentNode == target.dom;\r
14803     },\r
14804 \r
14805     // private\r
14806     renderAll : function(ct, target){\r
14807         var items = ct.items.items;\r
14808         for(var i = 0, len = items.length; i < len; i++) {\r
14809             var c = items[i];\r
14810             if(c && (!c.rendered || !this.isValidParent(c, target))){\r
14811                 this.renderItem(c, i, target);\r
14812             }\r
14813         }\r
14814     },\r
14815 \r
14816     // private\r
14817     renderItem : function(c, position, target){\r
14818         if(c && !c.rendered){\r
14819             c.render(target, position);\r
14820             if(this.extraCls){\r
14821                 var t = c.getPositionEl ? c.getPositionEl() : c;\r
14822                 t.addClass(this.extraCls);\r
14823             }\r
14824             if (this.renderHidden && c != this.activeItem) {\r
14825                 c.hide();\r
14826             }\r
14827         }else if(c && !this.isValidParent(c, target)){\r
14828             if(this.extraCls){\r
14829                 var t = c.getPositionEl ? c.getPositionEl() : c;\r
14830                 t.addClass(this.extraCls);\r
14831             }\r
14832             if(typeof position == 'number'){\r
14833                 position = target.dom.childNodes[position];\r
14834             }\r
14835             target.dom.insertBefore(c.getEl().dom, position || null);\r
14836             if (this.renderHidden && c != this.activeItem) {\r
14837                 c.hide();\r
14838             }\r
14839         }\r
14840     },\r
14841 \r
14842     // private\r
14843     onResize: function(){\r
14844         if(this.container.collapsed){\r
14845             return;\r
14846         }\r
14847         var b = this.container.bufferResize;\r
14848         if(b){\r
14849             if(!this.resizeTask){\r
14850                 this.resizeTask = new Ext.util.DelayedTask(this.layout, this);\r
14851                 this.resizeBuffer = typeof b == 'number' ? b : 100;\r
14852             }\r
14853             this.resizeTask.delay(this.resizeBuffer);\r
14854         }else{\r
14855             this.layout();\r
14856         }\r
14857     },\r
14858 \r
14859     // private\r
14860     setContainer : function(ct){\r
14861         if(this.monitorResize && ct != this.container){\r
14862             if(this.container){\r
14863                 this.container.un('resize', this.onResize, this);\r
14864             }\r
14865             if(ct){\r
14866                 ct.on('resize', this.onResize, this);\r
14867             }\r
14868         }\r
14869         this.container = ct;\r
14870     },\r
14871 \r
14872     // private\r
14873     parseMargins : function(v){\r
14874         var ms = v.split(' ');\r
14875         var len = ms.length;\r
14876         if(len == 1){\r
14877             ms[1] = ms[0];\r
14878             ms[2] = ms[0];\r
14879             ms[3] = ms[0];\r
14880         }\r
14881         if(len == 2){\r
14882             ms[2] = ms[0];\r
14883             ms[3] = ms[1];\r
14884         }\r
14885         return {\r
14886             top:parseInt(ms[0], 10) || 0,\r
14887             right:parseInt(ms[1], 10) || 0,\r
14888             bottom:parseInt(ms[2], 10) || 0,\r
14889             left:parseInt(ms[3], 10) || 0\r
14890         };\r
14891     },\r
14892 \r
14893     \r
14894     destroy : Ext.emptyFn\r
14895 };\r
14896 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;\r
14897 \r
14898 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
14899     // private\r
14900     monitorResize:true,\r
14901 \r
14902     // private\r
14903     onLayout : function(ct, target){\r
14904         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
14905         if(!this.container.collapsed){\r
14906             this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());\r
14907         }\r
14908     },\r
14909 \r
14910     // private\r
14911     setItemSize : function(item, size){\r
14912         if(item && size.height > 0){ // display none?\r
14913             item.setSize(size);\r
14914         }\r
14915     }\r
14916 });\r
14917 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;\r
14918 \r
14919 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
14920     \r
14921     deferredRender : false,\r
14922 \r
14923     // private\r
14924     renderHidden : true,\r
14925 \r
14926     \r
14927     setActiveItem : function(item){\r
14928         item = this.container.getComponent(item);\r
14929         if(this.activeItem != item){\r
14930             if(this.activeItem){\r
14931                 this.activeItem.hide();\r
14932             }\r
14933             this.activeItem = item;\r
14934             item.show();\r
14935             this.layout();\r
14936         }\r
14937     },\r
14938 \r
14939     // private\r
14940     renderAll : function(ct, target){\r
14941         if(this.deferredRender){\r
14942             this.renderItem(this.activeItem, undefined, target);\r
14943         }else{\r
14944             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
14945         }\r
14946     }\r
14947 });\r
14948 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;\r
14949 \r
14950 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
14951     // private\r
14952     monitorResize:true,\r
14953 \r
14954     // private\r
14955     getAnchorViewSize : function(ct, target){\r
14956         return target.dom == document.body ?\r
14957                    target.getViewSize() : target.getStyleSize();\r
14958     },\r
14959 \r
14960     // private\r
14961     onLayout : function(ct, target){\r
14962         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);\r
14963 \r
14964         var size = this.getAnchorViewSize(ct, target);\r
14965 \r
14966         var w = size.width, h = size.height;\r
14967 \r
14968         if(w < 20 || h < 20){\r
14969             return;\r
14970         }\r
14971 \r
14972         // find the container anchoring size\r
14973         var aw, ah;\r
14974         if(ct.anchorSize){\r
14975             if(typeof ct.anchorSize == 'number'){\r
14976                 aw = ct.anchorSize;\r
14977             }else{\r
14978                 aw = ct.anchorSize.width;\r
14979                 ah = ct.anchorSize.height;\r
14980             }\r
14981         }else{\r
14982             aw = ct.initialConfig.width;\r
14983             ah = ct.initialConfig.height;\r
14984         }\r
14985 \r
14986         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;\r
14987         for(i = 0; i < len; i++){\r
14988             c = cs[i];\r
14989             if(c.anchor){\r
14990                 a = c.anchorSpec;\r
14991                 if(!a){ // cache all anchor values\r
14992                     var vs = c.anchor.split(' ');\r
14993                     c.anchorSpec = a = {\r
14994                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),\r
14995                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)\r
14996                     };\r
14997                 }\r
14998                 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;\r
14999                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;\r
15000 \r
15001                 if(cw || ch){\r
15002                     c.setSize(cw || undefined, ch || undefined);\r
15003                 }\r
15004             }\r
15005         }\r
15006     },\r
15007 \r
15008     // private\r
15009     parseAnchor : function(a, start, cstart){\r
15010         if(a && a != 'none'){\r
15011             var last;\r
15012             if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor\r
15013                 var diff = cstart - start;\r
15014                 return function(v){\r
15015                     if(v !== last){\r
15016                         last = v;\r
15017                         return v - diff;\r
15018                     }\r
15019                 }\r
15020             }else if(a.indexOf('%') != -1){\r
15021                 var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage\r
15022                 return function(v){\r
15023                     if(v !== last){\r
15024                         last = v;\r
15025                         return Math.floor(v*ratio);\r
15026                     }\r
15027                 }\r
15028             }else{\r
15029                 a = parseInt(a, 10);\r
15030                 if(!isNaN(a)){                            // simple offset adjustment\r
15031                     return function(v){\r
15032                         if(v !== last){\r
15033                             last = v;\r
15034                             return v + a;\r
15035                         }\r
15036                     }\r
15037                 }\r
15038             }\r
15039         }\r
15040         return false;\r
15041     },\r
15042 \r
15043     // private\r
15044     adjustWidthAnchor : function(value, comp){\r
15045         return value;\r
15046     },\r
15047 \r
15048     // private\r
15049     adjustHeightAnchor : function(value, comp){\r
15050         return value;\r
15051     }\r
15052     \r
15053     \r
15054 });\r
15055 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;\r
15056 \r
15057 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
15058     // private\r
15059     monitorResize:true,\r
15060     \r
15061     \r
15062     extraCls: 'x-column',\r
15063 \r
15064     scrollOffset : 0,\r
15065 \r
15066     // private\r
15067     isValidParent : function(c, target){\r
15068         return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;\r
15069     },\r
15070 \r
15071     // private\r
15072     onLayout : function(ct, target){\r
15073         var cs = ct.items.items, len = cs.length, c, i;\r
15074 \r
15075         if(!this.innerCt){\r
15076             target.addClass('x-column-layout-ct');\r
15077 \r
15078             // the innerCt prevents wrapping and shuffling while\r
15079             // the container is resizing\r
15080             this.innerCt = target.createChild({cls:'x-column-inner'});\r
15081             this.innerCt.createChild({cls:'x-clear'});\r
15082         }\r
15083         this.renderAll(ct, this.innerCt);\r
15084 \r
15085         var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();\r
15086 \r
15087         if(size.width < 1 && size.height < 1){ // display none?\r
15088             return;\r
15089         }\r
15090 \r
15091         var w = size.width - target.getPadding('lr') - this.scrollOffset,\r
15092             h = size.height - target.getPadding('tb'),\r
15093             pw = w;\r
15094 \r
15095         this.innerCt.setWidth(w);\r
15096         \r
15097         // some columns can be percentages while others are fixed\r
15098         // so we need to make 2 passes\r
15099 \r
15100         for(i = 0; i < len; i++){\r
15101             c = cs[i];\r
15102             if(!c.columnWidth){\r
15103                 pw -= (c.getSize().width + c.getEl().getMargins('lr'));\r
15104             }\r
15105         }\r
15106 \r
15107         pw = pw < 0 ? 0 : pw;\r
15108 \r
15109         for(i = 0; i < len; i++){\r
15110             c = cs[i];\r
15111             if(c.columnWidth){\r
15112                 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));\r
15113             }\r
15114         }\r
15115     }\r
15116     \r
15117     \r
15118 });\r
15119 \r
15120 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;\r
15121 \r
15122 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
15123     // private\r
15124     monitorResize:true,\r
15125     // private\r
15126     rendered : false,\r
15127 \r
15128     // private\r
15129     onLayout : function(ct, target){\r
15130         var collapsed;\r
15131         if(!this.rendered){\r
15132             target.position();\r
15133             target.addClass('x-border-layout-ct');\r
15134             var items = ct.items.items;\r
15135             collapsed = [];\r
15136             for(var i = 0, len = items.length; i < len; i++) {\r
15137                 var c = items[i];\r
15138                 var pos = c.region;\r
15139                 if(c.collapsed){\r
15140                     collapsed.push(c);\r
15141                 }\r
15142                 c.collapsed = false;\r
15143                 if(!c.rendered){\r
15144                     c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';\r
15145                     c.render(target, i);\r
15146                 }\r
15147                 this[pos] = pos != 'center' && c.split ?\r
15148                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :\r
15149                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);\r
15150                 this[pos].render(target, c);\r
15151             }\r
15152             this.rendered = true;\r
15153         }\r
15154 \r
15155         var size = target.getViewSize();\r
15156         if(size.width < 20 || size.height < 20){ // display none?\r
15157             if(collapsed){\r
15158                 this.restoreCollapsed = collapsed;\r
15159             }\r
15160             return;\r
15161         }else if(this.restoreCollapsed){\r
15162             collapsed = this.restoreCollapsed;\r
15163             delete this.restoreCollapsed;\r
15164         }\r
15165 \r
15166         var w = size.width, h = size.height;\r
15167         var centerW = w, centerH = h, centerY = 0, centerX = 0;\r
15168 \r
15169         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;\r
15170         if(!c && Ext.layout.BorderLayout.WARN !== false){\r
15171             throw 'No center region defined in BorderLayout ' + ct.id;\r
15172         }\r
15173 \r
15174         if(n && n.isVisible()){\r
15175             var b = n.getSize();\r
15176             var m = n.getMargins();\r
15177             b.width = w - (m.left+m.right);\r
15178             b.x = m.left;\r
15179             b.y = m.top;\r
15180             centerY = b.height + b.y + m.bottom;\r
15181             centerH -= centerY;\r
15182             n.applyLayout(b);\r
15183         }\r
15184         if(s && s.isVisible()){\r
15185             var b = s.getSize();\r
15186             var m = s.getMargins();\r
15187             b.width = w - (m.left+m.right);\r
15188             b.x = m.left;\r
15189             var totalHeight = (b.height + m.top + m.bottom);\r
15190             b.y = h - totalHeight + m.top;\r
15191             centerH -= totalHeight;\r
15192             s.applyLayout(b);\r
15193         }\r
15194         if(west && west.isVisible()){\r
15195             var b = west.getSize();\r
15196             var m = west.getMargins();\r
15197             b.height = centerH - (m.top+m.bottom);\r
15198             b.x = m.left;\r
15199             b.y = centerY + m.top;\r
15200             var totalWidth = (b.width + m.left + m.right);\r
15201             centerX += totalWidth;\r
15202             centerW -= totalWidth;\r
15203             west.applyLayout(b);\r
15204         }\r
15205         if(e && e.isVisible()){\r
15206             var b = e.getSize();\r
15207             var m = e.getMargins();\r
15208             b.height = centerH - (m.top+m.bottom);\r
15209             var totalWidth = (b.width + m.left + m.right);\r
15210             b.x = w - totalWidth + m.left;\r
15211             b.y = centerY + m.top;\r
15212             centerW -= totalWidth;\r
15213             e.applyLayout(b);\r
15214         }\r
15215 \r
15216         if(c){\r
15217             var m = c.getMargins();\r
15218             var centerBox = {\r
15219                 x: centerX + m.left,\r
15220                 y: centerY + m.top,\r
15221                 width: centerW - (m.left+m.right),\r
15222                 height: centerH - (m.top+m.bottom)\r
15223             };\r
15224             c.applyLayout(centerBox);\r
15225         }\r
15226         if(collapsed){\r
15227             for(var i = 0, len = collapsed.length; i < len; i++){\r
15228                 collapsed[i].collapse(false);\r
15229             }\r
15230         }\r
15231 \r
15232         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue\r
15233             target.repaint();\r
15234         }\r
15235     },\r
15236 \r
15237     // inherit docs\r
15238     destroy: function() {\r
15239         var r = ['north', 'south', 'east', 'west'];\r
15240         for (var i = 0; i < r.length; i++) {\r
15241             var region = this[r[i]];\r
15242             if(region){\r
15243                 if(region.destroy){\r
15244                         region.destroy();\r
15245                     }else if (region.split){\r
15246                         region.split.destroy(true);\r
15247                     }\r
15248             }\r
15249         }\r
15250         Ext.layout.BorderLayout.superclass.destroy.call(this);\r
15251     }\r
15252     \r
15253     \r
15254 });\r
15255 \r
15256 \r
15257 Ext.layout.BorderLayout.Region = function(layout, config, pos){\r
15258     Ext.apply(this, config);\r
15259     this.layout = layout;\r
15260     this.position = pos;\r
15261     this.state = {};\r
15262     if(typeof this.margins == 'string'){\r
15263         this.margins = this.layout.parseMargins(this.margins);\r
15264     }\r
15265     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);\r
15266     if(this.collapsible){\r
15267         if(typeof this.cmargins == 'string'){\r
15268             this.cmargins = this.layout.parseMargins(this.cmargins);\r
15269         }\r
15270         if(this.collapseMode == 'mini' && !this.cmargins){\r
15271             this.cmargins = {left:0,top:0,right:0,bottom:0};\r
15272         }else{\r
15273             this.cmargins = Ext.applyIf(this.cmargins || {},\r
15274                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);\r
15275         }\r
15276     }\r
15277 };\r
15278 \r
15279 Ext.layout.BorderLayout.Region.prototype = {\r
15280     \r
15281     \r
15282         \r
15283     \r
15284     \r
15285     \r
15286     \r
15287     collapsible : false,\r
15288     \r
15289     split:false,\r
15290     \r
15291     floatable: true,\r
15292     \r
15293     minWidth:50,\r
15294     \r
15295     minHeight:50,\r
15296 \r
15297     // private\r
15298     defaultMargins : {left:0,top:0,right:0,bottom:0},\r
15299     // private\r
15300     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},\r
15301     // private\r
15302     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},\r
15303 \r
15304     \r
15305     isCollapsed : false,\r
15306 \r
15307     \r
15308     \r
15309     \r
15310 \r
15311     // private\r
15312     render : function(ct, p){\r
15313         this.panel = p;\r
15314         p.el.enableDisplayMode();\r
15315         this.targetEl = ct;\r
15316         this.el = p.el;\r
15317 \r
15318         var gs = p.getState, ps = this.position;\r
15319         p.getState = function(){\r
15320             return Ext.apply(gs.call(p) || {}, this.state);\r
15321         }.createDelegate(this);\r
15322 \r
15323         if(ps != 'center'){\r
15324             p.allowQueuedExpand = false;\r
15325             p.on({\r
15326                 beforecollapse: this.beforeCollapse,\r
15327                 collapse: this.onCollapse,\r
15328                 beforeexpand: this.beforeExpand,\r
15329                 expand: this.onExpand,\r
15330                 hide: this.onHide,\r
15331                 show: this.onShow,\r
15332                 scope: this\r
15333             });\r
15334             if(this.collapsible){\r
15335                 p.collapseEl = 'el';\r
15336                 p.slideAnchor = this.getSlideAnchor();\r
15337             }\r
15338             if(p.tools && p.tools.toggle){\r
15339                 p.tools.toggle.addClass('x-tool-collapse-'+ps);\r
15340                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');\r
15341             }\r
15342         }\r
15343     },\r
15344 \r
15345     // private\r
15346     getCollapsedEl : function(){\r
15347         if(!this.collapsedEl){\r
15348             if(!this.toolTemplate){\r
15349                 var tt = new Ext.Template(\r
15350                      '<div class="x-tool x-tool-{id}">&#160;</div>'\r
15351                 );\r
15352                 tt.disableFormats = true;\r
15353                 tt.compile();\r
15354                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;\r
15355             }\r
15356             this.collapsedEl = this.targetEl.createChild({\r
15357                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,\r
15358                 id: this.panel.id + '-xcollapsed'\r
15359             });\r
15360             this.collapsedEl.enableDisplayMode('block');\r
15361 \r
15362             if(this.collapseMode == 'mini'){\r
15363                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);\r
15364                 this.miniCollapsedEl = this.collapsedEl.createChild({\r
15365                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"\r
15366                 });\r
15367                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');\r
15368                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");\r
15369                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});\r
15370             }else {\r
15371                 var t = this.toolTemplate.append(\r
15372                         this.collapsedEl.dom,\r
15373                         {id:'expand-'+this.position}, true);\r
15374                 t.addClassOnOver('x-tool-expand-'+this.position+'-over');\r
15375                 t.on('click', this.onExpandClick, this, {stopEvent:true});\r
15376                 \r
15377                 if(this.floatable !== false){\r
15378                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");\r
15379                    this.collapsedEl.on("click", this.collapseClick, this);\r
15380                 }\r
15381             }\r
15382         }\r
15383         return this.collapsedEl;\r
15384     },\r
15385 \r
15386     // private\r
15387     onExpandClick : function(e){\r
15388         if(this.isSlid){\r
15389             this.afterSlideIn();\r
15390             this.panel.expand(false);\r
15391         }else{\r
15392             this.panel.expand();\r
15393         }\r
15394     },\r
15395 \r
15396     // private\r
15397     onCollapseClick : function(e){\r
15398         this.panel.collapse();\r
15399     },\r
15400 \r
15401     // private\r
15402     beforeCollapse : function(p, animate){\r
15403         this.lastAnim = animate;\r
15404         if(this.splitEl){\r
15405             this.splitEl.hide();\r
15406         }\r
15407         this.getCollapsedEl().show();\r
15408         this.panel.el.setStyle('z-index', 100);\r
15409         this.isCollapsed = true;\r
15410         this.layout.layout();\r
15411     },\r
15412 \r
15413     // private\r
15414     onCollapse : function(animate){\r
15415         this.panel.el.setStyle('z-index', 1);\r
15416         if(this.lastAnim === false || this.panel.animCollapse === false){\r
15417             this.getCollapsedEl().dom.style.visibility = 'visible';\r
15418         }else{\r
15419             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});\r
15420         }\r
15421         this.state.collapsed = true;\r
15422         this.panel.saveState();\r
15423     },\r
15424 \r
15425     // private\r
15426     beforeExpand : function(animate){\r
15427         var c = this.getCollapsedEl();\r
15428         this.el.show();\r
15429         if(this.position == 'east' || this.position == 'west'){\r
15430             this.panel.setSize(undefined, c.getHeight());\r
15431         }else{\r
15432             this.panel.setSize(c.getWidth(), undefined);\r
15433         }\r
15434         c.hide();\r
15435         c.dom.style.visibility = 'hidden';\r
15436         this.panel.el.setStyle('z-index', 100);\r
15437     },\r
15438 \r
15439     // private\r
15440     onExpand : function(){\r
15441         this.isCollapsed = false;\r
15442         if(this.splitEl){\r
15443             this.splitEl.show();\r
15444         }\r
15445         this.layout.layout();\r
15446         this.panel.el.setStyle('z-index', 1);\r
15447         this.state.collapsed = false;\r
15448         this.panel.saveState();\r
15449     },\r
15450 \r
15451     // private\r
15452     collapseClick : function(e){\r
15453         if(this.isSlid){\r
15454            e.stopPropagation();\r
15455            this.slideIn();\r
15456         }else{\r
15457            e.stopPropagation();\r
15458            this.slideOut();\r
15459         }\r
15460     },\r
15461 \r
15462     // private\r
15463     onHide : function(){\r
15464         if(this.isCollapsed){\r
15465             this.getCollapsedEl().hide();\r
15466         }else if(this.splitEl){\r
15467             this.splitEl.hide();\r
15468         }\r
15469     },\r
15470 \r
15471     // private\r
15472     onShow : function(){\r
15473         if(this.isCollapsed){\r
15474             this.getCollapsedEl().show();\r
15475         }else if(this.splitEl){\r
15476             this.splitEl.show();\r
15477         }\r
15478     },\r
15479 \r
15480     \r
15481     isVisible : function(){\r
15482         return !this.panel.hidden;\r
15483     },\r
15484 \r
15485     \r
15486     getMargins : function(){\r
15487         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;\r
15488     },\r
15489 \r
15490     \r
15491     getSize : function(){\r
15492         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();\r
15493     },\r
15494 \r
15495     \r
15496     setPanel : function(panel){\r
15497         this.panel = panel;\r
15498     },\r
15499 \r
15500     \r
15501     getMinWidth: function(){\r
15502         return this.minWidth;\r
15503     },\r
15504 \r
15505     \r
15506     getMinHeight: function(){\r
15507         return this.minHeight;\r
15508     },\r
15509 \r
15510     // private\r
15511     applyLayoutCollapsed : function(box){\r
15512         var ce = this.getCollapsedEl();\r
15513         ce.setLeftTop(box.x, box.y);\r
15514         ce.setSize(box.width, box.height);\r
15515     },\r
15516 \r
15517     // private\r
15518     applyLayout : function(box){\r
15519         if(this.isCollapsed){\r
15520             this.applyLayoutCollapsed(box);\r
15521         }else{\r
15522             this.panel.setPosition(box.x, box.y);\r
15523             this.panel.setSize(box.width, box.height);\r
15524         }\r
15525     },\r
15526 \r
15527     // private\r
15528     beforeSlide: function(){\r
15529         this.panel.beforeEffect();\r
15530     },\r
15531 \r
15532     // private\r
15533     afterSlide : function(){\r
15534         this.panel.afterEffect();\r
15535     },\r
15536 \r
15537     // private\r
15538     initAutoHide : function(){\r
15539         if(this.autoHide !== false){\r
15540             if(!this.autoHideHd){\r
15541                 var st = new Ext.util.DelayedTask(this.slideIn, this);\r
15542                 this.autoHideHd = {\r
15543                     "mouseout": function(e){\r
15544                         if(!e.within(this.el, true)){\r
15545                             st.delay(500);\r
15546                         }\r
15547                     },\r
15548                     "mouseover" : function(e){\r
15549                         st.cancel();\r
15550                     },\r
15551                     scope : this\r
15552                 };\r
15553             }\r
15554             this.el.on(this.autoHideHd);\r
15555         }\r
15556     },\r
15557 \r
15558     // private\r
15559     clearAutoHide : function(){\r
15560         if(this.autoHide !== false){\r
15561             this.el.un("mouseout", this.autoHideHd.mouseout);\r
15562             this.el.un("mouseover", this.autoHideHd.mouseover);\r
15563         }\r
15564     },\r
15565 \r
15566     // private\r
15567     clearMonitor : function(){\r
15568         Ext.getDoc().un("click", this.slideInIf, this);\r
15569     },\r
15570 \r
15571     // these names are backwards but not changed for compat\r
15572     // private\r
15573     slideOut : function(){\r
15574         if(this.isSlid || this.el.hasActiveFx()){\r
15575             return;\r
15576         }\r
15577         this.isSlid = true;\r
15578         var ts = this.panel.tools;\r
15579         if(ts && ts.toggle){\r
15580             ts.toggle.hide();\r
15581         }\r
15582         this.el.show();\r
15583         if(this.position == 'east' || this.position == 'west'){\r
15584             this.panel.setSize(undefined, this.collapsedEl.getHeight());\r
15585         }else{\r
15586             this.panel.setSize(this.collapsedEl.getWidth(), undefined);\r
15587         }\r
15588         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];\r
15589         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());\r
15590         this.el.setStyle("z-index", 102);\r
15591         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');\r
15592         if(this.animFloat !== false){\r
15593             this.beforeSlide();\r
15594             this.el.slideIn(this.getSlideAnchor(), {\r
15595                 callback: function(){\r
15596                     this.afterSlide();\r
15597                     this.initAutoHide();\r
15598                     Ext.getDoc().on("click", this.slideInIf, this);\r
15599                 },\r
15600                 scope: this,\r
15601                 block: true\r
15602             });\r
15603         }else{\r
15604             this.initAutoHide();\r
15605              Ext.getDoc().on("click", this.slideInIf, this);\r
15606         }\r
15607     },\r
15608 \r
15609     // private\r
15610     afterSlideIn : function(){\r
15611         this.clearAutoHide();\r
15612         this.isSlid = false;\r
15613         this.clearMonitor();\r
15614         this.el.setStyle("z-index", "");\r
15615         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');\r
15616         this.el.dom.style.left = this.restoreLT[0];\r
15617         this.el.dom.style.top = this.restoreLT[1];\r
15618 \r
15619         var ts = this.panel.tools;\r
15620         if(ts && ts.toggle){\r
15621             ts.toggle.show();\r
15622         }\r
15623     },\r
15624 \r
15625     // private\r
15626     slideIn : function(cb){\r
15627         if(!this.isSlid || this.el.hasActiveFx()){\r
15628             Ext.callback(cb);\r
15629             return;\r
15630         }\r
15631         this.isSlid = false;\r
15632         if(this.animFloat !== false){\r
15633             this.beforeSlide();\r
15634             this.el.slideOut(this.getSlideAnchor(), {\r
15635                 callback: function(){\r
15636                     this.el.hide();\r
15637                     this.afterSlide();\r
15638                     this.afterSlideIn();\r
15639                     Ext.callback(cb);\r
15640                 },\r
15641                 scope: this,\r
15642                 block: true\r
15643             });\r
15644         }else{\r
15645             this.el.hide();\r
15646             this.afterSlideIn();\r
15647         }\r
15648     },\r
15649 \r
15650     // private\r
15651     slideInIf : function(e){\r
15652         if(!e.within(this.el)){\r
15653             this.slideIn();\r
15654         }\r
15655     },\r
15656 \r
15657     // private\r
15658     anchors : {\r
15659         "west" : "left",\r
15660         "east" : "right",\r
15661         "north" : "top",\r
15662         "south" : "bottom"\r
15663     },\r
15664 \r
15665     // private\r
15666     sanchors : {\r
15667         "west" : "l",\r
15668         "east" : "r",\r
15669         "north" : "t",\r
15670         "south" : "b"\r
15671     },\r
15672 \r
15673     // private\r
15674     canchors : {\r
15675         "west" : "tl-tr",\r
15676         "east" : "tr-tl",\r
15677         "north" : "tl-bl",\r
15678         "south" : "bl-tl"\r
15679     },\r
15680 \r
15681     // private\r
15682     getAnchor : function(){\r
15683         return this.anchors[this.position];\r
15684     },\r
15685 \r
15686     // private\r
15687     getCollapseAnchor : function(){\r
15688         return this.canchors[this.position];\r
15689     },\r
15690 \r
15691     // private\r
15692     getSlideAnchor : function(){\r
15693         return this.sanchors[this.position];\r
15694     },\r
15695 \r
15696     // private\r
15697     getAlignAdj : function(){\r
15698         var cm = this.cmargins;\r
15699         switch(this.position){\r
15700             case "west":\r
15701                 return [0, 0];\r
15702             break;\r
15703             case "east":\r
15704                 return [0, 0];\r
15705             break;\r
15706             case "north":\r
15707                 return [0, 0];\r
15708             break;\r
15709             case "south":\r
15710                 return [0, 0];\r
15711             break;\r
15712         }\r
15713     },\r
15714 \r
15715     // private\r
15716     getExpandAdj : function(){\r
15717         var c = this.collapsedEl, cm = this.cmargins;\r
15718         switch(this.position){\r
15719             case "west":\r
15720                 return [-(cm.right+c.getWidth()+cm.left), 0];\r
15721             break;\r
15722             case "east":\r
15723                 return [cm.right+c.getWidth()+cm.left, 0];\r
15724             break;\r
15725             case "north":\r
15726                 return [0, -(cm.top+cm.bottom+c.getHeight())];\r
15727             break;\r
15728             case "south":\r
15729                 return [0, cm.top+cm.bottom+c.getHeight()];\r
15730             break;\r
15731         }\r
15732     }\r
15733 };\r
15734 \r
15735 \r
15736 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){\r
15737     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);\r
15738     // prevent switch\r
15739     this.applyLayout = this.applyFns[pos];\r
15740 };\r
15741 \r
15742 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {\r
15743     \r
15744     splitTip : "Drag to resize.",\r
15745     \r
15746     collapsibleSplitTip : "Drag to resize. Double click to hide.",\r
15747     \r
15748     useSplitTips : false,\r
15749 \r
15750     // private\r
15751     splitSettings : {\r
15752         north : {\r
15753             orientation: Ext.SplitBar.VERTICAL,\r
15754             placement: Ext.SplitBar.TOP,\r
15755             maxFn : 'getVMaxSize',\r
15756             minProp: 'minHeight',\r
15757             maxProp: 'maxHeight'\r
15758         },\r
15759         south : {\r
15760             orientation: Ext.SplitBar.VERTICAL,\r
15761             placement: Ext.SplitBar.BOTTOM,\r
15762             maxFn : 'getVMaxSize',\r
15763             minProp: 'minHeight',\r
15764             maxProp: 'maxHeight'\r
15765         },\r
15766         east : {\r
15767             orientation: Ext.SplitBar.HORIZONTAL,\r
15768             placement: Ext.SplitBar.RIGHT,\r
15769             maxFn : 'getHMaxSize',\r
15770             minProp: 'minWidth',\r
15771             maxProp: 'maxWidth'\r
15772         },\r
15773         west : {\r
15774             orientation: Ext.SplitBar.HORIZONTAL,\r
15775             placement: Ext.SplitBar.LEFT,\r
15776             maxFn : 'getHMaxSize',\r
15777             minProp: 'minWidth',\r
15778             maxProp: 'maxWidth'\r
15779         }\r
15780     },\r
15781 \r
15782     // private\r
15783     applyFns : {\r
15784         west : function(box){\r
15785             if(this.isCollapsed){\r
15786                 return this.applyLayoutCollapsed(box);\r
15787             }\r
15788             var sd = this.splitEl.dom, s = sd.style;\r
15789             this.panel.setPosition(box.x, box.y);\r
15790             var sw = sd.offsetWidth;\r
15791             s.left = (box.x+box.width-sw)+'px';\r
15792             s.top = (box.y)+'px';\r
15793             s.height = Math.max(0, box.height)+'px';\r
15794             this.panel.setSize(box.width-sw, box.height);\r
15795         },\r
15796         east : function(box){\r
15797             if(this.isCollapsed){\r
15798                 return this.applyLayoutCollapsed(box);\r
15799             }\r
15800             var sd = this.splitEl.dom, s = sd.style;\r
15801             var sw = sd.offsetWidth;\r
15802             this.panel.setPosition(box.x+sw, box.y);\r
15803             s.left = (box.x)+'px';\r
15804             s.top = (box.y)+'px';\r
15805             s.height = Math.max(0, box.height)+'px';\r
15806             this.panel.setSize(box.width-sw, box.height);\r
15807         },\r
15808         north : function(box){\r
15809             if(this.isCollapsed){\r
15810                 return this.applyLayoutCollapsed(box);\r
15811             }\r
15812             var sd = this.splitEl.dom, s = sd.style;\r
15813             var sh = sd.offsetHeight;\r
15814             this.panel.setPosition(box.x, box.y);\r
15815             s.left = (box.x)+'px';\r
15816             s.top = (box.y+box.height-sh)+'px';\r
15817             s.width = Math.max(0, box.width)+'px';\r
15818             this.panel.setSize(box.width, box.height-sh);\r
15819         },\r
15820         south : function(box){\r
15821             if(this.isCollapsed){\r
15822                 return this.applyLayoutCollapsed(box);\r
15823             }\r
15824             var sd = this.splitEl.dom, s = sd.style;\r
15825             var sh = sd.offsetHeight;\r
15826             this.panel.setPosition(box.x, box.y+sh);\r
15827             s.left = (box.x)+'px';\r
15828             s.top = (box.y)+'px';\r
15829             s.width = Math.max(0, box.width)+'px';\r
15830             this.panel.setSize(box.width, box.height-sh);\r
15831         }\r
15832     },\r
15833 \r
15834     // private\r
15835     render : function(ct, p){\r
15836         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);\r
15837 \r
15838         var ps = this.position;\r
15839 \r
15840         this.splitEl = ct.createChild({\r
15841             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",\r
15842             id: this.panel.id + '-xsplit'\r
15843         });\r
15844 \r
15845         if(this.collapseMode == 'mini'){\r
15846             this.miniSplitEl = this.splitEl.createChild({\r
15847                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"\r
15848             });\r
15849             this.miniSplitEl.addClassOnOver('x-layout-mini-over');\r
15850             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});\r
15851         }\r
15852 \r
15853         var s = this.splitSettings[ps];\r
15854 \r
15855         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);\r
15856         this.split.placement = s.placement;\r
15857         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);\r
15858         this.split.minSize = this.minSize || this[s.minProp];\r
15859         this.split.on("beforeapply", this.onSplitMove, this);\r
15860         this.split.useShim = this.useShim === true;\r
15861         this.maxSize = this.maxSize || this[s.maxProp];\r
15862 \r
15863         if(p.hidden){\r
15864             this.splitEl.hide();\r
15865         }\r
15866 \r
15867         if(this.useSplitTips){\r
15868             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;\r
15869         }\r
15870         if(this.collapsible){\r
15871             this.splitEl.on("dblclick", this.onCollapseClick,  this);\r
15872         }\r
15873     },\r
15874 \r
15875     //docs inherit from superclass\r
15876     getSize : function(){\r
15877         if(this.isCollapsed){\r
15878             return this.collapsedEl.getSize();\r
15879         }\r
15880         var s = this.panel.getSize();\r
15881         if(this.position == 'north' || this.position == 'south'){\r
15882             s.height += this.splitEl.dom.offsetHeight;\r
15883         }else{\r
15884             s.width += this.splitEl.dom.offsetWidth;\r
15885         }\r
15886         return s;\r
15887     },\r
15888 \r
15889     // private\r
15890     getHMaxSize : function(){\r
15891          var cmax = this.maxSize || 10000;\r
15892          var center = this.layout.center;\r
15893          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());\r
15894     },\r
15895 \r
15896     // private\r
15897     getVMaxSize : function(){\r
15898         var cmax = this.maxSize || 10000;\r
15899         var center = this.layout.center;\r
15900         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());\r
15901     },\r
15902 \r
15903     // private\r
15904     onSplitMove : function(split, newSize){\r
15905         var s = this.panel.getSize();\r
15906         this.lastSplitSize = newSize;\r
15907         if(this.position == 'north' || this.position == 'south'){\r
15908             this.panel.setSize(s.width, newSize);\r
15909             this.state.height = newSize;\r
15910         }else{\r
15911             this.panel.setSize(newSize, s.height);\r
15912             this.state.width = newSize;\r
15913         }\r
15914         this.layout.layout();\r
15915         this.panel.saveState();\r
15916         return false;\r
15917     },\r
15918 \r
15919     \r
15920     getSplitBar : function(){\r
15921         return this.split;\r
15922     },\r
15923     \r
15924     // inherit docs\r
15925     destroy : function() {\r
15926         Ext.destroy(\r
15927             this.miniSplitEl, \r
15928             this.split, \r
15929             this.splitEl\r
15930         );\r
15931     }\r
15932 });\r
15933 \r
15934 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;\r
15935 \r
15936 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
15937     \r
15938     labelSeparator : ':',\r
15939 \r
15940     // private\r
15941     getAnchorViewSize : function(ct, target){\r
15942         return (ct.body||ct.el).getStyleSize();\r
15943     },\r
15944 \r
15945     // private\r
15946     setContainer : function(ct){\r
15947         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);\r
15948 \r
15949         if(ct.labelAlign){\r
15950             ct.addClass('x-form-label-'+ct.labelAlign);\r
15951         }\r
15952 \r
15953         if(ct.hideLabels){\r
15954             this.labelStyle = "display:none";\r
15955             this.elementStyle = "padding-left:0;";\r
15956             this.labelAdjust = 0;\r
15957         }else{\r
15958             this.labelSeparator = ct.labelSeparator || this.labelSeparator;\r
15959             ct.labelWidth = ct.labelWidth || 100;\r
15960             if(typeof ct.labelWidth == 'number'){\r
15961                 var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);\r
15962                 this.labelAdjust = ct.labelWidth+pad;\r
15963                 this.labelStyle = "width:"+ct.labelWidth+"px;";\r
15964                 this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';\r
15965             }\r
15966             if(ct.labelAlign == 'top'){\r
15967                 this.labelStyle = "width:auto;";\r
15968                 this.labelAdjust = 0;\r
15969                 this.elementStyle = "padding-left:0;";\r
15970             }\r
15971         }\r
15972 \r
15973         if(!this.fieldTpl){\r
15974             // the default field template used by all form layouts\r
15975             var t = new Ext.Template(\r
15976                 '<div class="x-form-item {5}" tabIndex="-1">',\r
15977                     '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',\r
15978                     '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',\r
15979                     '</div><div class="{6}"></div>',\r
15980                 '</div>'\r
15981             );\r
15982             t.disableFormats = true;\r
15983             t.compile();\r
15984             Ext.layout.FormLayout.prototype.fieldTpl = t;\r
15985         }\r
15986     },\r
15987     \r
15988     //private\r
15989     getLabelStyle: function(s){\r
15990         var ls = '', items = [this.labelStyle, s];\r
15991         for (var i = 0, len = items.length; i < len; ++i){\r
15992             if (items[i]){\r
15993                 ls += items[i];\r
15994                 if (ls.substr(-1, 1) != ';'){\r
15995                     ls += ';'\r
15996                 }\r
15997             }\r
15998         }\r
15999         return ls;\r
16000     },\r
16001 \r
16002     // private\r
16003     renderItem : function(c, position, target){\r
16004         if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){\r
16005             var args = [\r
16006                    c.id, c.fieldLabel,\r
16007                    this.getLabelStyle(c.labelStyle),\r
16008                    this.elementStyle||'',\r
16009                    typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,\r
16010                    (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),\r
16011                    c.clearCls || 'x-form-clear-left' \r
16012             ];\r
16013             if(typeof position == 'number'){\r
16014                 position = target.dom.childNodes[position] || null;\r
16015             }\r
16016             if(position){\r
16017                 this.fieldTpl.insertBefore(position, args);\r
16018             }else{\r
16019                 this.fieldTpl.append(target, args);\r
16020             }\r
16021             c.render('x-form-el-'+c.id);\r
16022         }else {\r
16023             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);\r
16024         }\r
16025     },\r
16026 \r
16027     // private\r
16028     adjustWidthAnchor : function(value, comp){\r
16029         return value - (comp.isFormField  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);\r
16030     },\r
16031 \r
16032     // private\r
16033     isValidParent : function(c, target){\r
16034         return true;\r
16035     }\r
16036 \r
16037     \r
16038 });\r
16039 \r
16040 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;\r
16041 \r
16042 Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {\r
16043     \r
16044     fill : true,\r
16045     \r
16046     autoWidth : true,\r
16047     \r
16048     titleCollapse : true,\r
16049     \r
16050     hideCollapseTool : false,\r
16051     \r
16052     collapseFirst : false,\r
16053     \r
16054     animate : false,\r
16055     \r
16056     sequence : false,\r
16057     \r
16058     activeOnTop : false,\r
16059 \r
16060     renderItem : function(c){\r
16061         if(this.animate === false){\r
16062             c.animCollapse = false;\r
16063         }\r
16064         c.collapsible = true;\r
16065         if(this.autoWidth){\r
16066             c.autoWidth = true;\r
16067         }\r
16068         if(this.titleCollapse){\r
16069             c.titleCollapse = true;\r
16070         }\r
16071         if(this.hideCollapseTool){\r
16072             c.hideCollapseTool = true;\r
16073         }\r
16074         if(this.collapseFirst !== undefined){\r
16075             c.collapseFirst = this.collapseFirst;\r
16076         }\r
16077         if(!this.activeItem && !c.collapsed){\r
16078             this.activeItem = c;\r
16079         }else if(this.activeItem){\r
16080             c.collapsed = true;\r
16081         }\r
16082         Ext.layout.Accordion.superclass.renderItem.apply(this, arguments);\r
16083         c.header.addClass('x-accordion-hd');\r
16084         c.on('beforeexpand', this.beforeExpand, this);\r
16085     },\r
16086 \r
16087     // private\r
16088     beforeExpand : function(p, anim){\r
16089         var ai = this.activeItem;\r
16090         if(ai){\r
16091             if(this.sequence){\r
16092                 delete this.activeItem;\r
16093                 if (!ai.collapsed){\r
16094                     ai.collapse({callback:function(){\r
16095                         p.expand(anim || true);\r
16096                     }, scope: this});\r
16097                     return false;\r
16098                 }\r
16099             }else{\r
16100                 ai.collapse(this.animate);\r
16101             }\r
16102         }\r
16103         this.activeItem = p;\r
16104         if(this.activeOnTop){\r
16105             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
16106         }\r
16107         this.layout();\r
16108     },\r
16109 \r
16110     // private\r
16111     setItemSize : function(item, size){\r
16112         if(this.fill && item){\r
16113             var items = this.container.items.items;\r
16114             var hh = 0;\r
16115             for(var i = 0, len = items.length; i < len; i++){\r
16116                 var p = items[i];\r
16117                 if(p != item){\r
16118                     hh += (p.getSize().height - p.bwrap.getHeight());\r
16119                 }\r
16120             }\r
16121             size.height -= hh;\r
16122             item.setSize(size);\r
16123         }\r
16124     }\r
16125 });\r
16126 Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;\r
16127 \r
16128 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
16129     \r
16130 \r
16131     // private\r
16132     monitorResize:false,\r
16133 \r
16134     // private\r
16135     setContainer : function(ct){\r
16136         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
16137 \r
16138         this.currentRow = 0;\r
16139         this.currentColumn = 0;\r
16140         this.cells = [];\r
16141     },\r
16142 \r
16143     // private\r
16144     onLayout : function(ct, target){\r
16145         var cs = ct.items.items, len = cs.length, c, i;\r
16146 \r
16147         if(!this.table){\r
16148             target.addClass('x-table-layout-ct');\r
16149 \r
16150             this.table = target.createChild(\r
16151                 {tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, null, true);\r
16152 \r
16153             this.renderAll(ct, target);\r
16154         }\r
16155     },\r
16156 \r
16157     // private\r
16158     getRow : function(index){\r
16159         var row = this.table.tBodies[0].childNodes[index];\r
16160         if(!row){\r
16161             row = document.createElement('tr');\r
16162             this.table.tBodies[0].appendChild(row);\r
16163         }\r
16164         return row;\r
16165     },\r
16166 \r
16167     // private\r
16168         getNextCell : function(c){\r
16169                 var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
16170                 var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
16171                 for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
16172                         if(!this.cells[rowIndex]){\r
16173                                 this.cells[rowIndex] = [];\r
16174                         }\r
16175                         for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
16176                                 this.cells[rowIndex][colIndex] = true;\r
16177                         }\r
16178                 }\r
16179                 var td = document.createElement('td');\r
16180                 if(c.cellId){\r
16181                         td.id = c.cellId;\r
16182                 }\r
16183                 var cls = 'x-table-layout-cell';\r
16184                 if(c.cellCls){\r
16185                         cls += ' ' + c.cellCls;\r
16186                 }\r
16187                 td.className = cls;\r
16188                 if(c.colspan){\r
16189                         td.colSpan = c.colspan;\r
16190                 }\r
16191                 if(c.rowspan){\r
16192                         td.rowSpan = c.rowspan;\r
16193                 }\r
16194                 this.getRow(curRow).appendChild(td);\r
16195                 return td;\r
16196         },\r
16197     \r
16198     // private\r
16199         getNextNonSpan: function(colIndex, rowIndex){\r
16200                 var cols = this.columns;\r
16201                 while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
16202                         if(cols && colIndex >= cols){\r
16203                                 rowIndex++;\r
16204                                 colIndex = 0;\r
16205                         }else{\r
16206                                 colIndex++;\r
16207                         }\r
16208                 }\r
16209                 return [colIndex, rowIndex];\r
16210         },\r
16211 \r
16212     // private\r
16213     renderItem : function(c, position, target){\r
16214         if(c && !c.rendered){\r
16215             c.render(this.getNextCell(c));\r
16216             if(this.extraCls){\r
16217                 var t = c.getPositionEl ? c.getPositionEl() : c;\r
16218                 t.addClass(this.extraCls);\r
16219             }\r
16220         }\r
16221     },\r
16222 \r
16223     // private\r
16224     isValidParent : function(c, target){\r
16225         return true;\r
16226     }\r
16227 \r
16228     \r
16229 });\r
16230 \r
16231 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;\r
16232 \r
16233 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
16234     \r
16235     extraCls: 'x-abs-layout-item',\r
16236     isForm: false,\r
16237     // private\r
16238     setContainer : function(ct){\r
16239         Ext.layout.AbsoluteLayout.superclass.setContainer.call(this, ct);\r
16240         if(ct.isXType('form')){\r
16241             this.isForm = true;\r
16242         }\r
16243     },\r
16244 \r
16245     onLayout : function(ct, target){\r
16246         if(this.isForm){ ct.body.position(); } else { target.position(); }\r
16247         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
16248     },\r
16249 \r
16250     // private\r
16251     getAnchorViewSize : function(ct, target){\r
16252         return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);\r
16253     },\r
16254 \r
16255     // private\r
16256     isValidParent : function(c, target){\r
16257         return this.isForm ? true : Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);\r
16258     },\r
16259 \r
16260     // private\r
16261     adjustWidthAnchor : function(value, comp){\r
16262         return value ? value - comp.getPosition(true)[0] : value;\r
16263     },\r
16264 \r
16265     // private\r
16266     adjustHeightAnchor : function(value, comp){\r
16267         return  value ? value - comp.getPosition(true)[1] : value;\r
16268     }\r
16269     \r
16270 });\r
16271 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;\r
16272 \r
16273 Ext.Viewport = Ext.extend(Ext.Container, {\r
16274         \r
16275     \r
16276     \r
16277     \r
16278     \r
16279     \r
16280     \r
16281     \r
16282     \r
16283     \r
16284     \r
16285     \r
16286     initComponent : function() {\r
16287         Ext.Viewport.superclass.initComponent.call(this);\r
16288         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
16289         this.el = Ext.getBody();\r
16290         this.el.setHeight = Ext.emptyFn;\r
16291         this.el.setWidth = Ext.emptyFn;\r
16292         this.el.setSize = Ext.emptyFn;\r
16293         this.el.dom.scroll = 'no';\r
16294         this.allowDomMove = false;\r
16295         this.autoWidth = true;\r
16296         this.autoHeight = true;\r
16297         Ext.EventManager.onWindowResize(this.fireResize, this);\r
16298         this.renderTo = this.el;\r
16299     },\r
16300 \r
16301     fireResize : function(w, h){\r
16302         this.fireEvent('resize', this, w, h, w, h);\r
16303     }\r
16304 });\r
16305 Ext.reg('viewport', Ext.Viewport);\r
16306 \r
16307 Ext.Panel = Ext.extend(Ext.Container, {\r
16308     \r
16309     \r
16310     \r
16311     \r
16312     \r
16313     \r
16314     \r
16315     \r
16316     \r
16317     \r
16318     \r
16319     \r
16320     \r
16321     \r
16322     \r
16323     \r
16324     \r
16325     \r
16326     \r
16327     \r
16328     \r
16329     \r
16330     \r
16331     \r
16332     \r
16333     \r
16334     \r
16335     \r
16336     \r
16337      \r
16338     \r
16339     \r
16340     \r
16341     \r
16342 \r
16343     \r
16344     baseCls : 'x-panel',\r
16345     \r
16346     collapsedCls : 'x-panel-collapsed',\r
16347     \r
16348     maskDisabled: true,\r
16349     \r
16350     animCollapse: Ext.enableFx,\r
16351     \r
16352     headerAsText: true,\r
16353     \r
16354     buttonAlign: 'right',\r
16355     \r
16356     collapsed : false,\r
16357     \r
16358     collapseFirst: true,\r
16359     \r
16360     minButtonWidth:75,\r
16361     \r
16362     elements : 'body',\r
16363 \r
16364     // protected - these could be used to customize the behavior of the window,\r
16365     // but changing them would not be useful without further mofifications and\r
16366     // could lead to unexpected or undesirable results.\r
16367     toolTarget : 'header',\r
16368     collapseEl : 'bwrap',\r
16369     slideAnchor : 't',\r
16370     disabledClass: '',\r
16371 \r
16372     // private, notify box this class will handle heights\r
16373     deferHeight: true,\r
16374     // private\r
16375     expandDefaults: {\r
16376         duration:.25\r
16377     },\r
16378     // private\r
16379     collapseDefaults: {\r
16380         duration:.25\r
16381     },\r
16382 \r
16383     // private\r
16384     initComponent : function(){\r
16385         Ext.Panel.superclass.initComponent.call(this);\r
16386 \r
16387         this.addEvents(\r
16388             \r
16389             'bodyresize',\r
16390             \r
16391             'titlechange',\r
16392             \r
16393             'iconchange',\r
16394             \r
16395             'collapse',\r
16396             \r
16397             'expand',\r
16398             \r
16399             'beforecollapse',\r
16400             \r
16401             'beforeexpand',\r
16402             \r
16403             'beforeclose',\r
16404             \r
16405             'close',\r
16406             \r
16407             'activate',\r
16408             \r
16409             'deactivate'\r
16410         );\r
16411 \r
16412         // shortcuts\r
16413         if(this.tbar){\r
16414             this.elements += ',tbar';\r
16415             if(typeof this.tbar == 'object'){\r
16416                 this.topToolbar = this.tbar;\r
16417             }\r
16418             delete this.tbar;\r
16419         }\r
16420         if(this.bbar){\r
16421             this.elements += ',bbar';\r
16422             if(typeof this.bbar == 'object'){\r
16423                 this.bottomToolbar = this.bbar;\r
16424             }\r
16425             delete this.bbar;\r
16426         }\r
16427 \r
16428         if(this.header === true){\r
16429             this.elements += ',header';\r
16430             delete this.header;\r
16431         }else if(this.title && this.header !== false){\r
16432             this.elements += ',header';\r
16433         }\r
16434 \r
16435         if(this.footer === true){\r
16436             this.elements += ',footer';\r
16437             delete this.footer;\r
16438         }\r
16439 \r
16440         if(this.buttons){\r
16441             var btns = this.buttons;\r
16442             \r
16443             this.buttons = [];\r
16444             for(var i = 0, len = btns.length; i < len; i++) {\r
16445                 if(btns[i].render){ // button instance\r
16446                     btns[i].ownerCt = this;\r
16447                     this.buttons.push(btns[i]);\r
16448                 }else{\r
16449                     this.addButton(btns[i]);\r
16450                 }\r
16451             }\r
16452         }\r
16453         if(this.autoLoad){\r
16454             this.on('render', this.doAutoLoad, this, {delay:10});\r
16455         }\r
16456     },\r
16457 \r
16458     // private\r
16459     createElement : function(name, pnode){\r
16460         if(this[name]){\r
16461             pnode.appendChild(this[name].dom);\r
16462             return;\r
16463         }\r
16464 \r
16465         if(name === 'bwrap' || this.elements.indexOf(name) != -1){\r
16466             if(this[name+'Cfg']){\r
16467                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);\r
16468             }else{\r
16469                 var el = document.createElement('div');\r
16470                 el.className = this[name+'Cls'];\r
16471                 this[name] = Ext.get(pnode.appendChild(el));\r
16472             }\r
16473             if(this[name+'CssClass']){\r
16474                 this[name].addClass(this[name+'CssClass']);\r
16475             }\r
16476             if(this[name+'Style']){\r
16477                 this[name].applyStyles(this[name+'Style']);\r
16478             }\r
16479         }\r
16480     },\r
16481 \r
16482     // private\r
16483     onRender : function(ct, position){\r
16484         Ext.Panel.superclass.onRender.call(this, ct, position);\r
16485 \r
16486         this.createClasses();\r
16487 \r
16488         if(this.el){ // existing markup\r
16489             this.el.addClass(this.baseCls);\r
16490             this.header = this.el.down('.'+this.headerCls);\r
16491             this.bwrap = this.el.down('.'+this.bwrapCls);\r
16492             var cp = this.bwrap ? this.bwrap : this.el;\r
16493             this.tbar = cp.down('.'+this.tbarCls);\r
16494             this.body = cp.down('.'+this.bodyCls);\r
16495             this.bbar = cp.down('.'+this.bbarCls);\r
16496             this.footer = cp.down('.'+this.footerCls);\r
16497             this.fromMarkup = true;\r
16498         }else{\r
16499             this.el = ct.createChild({\r
16500                 id: this.id,\r
16501                 cls: this.baseCls\r
16502             }, position);\r
16503         }\r
16504         var el = this.el, d = el.dom;\r
16505 \r
16506         if(this.cls){\r
16507             this.el.addClass(this.cls);\r
16508         }\r
16509 \r
16510         if(this.buttons){\r
16511             this.elements += ',footer';\r
16512         }\r
16513 \r
16514         // This block allows for maximum flexibility and performance when using existing markup\r
16515 \r
16516         // framing requires special markup\r
16517         if(this.frame){\r
16518             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));\r
16519 \r
16520             this.createElement('header', d.firstChild.firstChild.firstChild);\r
16521             this.createElement('bwrap', d);\r
16522 \r
16523             // append the mid and bottom frame to the bwrap\r
16524             var bw = this.bwrap.dom;\r
16525             var ml = d.childNodes[1], bl = d.childNodes[2];\r
16526             bw.appendChild(ml);\r
16527             bw.appendChild(bl);\r
16528 \r
16529             var mc = bw.firstChild.firstChild.firstChild;\r
16530             this.createElement('tbar', mc);\r
16531             this.createElement('body', mc);\r
16532             this.createElement('bbar', mc);\r
16533             this.createElement('footer', bw.lastChild.firstChild.firstChild);\r
16534 \r
16535             if(!this.footer){\r
16536                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';\r
16537             }\r
16538         }else{\r
16539             this.createElement('header', d);\r
16540             this.createElement('bwrap', d);\r
16541 \r
16542             // append the mid and bottom frame to the bwrap\r
16543             var bw = this.bwrap.dom;\r
16544             this.createElement('tbar', bw);\r
16545             this.createElement('body', bw);\r
16546             this.createElement('bbar', bw);\r
16547             this.createElement('footer', bw);\r
16548 \r
16549             if(!this.header){\r
16550                 this.body.addClass(this.bodyCls + '-noheader');\r
16551                 if(this.tbar){\r
16552                     this.tbar.addClass(this.tbarCls + '-noheader');\r
16553                 }\r
16554             }\r
16555         }\r
16556 \r
16557         if(this.border === false){\r
16558             this.el.addClass(this.baseCls + '-noborder');\r
16559             this.body.addClass(this.bodyCls + '-noborder');\r
16560             if(this.header){\r
16561                 this.header.addClass(this.headerCls + '-noborder');\r
16562             }\r
16563             if(this.footer){\r
16564                 this.footer.addClass(this.footerCls + '-noborder');\r
16565             }\r
16566             if(this.tbar){\r
16567                 this.tbar.addClass(this.tbarCls + '-noborder');\r
16568             }\r
16569             if(this.bbar){\r
16570                 this.bbar.addClass(this.bbarCls + '-noborder');\r
16571             }\r
16572         }\r
16573 \r
16574         if(this.bodyBorder === false){\r
16575            this.body.addClass(this.bodyCls + '-noborder');\r
16576         }\r
16577 \r
16578         this.bwrap.enableDisplayMode('block');\r
16579 \r
16580         if(this.header){\r
16581             this.header.unselectable();\r
16582 \r
16583             // for tools, we need to wrap any existing header markup\r
16584             if(this.headerAsText){\r
16585                 this.header.dom.innerHTML =\r
16586                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';\r
16587 \r
16588                 if(this.iconCls){\r
16589                     this.setIconClass(this.iconCls);\r
16590                 }\r
16591             }\r
16592         }\r
16593 \r
16594         if(this.floating){\r
16595             this.makeFloating(this.floating);\r
16596         }\r
16597 \r
16598         if(this.collapsible){\r
16599             this.tools = this.tools ? this.tools.slice(0) : [];\r
16600             if(!this.hideCollapseTool){\r
16601                 this.tools[this.collapseFirst?'unshift':'push']({\r
16602                     id: 'toggle',\r
16603                     handler : this.toggleCollapse,\r
16604                     scope: this\r
16605                 });\r
16606             }\r
16607             if(this.titleCollapse && this.header){\r
16608                 this.header.on('click', this.toggleCollapse, this);\r
16609                 this.header.setStyle('cursor', 'pointer');\r
16610             }\r
16611         }\r
16612         if(this.tools){\r
16613             var ts = this.tools;\r
16614             this.tools = {};\r
16615             this.addTool.apply(this, ts);\r
16616         }else{\r
16617             this.tools = {};\r
16618         }\r
16619 \r
16620         if(this.buttons && this.buttons.length > 0){\r
16621             // tables are required to maintain order and for correct IE layout\r
16622             var tb = this.footer.createChild({cls:'x-panel-btns-ct', cn: {\r
16623                 cls:"x-panel-btns x-panel-btns-"+this.buttonAlign,\r
16624                 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'\r
16625             }}, null, true);\r
16626             var tr = tb.getElementsByTagName('tr')[0];\r
16627             for(var i = 0, len = this.buttons.length; i < len; i++) {\r
16628                 var b = this.buttons[i];\r
16629                 var td = document.createElement('td');\r
16630                 td.className = 'x-panel-btn-td';\r
16631                 b.render(tr.appendChild(td));\r
16632             }\r
16633         }\r
16634 \r
16635         if(this.tbar && this.topToolbar){\r
16636             if(Ext.isArray(this.topToolbar)){\r
16637                 this.topToolbar = new Ext.Toolbar(this.topToolbar);\r
16638             }\r
16639             this.topToolbar.render(this.tbar);\r
16640             this.topToolbar.ownerCt = this;\r
16641         }\r
16642         if(this.bbar && this.bottomToolbar){\r
16643             if(Ext.isArray(this.bottomToolbar)){\r
16644                 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);\r
16645             }\r
16646             this.bottomToolbar.render(this.bbar);\r
16647             this.bottomToolbar.ownerCt = this;\r
16648         }\r
16649     },\r
16650 \r
16651     \r
16652     setIconClass : function(cls){\r
16653         var old = this.iconCls;\r
16654         this.iconCls = cls;\r
16655         if(this.rendered && this.header){\r
16656             if(this.frame){\r
16657                 this.header.addClass('x-panel-icon');\r
16658                 this.header.replaceClass(old, this.iconCls);\r
16659             }else{\r
16660                 var hd = this.header.dom;\r
16661                 var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;\r
16662                 if(img){\r
16663                     Ext.fly(img).replaceClass(old, this.iconCls);\r
16664                 }else{\r
16665                     Ext.DomHelper.insertBefore(hd.firstChild, {\r
16666                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls\r
16667                     });\r
16668                  }\r
16669             }\r
16670         }\r
16671         this.fireEvent('iconchange', this, cls, old);\r
16672     },\r
16673 \r
16674     // private\r
16675     makeFloating : function(cfg){\r
16676         this.floating = true;\r
16677         this.el = new Ext.Layer(\r
16678             typeof cfg == 'object' ? cfg : {\r
16679                 shadow: this.shadow !== undefined ? this.shadow : 'sides',\r
16680                 shadowOffset: this.shadowOffset,\r
16681                 constrain:false,\r
16682                 shim: this.shim === false ? false : undefined\r
16683             }, this.el\r
16684         );\r
16685     },\r
16686 \r
16687     \r
16688     getTopToolbar : function(){\r
16689         return this.topToolbar;\r
16690     },\r
16691 \r
16692     \r
16693     getBottomToolbar : function(){\r
16694         return this.bottomToolbar;\r
16695     },\r
16696 \r
16697     \r
16698     addButton : function(config, handler, scope){\r
16699         var bc = {\r
16700             handler: handler,\r
16701             scope: scope,\r
16702             minWidth: this.minButtonWidth,\r
16703             hideParent:true\r
16704         };\r
16705         if(typeof config == "string"){\r
16706             bc.text = config;\r
16707         }else{\r
16708             Ext.apply(bc, config);\r
16709         }\r
16710         var btn = new Ext.Button(bc);\r
16711         btn.ownerCt = this;\r
16712         if(!this.buttons){\r
16713             this.buttons = [];\r
16714         }\r
16715         this.buttons.push(btn);\r
16716         return btn;\r
16717     },\r
16718 \r
16719     // private\r
16720     addTool : function(){\r
16721         if(!this[this.toolTarget]) { // no where to render tools!\r
16722             return;\r
16723         }\r
16724         if(!this.toolTemplate){\r
16725             // initialize the global tool template on first use\r
16726             var tt = new Ext.Template(\r
16727                  '<div class="x-tool x-tool-{id}">&#160;</div>'\r
16728             );\r
16729             tt.disableFormats = true;\r
16730             tt.compile();\r
16731             Ext.Panel.prototype.toolTemplate = tt;\r
16732         }\r
16733         for(var i = 0, a = arguments, len = a.length; i < len; i++) {\r
16734             var tc = a[i];\r
16735             if(!this.tools[tc.id]){\r
16736                     var overCls = 'x-tool-'+tc.id+'-over';\r
16737                     var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);\r
16738                     this.tools[tc.id] = t;\r
16739                     t.enableDisplayMode('block');\r
16740                     t.on('click', this.createToolHandler(t, tc, overCls, this));\r
16741                     if(tc.on){\r
16742                         t.on(tc.on);\r
16743                     }\r
16744                     if(tc.hidden){\r
16745                         t.hide();\r
16746                     }\r
16747                     if(tc.qtip){\r
16748                         if(typeof tc.qtip == 'object'){\r
16749                             Ext.QuickTips.register(Ext.apply({\r
16750                                   target: t.id\r
16751                             }, tc.qtip));\r
16752                         } else {\r
16753                             t.dom.qtip = tc.qtip;\r
16754                         }\r
16755                     }\r
16756                     t.addClassOnOver(overCls);\r
16757             }\r
16758         }\r
16759     },\r
16760 \r
16761     // private\r
16762     onShow : function(){\r
16763         if(this.floating){\r
16764             return this.el.show();\r
16765         }\r
16766         Ext.Panel.superclass.onShow.call(this);\r
16767     },\r
16768 \r
16769     // private\r
16770     onHide : function(){\r
16771         if(this.floating){\r
16772             return this.el.hide();\r
16773         }\r
16774         Ext.Panel.superclass.onHide.call(this);\r
16775     },\r
16776 \r
16777     // private\r
16778     createToolHandler : function(t, tc, overCls, panel){\r
16779         return function(e){\r
16780             t.removeClass(overCls);\r
16781             e.stopEvent();\r
16782             if(tc.handler){\r
16783                 tc.handler.call(tc.scope || t, e, t, panel);\r
16784             }\r
16785         };\r
16786     },\r
16787 \r
16788     // private\r
16789     afterRender : function(){\r
16790         if(this.fromMarkup && this.height === undefined && !this.autoHeight){\r
16791             this.height = this.el.getHeight();\r
16792         }\r
16793         if(this.floating && !this.hidden && !this.initHidden){\r
16794             this.el.show();\r
16795         }\r
16796         if(this.title){\r
16797             this.setTitle(this.title);\r
16798         }\r
16799         this.setAutoScroll();\r
16800         if(this.html){\r
16801             this.body.update(typeof this.html == 'object' ?\r
16802                              Ext.DomHelper.markup(this.html) :\r
16803                              this.html);\r
16804             delete this.html;\r
16805         }\r
16806         if(this.contentEl){\r
16807             var ce = Ext.getDom(this.contentEl);\r
16808             Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);\r
16809             this.body.dom.appendChild(ce);\r
16810         }\r
16811         if(this.collapsed){\r
16812             this.collapsed = false;\r
16813             this.collapse(false);\r
16814         }\r
16815         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last\r
16816         this.initEvents();\r
16817     },\r
16818 \r
16819     // private\r
16820     setAutoScroll : function(){\r
16821         if(this.rendered && this.autoScroll){\r
16822             var el = this.body || this.el;\r
16823             if(el){\r
16824                 el.setOverflow('auto');\r
16825             }\r
16826         }\r
16827     },\r
16828 \r
16829     // private\r
16830     getKeyMap : function(){\r
16831         if(!this.keyMap){\r
16832             this.keyMap = new Ext.KeyMap(this.el, this.keys);\r
16833         }\r
16834         return this.keyMap;\r
16835     },\r
16836 \r
16837     // private\r
16838     initEvents : function(){\r
16839         if(this.keys){\r
16840             this.getKeyMap();\r
16841         }\r
16842         if(this.draggable){\r
16843             this.initDraggable();\r
16844         }\r
16845     },\r
16846 \r
16847     // private\r
16848     initDraggable : function(){\r
16849         \r
16850         this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);\r
16851     },\r
16852 \r
16853     // private\r
16854     beforeEffect : function(){\r
16855         if(this.floating){\r
16856             this.el.beforeAction();\r
16857         }\r
16858         this.el.addClass('x-panel-animated');\r
16859     },\r
16860 \r
16861     // private\r
16862     afterEffect : function(){\r
16863         this.syncShadow();\r
16864         this.el.removeClass('x-panel-animated');\r
16865     },\r
16866 \r
16867     // private - wraps up an animation param with internal callbacks\r
16868     createEffect : function(a, cb, scope){\r
16869         var o = {\r
16870             scope:scope,\r
16871             block:true\r
16872         };\r
16873         if(a === true){\r
16874             o.callback = cb;\r
16875             return o;\r
16876         }else if(!a.callback){\r
16877             o.callback = cb;\r
16878         }else { // wrap it up\r
16879             o.callback = function(){\r
16880                 cb.call(scope);\r
16881                 Ext.callback(a.callback, a.scope);\r
16882             };\r
16883         }\r
16884         return Ext.applyIf(o, a);\r
16885     },\r
16886 \r
16887     \r
16888     collapse : function(animate){\r
16889         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){\r
16890             return;\r
16891         }\r
16892         var doAnim = animate === true || (animate !== false && this.animCollapse);\r
16893         this.beforeEffect();\r
16894         this.onCollapse(doAnim, animate);\r
16895         return this;\r
16896     },\r
16897 \r
16898     // private\r
16899     onCollapse : function(doAnim, animArg){\r
16900         if(doAnim){\r
16901             this[this.collapseEl].slideOut(this.slideAnchor,\r
16902                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),\r
16903                         this.collapseDefaults));\r
16904         }else{\r
16905             this[this.collapseEl].hide();\r
16906             this.afterCollapse();\r
16907         }\r
16908     },\r
16909 \r
16910     // private\r
16911     afterCollapse : function(){\r
16912         this.collapsed = true;\r
16913         this.el.addClass(this.collapsedCls);\r
16914         this.afterEffect();\r
16915         this.fireEvent('collapse', this);\r
16916     },\r
16917 \r
16918     \r
16919     expand : function(animate){\r
16920         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){\r
16921             return;\r
16922         }\r
16923         var doAnim = animate === true || (animate !== false && this.animCollapse);\r
16924         this.el.removeClass(this.collapsedCls);\r
16925         this.beforeEffect();\r
16926         this.onExpand(doAnim, animate);\r
16927         return this;\r
16928     },\r
16929 \r
16930     // private\r
16931     onExpand : function(doAnim, animArg){\r
16932         if(doAnim){\r
16933             this[this.collapseEl].slideIn(this.slideAnchor,\r
16934                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),\r
16935                         this.expandDefaults));\r
16936         }else{\r
16937             this[this.collapseEl].show();\r
16938             this.afterExpand();\r
16939         }\r
16940     },\r
16941 \r
16942     // private\r
16943     afterExpand : function(){\r
16944         this.collapsed = false;\r
16945         this.afterEffect();\r
16946         this.fireEvent('expand', this);\r
16947     },\r
16948 \r
16949     \r
16950     toggleCollapse : function(animate){\r
16951         this[this.collapsed ? 'expand' : 'collapse'](animate);\r
16952         return this;\r
16953     },\r
16954 \r
16955     // private\r
16956     onDisable : function(){\r
16957         if(this.rendered && this.maskDisabled){\r
16958             this.el.mask();\r
16959         }\r
16960         Ext.Panel.superclass.onDisable.call(this);\r
16961     },\r
16962 \r
16963     // private\r
16964     onEnable : function(){\r
16965         if(this.rendered && this.maskDisabled){\r
16966             this.el.unmask();\r
16967         }\r
16968         Ext.Panel.superclass.onEnable.call(this);\r
16969     },\r
16970 \r
16971     // private\r
16972     onResize : function(w, h){\r
16973         if(w !== undefined || h !== undefined){\r
16974             if(!this.collapsed){\r
16975                 if(typeof w == 'number'){\r
16976                     this.body.setWidth(\r
16977                             this.adjustBodyWidth(w - this.getFrameWidth()));\r
16978                 }else if(w == 'auto'){\r
16979                     this.body.setWidth(w);\r
16980                 }\r
16981 \r
16982                 if(typeof h == 'number'){\r
16983                     this.body.setHeight(\r
16984                             this.adjustBodyHeight(h - this.getFrameHeight()));\r
16985                 }else if(h == 'auto'){\r
16986                     this.body.setHeight(h);\r
16987                 }\r
16988                 \r
16989                 if(this.disabled && this.el._mask){\r
16990                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());\r
16991                 }\r
16992             }else{\r
16993                 this.queuedBodySize = {width: w, height: h};\r
16994                 if(!this.queuedExpand && this.allowQueuedExpand !== false){\r
16995                     this.queuedExpand = true;\r
16996                     this.on('expand', function(){\r
16997                         delete this.queuedExpand;\r
16998                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);\r
16999                         this.doLayout();\r
17000                     }, this, {single:true});\r
17001                 }\r
17002             }\r
17003             this.fireEvent('bodyresize', this, w, h);\r
17004         }\r
17005         this.syncShadow();\r
17006     },\r
17007 \r
17008     // private\r
17009     adjustBodyHeight : function(h){\r
17010         return h;\r
17011     },\r
17012 \r
17013     // private\r
17014     adjustBodyWidth : function(w){\r
17015         return w;\r
17016     },\r
17017 \r
17018     // private\r
17019     onPosition : function(){\r
17020         this.syncShadow();\r
17021     },\r
17022 \r
17023     \r
17024     getFrameWidth : function(){\r
17025         var w = this.el.getFrameWidth('lr');\r
17026 \r
17027         if(this.frame){\r
17028             var l = this.bwrap.dom.firstChild;\r
17029             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));\r
17030             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;\r
17031             w += Ext.fly(mc).getFrameWidth('lr');\r
17032         }\r
17033         return w;\r
17034     },\r
17035 \r
17036     \r
17037     getFrameHeight : function(){\r
17038         var h  = this.el.getFrameWidth('tb');\r
17039         h += (this.tbar ? this.tbar.getHeight() : 0) +\r
17040              (this.bbar ? this.bbar.getHeight() : 0);\r
17041 \r
17042         if(this.frame){\r
17043             var hd = this.el.dom.firstChild;\r
17044             var ft = this.bwrap.dom.lastChild;\r
17045             h += (hd.offsetHeight + ft.offsetHeight);\r
17046             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;\r
17047             h += Ext.fly(mc).getFrameWidth('tb');\r
17048         }else{\r
17049             h += (this.header ? this.header.getHeight() : 0) +\r
17050                 (this.footer ? this.footer.getHeight() : 0);\r
17051         }\r
17052         return h;\r
17053     },\r
17054 \r
17055     \r
17056     getInnerWidth : function(){\r
17057         return this.getSize().width - this.getFrameWidth();\r
17058     },\r
17059 \r
17060     \r
17061     getInnerHeight : function(){\r
17062         return this.getSize().height - this.getFrameHeight();\r
17063     },\r
17064 \r
17065     // private\r
17066     syncShadow : function(){\r
17067         if(this.floating){\r
17068             this.el.sync(true);\r
17069         }\r
17070     },\r
17071 \r
17072     // private\r
17073     getLayoutTarget : function(){\r
17074         return this.body;\r
17075     },\r
17076 \r
17077     \r
17078     setTitle : function(title, iconCls){\r
17079         this.title = title;\r
17080         if(this.header && this.headerAsText){\r
17081             this.header.child('span').update(title);\r
17082         }\r
17083         if(iconCls){\r
17084             this.setIconClass(iconCls);\r
17085         }\r
17086         this.fireEvent('titlechange', this, title);\r
17087         return this;\r
17088     },\r
17089 \r
17090     \r
17091     getUpdater : function(){\r
17092         return this.body.getUpdater();\r
17093     },\r
17094 \r
17095      \r
17096     load : function(){\r
17097         var um = this.body.getUpdater();\r
17098         um.update.apply(um, arguments);\r
17099         return this;\r
17100     },\r
17101 \r
17102     // private\r
17103     beforeDestroy : function(){\r
17104         if(this.header){\r
17105             this.header.removeAllListeners();\r
17106             if(this.headerAsText){\r
17107                 Ext.Element.uncache(this.header.child('span'));\r
17108             }\r
17109         }\r
17110         Ext.Element.uncache(\r
17111             this.header,\r
17112             this.tbar,\r
17113             this.bbar,\r
17114             this.footer,\r
17115             this.body,\r
17116             this.bwrap\r
17117         );\r
17118         if(this.tools){\r
17119             for(var k in this.tools){\r
17120                 Ext.destroy(this.tools[k]);\r
17121             }\r
17122         }\r
17123         if(this.buttons){\r
17124             for(var b in this.buttons){\r
17125                 Ext.destroy(this.buttons[b]);\r
17126             }\r
17127         }\r
17128         Ext.destroy(\r
17129             this.topToolbar,\r
17130             this.bottomToolbar\r
17131         );\r
17132         Ext.Panel.superclass.beforeDestroy.call(this);\r
17133     },\r
17134 \r
17135     // private\r
17136     createClasses : function(){\r
17137         this.headerCls = this.baseCls + '-header';\r
17138         this.headerTextCls = this.baseCls + '-header-text';\r
17139         this.bwrapCls = this.baseCls + '-bwrap';\r
17140         this.tbarCls = this.baseCls + '-tbar';\r
17141         this.bodyCls = this.baseCls + '-body';\r
17142         this.bbarCls = this.baseCls + '-bbar';\r
17143         this.footerCls = this.baseCls + '-footer';\r
17144     },\r
17145 \r
17146     // private\r
17147     createGhost : function(cls, useShim, appendTo){\r
17148         var el = document.createElement('div');\r
17149         el.className = 'x-panel-ghost ' + (cls ? cls : '');\r
17150         if(this.header){\r
17151             el.appendChild(this.el.dom.firstChild.cloneNode(true));\r
17152         }\r
17153         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());\r
17154         el.style.width = this.el.dom.offsetWidth + 'px';;\r
17155         if(!appendTo){\r
17156             this.container.dom.appendChild(el);\r
17157         }else{\r
17158             Ext.getDom(appendTo).appendChild(el);\r
17159         }\r
17160         if(useShim !== false && this.el.useShim !== false){\r
17161             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);\r
17162             layer.show();\r
17163             return layer;\r
17164         }else{\r
17165             return new Ext.Element(el);\r
17166         }\r
17167     },\r
17168 \r
17169     // private\r
17170     doAutoLoad : function(){\r
17171         this.body.load(\r
17172             typeof this.autoLoad == 'object' ?\r
17173                 this.autoLoad : {url: this.autoLoad});\r
17174     },\r
17175     \r
17176     \r
17177     getTool: function(id) {\r
17178         return this.tools[id];\r
17179     }\r
17180 \r
17181 \r
17182 });\r
17183 Ext.reg('panel', Ext.Panel);\r
17184 \r
17185 \r
17186 Ext.Window = Ext.extend(Ext.Panel, {\r
17187     \r
17188     \r
17189     \r
17190     \r
17191     \r
17192     \r
17193     \r
17194     \r
17195     \r
17196     \r
17197     \r
17198     \r
17199     baseCls : 'x-window',\r
17200     \r
17201     resizable:true,\r
17202     \r
17203     draggable:true,\r
17204     \r
17205     closable : true,\r
17206     \r
17207     constrain:false,\r
17208     \r
17209     constrainHeader:false,\r
17210     \r
17211     plain:false,\r
17212     \r
17213     minimizable : false,\r
17214     \r
17215     maximizable : false,\r
17216     \r
17217     minHeight: 100,\r
17218     \r
17219     minWidth: 200,\r
17220     \r
17221     expandOnShow: true,\r
17222     \r
17223     closeAction: 'close',\r
17224     \r
17225     elements: 'header,body',\r
17226 \r
17227     // inherited docs, same default\r
17228     collapsible:false,\r
17229 \r
17230     // private\r
17231     initHidden : true,\r
17232     \r
17233     monitorResize : true,\r
17234     \r
17235     frame:true,\r
17236     \r
17237     floating:true,\r
17238 \r
17239     // private\r
17240     initComponent : function(){\r
17241         Ext.Window.superclass.initComponent.call(this);\r
17242         this.addEvents(\r
17243             \r
17244             \r
17245             \r
17246             'resize',\r
17247             \r
17248             'maximize',\r
17249             \r
17250             'minimize',\r
17251             \r
17252             'restore'\r
17253         );\r
17254     },\r
17255 \r
17256     // private\r
17257     getState : function(){\r
17258         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox());\r
17259     },\r
17260 \r
17261     // private\r
17262     onRender : function(ct, position){\r
17263         Ext.Window.superclass.onRender.call(this, ct, position);\r
17264 \r
17265         if(this.plain){\r
17266             this.el.addClass('x-window-plain');\r
17267         }\r
17268 \r
17269         // this element allows the Window to be focused for keyboard events\r
17270         this.focusEl = this.el.createChild({\r
17271                     tag: "a", href:"#", cls:"x-dlg-focus",\r
17272                     tabIndex:"-1", html: "&#160;"});\r
17273         this.focusEl.swallowEvent('click', true);\r
17274 \r
17275         this.proxy = this.el.createProxy("x-window-proxy");\r
17276         this.proxy.enableDisplayMode('block');\r
17277 \r
17278         if(this.modal){\r
17279             this.mask = this.container.createChild({cls:"ext-el-mask"}, this.el.dom);\r
17280             this.mask.enableDisplayMode("block");\r
17281             this.mask.hide();\r
17282             this.mask.on('click', this.focus, this);\r
17283         }\r
17284     },\r
17285 \r
17286     // private\r
17287     initEvents : function(){\r
17288         Ext.Window.superclass.initEvents.call(this);\r
17289         if(this.animateTarget){\r
17290             this.setAnimateTarget(this.animateTarget);\r
17291         }\r
17292 \r
17293         if(this.resizable){\r
17294             this.resizer = new Ext.Resizable(this.el, {\r
17295                 minWidth: this.minWidth,\r
17296                 minHeight:this.minHeight,\r
17297                 handles: this.resizeHandles || "all",\r
17298                 pinned: true,\r
17299                 resizeElement : this.resizerAction\r
17300             });\r
17301             this.resizer.window = this;\r
17302             this.resizer.on("beforeresize", this.beforeResize, this);\r
17303         }\r
17304 \r
17305         if(this.draggable){\r
17306             this.header.addClass("x-window-draggable");\r
17307         }\r
17308         this.initTools();\r
17309 \r
17310         this.el.on("mousedown", this.toFront, this);\r
17311         this.manager = this.manager || Ext.WindowMgr;\r
17312         this.manager.register(this);\r
17313         this.hidden = true;\r
17314         if(this.maximized){\r
17315             this.maximized = false;\r
17316             this.maximize();\r
17317         }\r
17318         if(this.closable){\r
17319             var km = this.getKeyMap();\r
17320             km.on(27, this.onEsc, this);\r
17321             km.disable();\r
17322         }\r
17323     },\r
17324 \r
17325     initDraggable : function(){\r
17326         \r
17327         this.dd = new Ext.Window.DD(this);\r
17328     },\r
17329 \r
17330    // private\r
17331     onEsc : function(){\r
17332         this[this.closeAction]();\r
17333     },\r
17334 \r
17335     // private\r
17336     beforeDestroy : function(){\r
17337         this.hide();\r
17338         if(this.doAnchor){\r
17339             Ext.EventManager.removeResizeListener(this.doAnchor, this);\r
17340             Ext.EventManager.un(window, 'scroll', this.doAnchor, this);\r
17341         }\r
17342         Ext.destroy(\r
17343             this.focusEl,\r
17344             this.resizer,\r
17345             this.dd,\r
17346             this.proxy,\r
17347             this.mask\r
17348         );\r
17349         Ext.Window.superclass.beforeDestroy.call(this);\r
17350     },\r
17351 \r
17352     // private\r
17353     onDestroy : function(){\r
17354         if(this.manager){\r
17355             this.manager.unregister(this);\r
17356         }\r
17357         Ext.Window.superclass.onDestroy.call(this);\r
17358     },\r
17359 \r
17360     // private\r
17361     initTools : function(){\r
17362         if(this.minimizable){\r
17363             this.addTool({\r
17364                 id: 'minimize',\r
17365                 handler: this.minimize.createDelegate(this, [])\r
17366             });\r
17367         }\r
17368         if(this.maximizable){\r
17369             this.addTool({\r
17370                 id: 'maximize',\r
17371                 handler: this.maximize.createDelegate(this, [])\r
17372             });\r
17373             this.addTool({\r
17374                 id: 'restore',\r
17375                 handler: this.restore.createDelegate(this, []),\r
17376                 hidden:true\r
17377             });\r
17378             this.header.on('dblclick', this.toggleMaximize, this);\r
17379         }\r
17380         if(this.closable){\r
17381             this.addTool({\r
17382                 id: 'close',\r
17383                 handler: this[this.closeAction].createDelegate(this, [])\r
17384             });\r
17385         }\r
17386     },\r
17387 \r
17388     // private\r
17389     resizerAction : function(){\r
17390         var box = this.proxy.getBox();\r
17391         this.proxy.hide();\r
17392         this.window.handleResize(box);\r
17393         return box;\r
17394     },\r
17395 \r
17396     // private\r
17397     beforeResize : function(){\r
17398         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); // 40 is a magic minimum content size?\r
17399         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);\r
17400         this.resizeBox = this.el.getBox();\r
17401     },\r
17402 \r
17403     // private\r
17404     updateHandles : function(){\r
17405         if(Ext.isIE && this.resizer){\r
17406             this.resizer.syncHandleHeight();\r
17407             this.el.repaint();\r
17408         }\r
17409     },\r
17410 \r
17411     // private\r
17412     handleResize : function(box){\r
17413         var rz = this.resizeBox;\r
17414         if(rz.x != box.x || rz.y != box.y){\r
17415             this.updateBox(box);\r
17416         }else{\r
17417             this.setSize(box);\r
17418         }\r
17419         this.focus();\r
17420         this.updateHandles();\r
17421         this.saveState();\r
17422         if(this.layout){\r
17423             this.doLayout();\r
17424         }\r
17425         this.fireEvent("resize", this, box.width, box.height);\r
17426     },\r
17427 \r
17428     \r
17429     focus : function(){\r
17430         var f = this.focusEl, db = this.defaultButton, t = typeof db;\r
17431         if(t != 'undefined'){\r
17432             if(t == 'number'){\r
17433                 f = this.buttons[db];\r
17434             }else if(t == 'string'){\r
17435                 f = Ext.getCmp(db);\r
17436             }else{\r
17437                 f = db;\r
17438             }\r
17439         }\r
17440         f.focus.defer(10, f);\r
17441     },\r
17442 \r
17443     \r
17444     setAnimateTarget : function(el){\r
17445         el = Ext.get(el);\r
17446         this.animateTarget = el;\r
17447     },\r
17448 \r
17449     // private\r
17450     beforeShow : function(){\r
17451         delete this.el.lastXY;\r
17452         delete this.el.lastLT;\r
17453         if(this.x === undefined || this.y === undefined){\r
17454             var xy = this.el.getAlignToXY(this.container, 'c-c');\r
17455             var pos = this.el.translatePoints(xy[0], xy[1]);\r
17456             this.x = this.x === undefined? pos.left : this.x;\r
17457             this.y = this.y === undefined? pos.top : this.y;\r
17458         }\r
17459         this.el.setLeftTop(this.x, this.y);\r
17460 \r
17461         if(this.expandOnShow){\r
17462             this.expand(false);\r
17463         }\r
17464 \r
17465         if(this.modal){\r
17466             Ext.getBody().addClass("x-body-masked");\r
17467             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
17468             this.mask.show();\r
17469         }\r
17470     },\r
17471 \r
17472     \r
17473     show : function(animateTarget, cb, scope){\r
17474         if(!this.rendered){\r
17475             this.render(Ext.getBody());\r
17476         }\r
17477         if(this.hidden === false){\r
17478             this.toFront();\r
17479             return;\r
17480         }\r
17481         if(this.fireEvent("beforeshow", this) === false){\r
17482             return;\r
17483         }\r
17484         if(cb){\r
17485             this.on('show', cb, scope, {single:true});\r
17486         }\r
17487         this.hidden = false;\r
17488         if(animateTarget !== undefined){\r
17489             this.setAnimateTarget(animateTarget);\r
17490         }\r
17491         this.beforeShow();\r
17492         if(this.animateTarget){\r
17493             this.animShow();\r
17494         }else{\r
17495             this.afterShow();\r
17496         }\r
17497     },\r
17498 \r
17499     // private\r
17500     afterShow : function(){\r
17501         this.proxy.hide();\r
17502         this.el.setStyle('display', 'block');\r
17503         this.el.show();\r
17504         if(this.maximized){\r
17505             this.fitContainer();\r
17506         }\r
17507         if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug\r
17508                 this.cascade(this.setAutoScroll);\r
17509         }\r
17510 \r
17511         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){\r
17512             Ext.EventManager.onWindowResize(this.onWindowResize, this);\r
17513         }\r
17514         this.doConstrain();\r
17515         if(this.layout){\r
17516             this.doLayout();\r
17517         }\r
17518         if(this.keyMap){\r
17519             this.keyMap.enable();\r
17520         }\r
17521         this.toFront();\r
17522         this.updateHandles();\r
17523         this.fireEvent("show", this);\r
17524     },\r
17525 \r
17526     // private\r
17527     animShow : function(){\r
17528         this.proxy.show();\r
17529         this.proxy.setBox(this.animateTarget.getBox());\r
17530         this.proxy.setOpacity(0);\r
17531         var b = this.getBox(false);\r
17532         b.callback = this.afterShow;\r
17533         b.scope = this;\r
17534         b.duration = .25;\r
17535         b.easing = 'easeNone';\r
17536         b.opacity = .5;\r
17537         b.block = true;\r
17538         this.el.setStyle('display', 'none');\r
17539         this.proxy.shift(b);\r
17540     },\r
17541 \r
17542     \r
17543     hide : function(animateTarget, cb, scope){\r
17544         if(this.activeGhost){ // drag active?\r
17545             this.hide.defer(100, this, [animateTarget, cb, scope]);\r
17546             return;\r
17547         }\r
17548         if(this.hidden || this.fireEvent("beforehide", this) === false){\r
17549             return;\r
17550         }\r
17551         if(cb){\r
17552             this.on('hide', cb, scope, {single:true});\r
17553         }\r
17554         this.hidden = true;\r
17555         if(animateTarget !== undefined){\r
17556             this.setAnimateTarget(animateTarget);\r
17557         }\r
17558         if(this.animateTarget){\r
17559             this.animHide();\r
17560         }else{\r
17561             this.el.hide();\r
17562             this.afterHide();\r
17563         }\r
17564     },\r
17565 \r
17566     // private\r
17567     afterHide : function(){\r
17568         this.proxy.hide();\r
17569         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){\r
17570             Ext.EventManager.removeResizeListener(this.onWindowResize, this);\r
17571         }\r
17572         if(this.modal){\r
17573             this.mask.hide();\r
17574             Ext.getBody().removeClass("x-body-masked");\r
17575         }\r
17576         if(this.keyMap){\r
17577             this.keyMap.disable();\r
17578         }\r
17579         this.fireEvent("hide", this);\r
17580     },\r
17581 \r
17582     // private\r
17583     animHide : function(){\r
17584         this.proxy.setOpacity(.5);\r
17585         this.proxy.show();\r
17586         var tb = this.getBox(false);\r
17587         this.proxy.setBox(tb);\r
17588         this.el.hide();\r
17589         var b = this.animateTarget.getBox();\r
17590         b.callback = this.afterHide;\r
17591         b.scope = this;\r
17592         b.duration = .25;\r
17593         b.easing = 'easeNone';\r
17594         b.block = true;\r
17595         b.opacity = 0;\r
17596         this.proxy.shift(b);\r
17597     },\r
17598 \r
17599     // private\r
17600     onWindowResize : function(){\r
17601         if(this.maximized){\r
17602             this.fitContainer();\r
17603         }\r
17604         if(this.modal){\r
17605             this.mask.setSize('100%', '100%');\r
17606             var force = this.mask.dom.offsetHeight;\r
17607             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
17608         }\r
17609         this.doConstrain();\r
17610     },\r
17611 \r
17612     // private\r
17613     doConstrain : function(){\r
17614         if(this.constrain || this.constrainHeader){\r
17615             var offsets;\r
17616             if(this.constrain){\r
17617                 offsets = {\r
17618                     right:this.el.shadowOffset,\r
17619                     left:this.el.shadowOffset,\r
17620                     bottom:this.el.shadowOffset\r
17621                 };\r
17622             }else {\r
17623                 var s = this.getSize();\r
17624                 offsets = {\r
17625                     right:-(s.width - 100),\r
17626                     bottom:-(s.height - 25)\r
17627                 };\r
17628             }\r
17629 \r
17630             var xy = this.el.getConstrainToXY(this.container, true, offsets);\r
17631             if(xy){\r
17632                 this.setPosition(xy[0], xy[1]);\r
17633             }\r
17634         }\r
17635     },\r
17636 \r
17637     // private - used for dragging\r
17638     ghost : function(cls){\r
17639         var ghost = this.createGhost(cls);\r
17640         var box = this.getBox(true);\r
17641         ghost.setLeftTop(box.x, box.y);\r
17642         ghost.setWidth(box.width);\r
17643         this.el.hide();\r
17644         this.activeGhost = ghost;\r
17645         return ghost;\r
17646     },\r
17647 \r
17648     // private\r
17649     unghost : function(show, matchPosition){\r
17650         if(show !== false){\r
17651             this.el.show();\r
17652             this.focus();\r
17653                 if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug\r
17654                         this.cascade(this.setAutoScroll);\r
17655                 }\r
17656         }\r
17657         if(matchPosition !== false){\r
17658             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));\r
17659         }\r
17660         this.activeGhost.hide();\r
17661         this.activeGhost.remove();\r
17662         delete this.activeGhost;\r
17663     },\r
17664 \r
17665     \r
17666     minimize : function(){\r
17667         this.fireEvent('minimize', this);\r
17668     },\r
17669 \r
17670     \r
17671     close : function(){\r
17672         if(this.fireEvent("beforeclose", this) !== false){\r
17673             this.hide(null, function(){\r
17674                 this.fireEvent('close', this);\r
17675                 this.destroy();\r
17676             }, this);\r
17677         }\r
17678     },\r
17679 \r
17680     \r
17681     maximize : function(){\r
17682         if(!this.maximized){\r
17683             this.expand(false);\r
17684             this.restoreSize = this.getSize();\r
17685             this.restorePos = this.getPosition(true);\r
17686             if (this.maximizable){\r
17687                 this.tools.maximize.hide();\r
17688                 this.tools.restore.show();\r
17689             }\r
17690             this.maximized = true;\r
17691             this.el.disableShadow();\r
17692 \r
17693             if(this.dd){\r
17694                 this.dd.lock();\r
17695             }\r
17696             if(this.collapsible){\r
17697                 this.tools.toggle.hide();\r
17698             }\r
17699             this.el.addClass('x-window-maximized');\r
17700             this.container.addClass('x-window-maximized-ct');\r
17701 \r
17702             this.setPosition(0, 0);\r
17703             this.fitContainer();\r
17704             this.fireEvent('maximize', this);\r
17705         }\r
17706     },\r
17707 \r
17708     \r
17709     restore : function(){\r
17710         if(this.maximized){\r
17711             this.el.removeClass('x-window-maximized');\r
17712             this.tools.restore.hide();\r
17713             this.tools.maximize.show();\r
17714             this.setPosition(this.restorePos[0], this.restorePos[1]);\r
17715             this.setSize(this.restoreSize.width, this.restoreSize.height);\r
17716             delete this.restorePos;\r
17717             delete this.restoreSize;\r
17718             this.maximized = false;\r
17719             this.el.enableShadow(true);\r
17720 \r
17721             if(this.dd){\r
17722                 this.dd.unlock();\r
17723             }\r
17724             if(this.collapsible){\r
17725                 this.tools.toggle.show();\r
17726             }\r
17727             this.container.removeClass('x-window-maximized-ct');\r
17728 \r
17729             this.doConstrain();\r
17730             this.fireEvent('restore', this);\r
17731         }\r
17732     },\r
17733 \r
17734     \r
17735     toggleMaximize : function(){\r
17736         this[this.maximized ? 'restore' : 'maximize']();\r
17737     },\r
17738 \r
17739     // private\r
17740     fitContainer : function(){\r
17741         var vs = this.container.getViewSize();\r
17742         this.setSize(vs.width, vs.height);\r
17743     },\r
17744 \r
17745     // private\r
17746     // z-index is managed by the WindowManager and may be overwritten at any time\r
17747     setZIndex : function(index){\r
17748         if(this.modal){\r
17749             this.mask.setStyle("z-index", index);\r
17750         }\r
17751         this.el.setZIndex(++index);\r
17752         index += 5;\r
17753 \r
17754         if(this.resizer){\r
17755             this.resizer.proxy.setStyle("z-index", ++index);\r
17756         }\r
17757 \r
17758         this.lastZIndex = index;\r
17759     },\r
17760 \r
17761     \r
17762     alignTo : function(element, position, offsets){\r
17763         var xy = this.el.getAlignToXY(element, position, offsets);\r
17764         this.setPagePosition(xy[0], xy[1]);\r
17765         return this;\r
17766     },\r
17767 \r
17768     \r
17769     anchorTo : function(el, alignment, offsets, monitorScroll){\r
17770       if(this.doAnchor){\r
17771           Ext.EventManager.removeResizeListener(this.doAnchor, this);\r
17772           Ext.EventManager.un(window, 'scroll', this.doAnchor, this);\r
17773       }\r
17774       this.doAnchor = function(){\r
17775           this.alignTo(el, alignment, offsets);\r
17776       };\r
17777       Ext.EventManager.onWindowResize(this.doAnchor, this);\r
17778       \r
17779       var tm = typeof monitorScroll;\r
17780       if(tm != 'undefined'){\r
17781           Ext.EventManager.on(window, 'scroll', this.doAnchor, this,\r
17782               {buffer: tm == 'number' ? monitorScroll : 50});\r
17783       }\r
17784       this.doAnchor();\r
17785       return this;\r
17786     },\r
17787 \r
17788     \r
17789     toFront : function(e){\r
17790         if(this.manager.bringToFront(this)){\r
17791             if(!e || !e.getTarget().focus){\r
17792                 this.focus();\r
17793             }\r
17794         }\r
17795         return this;\r
17796     },\r
17797 \r
17798     \r
17799     setActive : function(active){\r
17800         if(active){\r
17801             if(!this.maximized){\r
17802                 this.el.enableShadow(true);\r
17803             }\r
17804             this.fireEvent('activate', this);\r
17805         }else{\r
17806             this.el.disableShadow();\r
17807             this.fireEvent('deactivate', this);\r
17808         }\r
17809     },\r
17810 \r
17811     \r
17812     toBack : function(){\r
17813         this.manager.sendToBack(this);\r
17814         return this;\r
17815     },\r
17816 \r
17817     \r
17818     center : function(){\r
17819         var xy = this.el.getAlignToXY(this.container, 'c-c');\r
17820         this.setPagePosition(xy[0], xy[1]);\r
17821         return this;\r
17822     }\r
17823 \r
17824     \r
17825 });\r
17826 Ext.reg('window', Ext.Window);\r
17827 \r
17828 // private - custom Window DD implementation\r
17829 Ext.Window.DD = function(win){\r
17830     this.win = win;\r
17831     Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);\r
17832     this.setHandleElId(win.header.id);\r
17833     this.scroll = false;\r
17834 };\r
17835 \r
17836 Ext.extend(Ext.Window.DD, Ext.dd.DD, {\r
17837     moveOnly:true,\r
17838     headerOffsets:[100, 25],\r
17839     startDrag : function(){\r
17840         var w = this.win;\r
17841         this.proxy = w.ghost();\r
17842         if(w.constrain !== false){\r
17843             var so = w.el.shadowOffset;\r
17844             this.constrainTo(w.container, {right: so, left: so, bottom: so});\r
17845         }else if(w.constrainHeader !== false){\r
17846             var s = this.proxy.getSize();\r
17847             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});\r
17848         }\r
17849     },\r
17850     b4Drag : Ext.emptyFn,\r
17851 \r
17852     onDrag : function(e){\r
17853         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());\r
17854     },\r
17855 \r
17856     endDrag : function(e){\r
17857         this.win.unghost();\r
17858         this.win.saveState();\r
17859     }\r
17860 });\r
17861 \r
17862 \r
17863 Ext.WindowGroup = function(){\r
17864     var list = {};\r
17865     var accessList = [];\r
17866     var front = null;\r
17867 \r
17868     // private\r
17869     var sortWindows = function(d1, d2){\r
17870         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;\r
17871     };\r
17872 \r
17873     // private\r
17874     var orderWindows = function(){\r
17875         var a = accessList, len = a.length;\r
17876         if(len > 0){\r
17877             a.sort(sortWindows);\r
17878             var seed = a[0].manager.zseed;\r
17879             for(var i = 0; i < len; i++){\r
17880                 var win = a[i];\r
17881                 if(win && !win.hidden){\r
17882                     win.setZIndex(seed + (i*10));\r
17883                 }\r
17884             }\r
17885         }\r
17886         activateLast();\r
17887     };\r
17888 \r
17889     // private\r
17890     var setActiveWin = function(win){\r
17891         if(win != front){\r
17892             if(front){\r
17893                 front.setActive(false);\r
17894             }\r
17895             front = win;\r
17896             if(win){\r
17897                 win.setActive(true);\r
17898             }\r
17899         }\r
17900     };\r
17901 \r
17902     // private\r
17903     var activateLast = function(){\r
17904         for(var i = accessList.length-1; i >=0; --i) {\r
17905             if(!accessList[i].hidden){\r
17906                 setActiveWin(accessList[i]);\r
17907                 return;\r
17908             }\r
17909         }\r
17910         // none to activate\r
17911         setActiveWin(null);\r
17912     };\r
17913 \r
17914     return {\r
17915         \r
17916         zseed : 9000,\r
17917 \r
17918         // private\r
17919         register : function(win){\r
17920             list[win.id] = win;\r
17921             accessList.push(win);\r
17922             win.on('hide', activateLast);\r
17923         },\r
17924 \r
17925         // private\r
17926         unregister : function(win){\r
17927             delete list[win.id];\r
17928             win.un('hide', activateLast);\r
17929             accessList.remove(win);\r
17930         },\r
17931 \r
17932         \r
17933         get : function(id){\r
17934             return typeof id == "object" ? id : list[id];\r
17935         },\r
17936 \r
17937         \r
17938         bringToFront : function(win){\r
17939             win = this.get(win);\r
17940             if(win != front){\r
17941                 win._lastAccess = new Date().getTime();\r
17942                 orderWindows();\r
17943                 return true;\r
17944             }\r
17945             return false;\r
17946         },\r
17947 \r
17948         \r
17949         sendToBack : function(win){\r
17950             win = this.get(win);\r
17951             win._lastAccess = -(new Date().getTime());\r
17952             orderWindows();\r
17953             return win;\r
17954         },\r
17955 \r
17956         \r
17957         hideAll : function(){\r
17958             for(var id in list){\r
17959                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){\r
17960                     list[id].hide();\r
17961                 }\r
17962             }\r
17963         },\r
17964 \r
17965         \r
17966         getActive : function(){\r
17967             return front;\r
17968         },\r
17969 \r
17970         \r
17971         getBy : function(fn, scope){\r
17972             var r = [];\r
17973             for(var i = accessList.length-1; i >=0; --i) {\r
17974                 var win = accessList[i];\r
17975                 if(fn.call(scope||win, win) !== false){\r
17976                     r.push(win);\r
17977                 }\r
17978             }\r
17979             return r;\r
17980         },\r
17981 \r
17982         \r
17983         each : function(fn, scope){\r
17984             for(var id in list){\r
17985                 if(list[id] && typeof list[id] != "function"){\r
17986                     if(fn.call(scope || list[id], list[id]) === false){\r
17987                         return;\r
17988                     }\r
17989                 }\r
17990             }\r
17991         }\r
17992     };\r
17993 };\r
17994 \r
17995 \r
17996 \r
17997 Ext.WindowMgr = new Ext.WindowGroup();\r
17998 \r
17999 Ext.dd.PanelProxy = function(panel, config){\r
18000     this.panel = panel;\r
18001     this.id = this.panel.id +'-ddproxy';\r
18002     Ext.apply(this, config);\r
18003 };\r
18004 \r
18005 Ext.dd.PanelProxy.prototype = {\r
18006     \r
18007     insertProxy : true,\r
18008 \r
18009     // private overrides\r
18010     setStatus : Ext.emptyFn,\r
18011     reset : Ext.emptyFn,\r
18012     update : Ext.emptyFn,\r
18013     stop : Ext.emptyFn,\r
18014     sync: Ext.emptyFn,\r
18015 \r
18016     \r
18017     getEl : function(){\r
18018         return this.ghost;\r
18019     },\r
18020 \r
18021     \r
18022     getGhost : function(){\r
18023         return this.ghost;\r
18024     },\r
18025 \r
18026     \r
18027     getProxy : function(){\r
18028         return this.proxy;\r
18029     },\r
18030 \r
18031     \r
18032     hide : function(){\r
18033         if(this.ghost){\r
18034             if(this.proxy){\r
18035                 this.proxy.remove();\r
18036                 delete this.proxy;\r
18037             }\r
18038             this.panel.el.dom.style.display = '';\r
18039             this.ghost.remove();\r
18040             delete this.ghost;\r
18041         }\r
18042     },\r
18043 \r
18044     \r
18045     show : function(){\r
18046         if(!this.ghost){\r
18047             this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());\r
18048             this.ghost.setXY(this.panel.el.getXY())\r
18049             if(this.insertProxy){\r
18050                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});\r
18051                 this.proxy.setSize(this.panel.getSize());\r
18052             }\r
18053             this.panel.el.dom.style.display = 'none';\r
18054         }\r
18055     },\r
18056 \r
18057     // private\r
18058     repair : function(xy, callback, scope){\r
18059         this.hide();\r
18060         if(typeof callback == "function"){\r
18061             callback.call(scope || this);\r
18062         }\r
18063     },\r
18064 \r
18065     \r
18066     moveProxy : function(parentNode, before){\r
18067         if(this.proxy){\r
18068             parentNode.insertBefore(this.proxy.dom, before);\r
18069         }\r
18070     }\r
18071 };\r
18072 \r
18073 // private - DD implementation for Panels\r
18074 Ext.Panel.DD = function(panel, cfg){\r
18075     this.panel = panel;\r
18076     this.dragData = {panel: panel};\r
18077     this.proxy = new Ext.dd.PanelProxy(panel, cfg);\r
18078     Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);\r
18079     var h = panel.header;\r
18080     if(h){\r
18081         this.setHandleElId(h.id);\r
18082     }\r
18083     (h ? h : this.panel.body).setStyle('cursor', 'move');\r
18084     this.scroll = false;\r
18085 };\r
18086 \r
18087 Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {\r
18088     showFrame: Ext.emptyFn,\r
18089     startDrag: Ext.emptyFn,\r
18090     b4StartDrag: function(x, y) {\r
18091         this.proxy.show();\r
18092     },\r
18093     b4MouseDown: function(e) {\r
18094         var x = e.getPageX();\r
18095         var y = e.getPageY();\r
18096         this.autoOffset(x, y);\r
18097     },\r
18098     onInitDrag : function(x, y){\r
18099         this.onStartDrag(x, y);\r
18100         return true;\r
18101     },\r
18102     createFrame : Ext.emptyFn,\r
18103     getDragEl : function(e){\r
18104         return this.proxy.ghost.dom;\r
18105     },\r
18106     endDrag : function(e){\r
18107         this.proxy.hide();\r
18108         this.panel.saveState();\r
18109     },\r
18110 \r
18111     autoOffset : function(x, y) {\r
18112         x -= this.startPageX;\r
18113         y -= this.startPageY;\r
18114         this.setDelta(x, y);\r
18115     }\r
18116 });\r
18117 \r
18118 Ext.state.Provider = function(){\r
18119     \r
18120     this.addEvents("statechange");\r
18121     this.state = {};\r
18122     Ext.state.Provider.superclass.constructor.call(this);\r
18123 };\r
18124 Ext.extend(Ext.state.Provider, Ext.util.Observable, {\r
18125     \r
18126     get : function(name, defaultValue){\r
18127         return typeof this.state[name] == "undefined" ?\r
18128             defaultValue : this.state[name];\r
18129     },\r
18130     \r
18131     \r
18132     clear : function(name){\r
18133         delete this.state[name];\r
18134         this.fireEvent("statechange", this, name, null);\r
18135     },\r
18136     \r
18137     \r
18138     set : function(name, value){\r
18139         this.state[name] = value;\r
18140         this.fireEvent("statechange", this, name, value);\r
18141     },\r
18142     \r
18143     \r
18144     decodeValue : function(cookie){\r
18145         var re = /^(a|n|d|b|s|o)\:(.*)$/;\r
18146         var matches = re.exec(unescape(cookie));\r
18147         if(!matches || !matches[1]) return; // non state cookie\r
18148         var type = matches[1];\r
18149         var v = matches[2];\r
18150         switch(type){\r
18151             case "n":\r
18152                 return parseFloat(v);\r
18153             case "d":\r
18154                 return new Date(Date.parse(v));\r
18155             case "b":\r
18156                 return (v == "1");\r
18157             case "a":\r
18158                 var all = [];\r
18159                 var values = v.split("^");\r
18160                 for(var i = 0, len = values.length; i < len; i++){\r
18161                     all.push(this.decodeValue(values[i]));\r
18162                 }\r
18163                 return all;\r
18164            case "o":\r
18165                 var all = {};\r
18166                 var values = v.split("^");\r
18167                 for(var i = 0, len = values.length; i < len; i++){\r
18168                     var kv = values[i].split("=");\r
18169                     all[kv[0]] = this.decodeValue(kv[1]);\r
18170                 }\r
18171                 return all;\r
18172            default:\r
18173                 return v;\r
18174         }\r
18175     },\r
18176     \r
18177     \r
18178     encodeValue : function(v){\r
18179         var enc;\r
18180         if(typeof v == "number"){\r
18181             enc = "n:" + v;\r
18182         }else if(typeof v == "boolean"){\r
18183             enc = "b:" + (v ? "1" : "0");\r
18184         }else if(Ext.isDate(v)){\r
18185             enc = "d:" + v.toGMTString();\r
18186         }else if(Ext.isArray(v)){\r
18187             var flat = "";\r
18188             for(var i = 0, len = v.length; i < len; i++){\r
18189                 flat += this.encodeValue(v[i]);\r
18190                 if(i != len-1) flat += "^";\r
18191             }\r
18192             enc = "a:" + flat;\r
18193         }else if(typeof v == "object"){\r
18194             var flat = "";\r
18195             for(var key in v){\r
18196                 if(typeof v[key] != "function" && v[key] !== undefined){\r
18197                     flat += key + "=" + this.encodeValue(v[key]) + "^";\r
18198                 }\r
18199             }\r
18200             enc = "o:" + flat.substring(0, flat.length-1);\r
18201         }else{\r
18202             enc = "s:" + v;\r
18203         }\r
18204         return escape(enc);        \r
18205     }\r
18206 });\r
18207 \r
18208 \r
18209 Ext.state.Manager = function(){\r
18210     var provider = new Ext.state.Provider();\r
18211 \r
18212     return {\r
18213         \r
18214         setProvider : function(stateProvider){\r
18215             provider = stateProvider;\r
18216         },\r
18217 \r
18218         \r
18219         get : function(key, defaultValue){\r
18220             return provider.get(key, defaultValue);\r
18221         },\r
18222 \r
18223         \r
18224          set : function(key, value){\r
18225             provider.set(key, value);\r
18226         },\r
18227 \r
18228         \r
18229         clear : function(key){\r
18230             provider.clear(key);\r
18231         },\r
18232 \r
18233         \r
18234         getProvider : function(){\r
18235             return provider;\r
18236         }\r
18237     };\r
18238 }();\r
18239 \r
18240 \r
18241 Ext.state.CookieProvider = function(config){\r
18242     Ext.state.CookieProvider.superclass.constructor.call(this);\r
18243     this.path = "/";\r
18244     this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days\r
18245     this.domain = null;\r
18246     this.secure = false;\r
18247     Ext.apply(this, config);\r
18248     this.state = this.readCookies();\r
18249 };\r
18250 \r
18251 Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {\r
18252     // private\r
18253     set : function(name, value){\r
18254         if(typeof value == "undefined" || value === null){\r
18255             this.clear(name);\r
18256             return;\r
18257         }\r
18258         this.setCookie(name, value);\r
18259         Ext.state.CookieProvider.superclass.set.call(this, name, value);\r
18260     },\r
18261 \r
18262     // private\r
18263     clear : function(name){\r
18264         this.clearCookie(name);\r
18265         Ext.state.CookieProvider.superclass.clear.call(this, name);\r
18266     },\r
18267 \r
18268     // private\r
18269     readCookies : function(){\r
18270         var cookies = {};\r
18271         var c = document.cookie + ";";\r
18272         var re = /\s?(.*?)=(.*?);/g;\r
18273         var matches;\r
18274         while((matches = re.exec(c)) != null){\r
18275             var name = matches[1];\r
18276             var value = matches[2];\r
18277             if(name && name.substring(0,3) == "ys-"){\r
18278                 cookies[name.substr(3)] = this.decodeValue(value);\r
18279             }\r
18280         }\r
18281         return cookies;\r
18282     },\r
18283 \r
18284     // private\r
18285     setCookie : function(name, value){\r
18286         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +\r
18287            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +\r
18288            ((this.path == null) ? "" : ("; path=" + this.path)) +\r
18289            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +\r
18290            ((this.secure == true) ? "; secure" : "");\r
18291     },\r
18292 \r
18293     // private\r
18294     clearCookie : function(name){\r
18295         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +\r
18296            ((this.path == null) ? "" : ("; path=" + this.path)) +\r
18297            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +\r
18298            ((this.secure == true) ? "; secure" : "");\r
18299     }\r
18300 });\r
18301 \r
18302 Ext.DataView = Ext.extend(Ext.BoxComponent, {\r
18303     \r
18304     \r
18305     \r
18306     \r
18307     \r
18308     \r
18309     \r
18310     \r
18311     \r
18312     selectedClass : "x-view-selected",\r
18313     \r
18314     emptyText : "",\r
18315 \r
18316     \r
18317     deferEmptyText: true,\r
18318     \r
18319     trackOver: false,\r
18320 \r
18321     //private\r
18322     last: false,\r
18323 \r
18324 \r
18325     // private\r
18326     initComponent : function(){\r
18327         Ext.DataView.superclass.initComponent.call(this);\r
18328         if(typeof this.tpl == "string"){\r
18329             this.tpl = new Ext.XTemplate(this.tpl);\r
18330         }\r
18331 \r
18332         this.addEvents(\r
18333             \r
18334             "beforeclick",\r
18335             \r
18336             "click",\r
18337             \r
18338             "mouseenter",\r
18339             \r
18340             "mouseleave",\r
18341             \r
18342             "containerclick",\r
18343             \r
18344             "dblclick",\r
18345             \r
18346             "contextmenu",\r
18347             \r
18348             "selectionchange",\r
18349 \r
18350             \r
18351             "beforeselect"\r
18352         );\r
18353 \r
18354         this.all = new Ext.CompositeElementLite();\r
18355         this.selected = new Ext.CompositeElementLite();\r
18356     },\r
18357 \r
18358     // private\r
18359     onRender : function(){\r
18360         if(!this.el){\r
18361             this.el = document.createElement('div');\r
18362             this.el.id = this.id;\r
18363         }\r
18364         Ext.DataView.superclass.onRender.apply(this, arguments);\r
18365     },\r
18366 \r
18367     // private\r
18368     afterRender : function(){\r
18369         Ext.DataView.superclass.afterRender.call(this);\r
18370 \r
18371         this.el.on({\r
18372             "click": this.onClick,\r
18373             "dblclick": this.onDblClick,\r
18374             "contextmenu": this.onContextMenu,\r
18375             scope:this\r
18376         });\r
18377 \r
18378         if(this.overClass || this.trackOver){\r
18379             this.el.on({\r
18380                 "mouseover": this.onMouseOver,\r
18381                 "mouseout": this.onMouseOut,\r
18382                 scope:this\r
18383             });\r
18384         }\r
18385 \r
18386         if(this.store){\r
18387             this.setStore(this.store, true);\r
18388         }\r
18389     },\r
18390 \r
18391     \r
18392     refresh : function(){\r
18393         this.clearSelections(false, true);\r
18394         this.el.update("");\r
18395         var records = this.store.getRange();\r
18396         if(records.length < 1){\r
18397             if(!this.deferEmptyText || this.hasSkippedEmptyText){\r
18398                 this.el.update(this.emptyText);\r
18399             }\r
18400             this.hasSkippedEmptyText = true;\r
18401             this.all.clear();\r
18402             return;\r
18403         }\r
18404         this.tpl.overwrite(this.el, this.collectData(records, 0));\r
18405         this.all.fill(Ext.query(this.itemSelector, this.el.dom));\r
18406         this.updateIndexes(0);\r
18407     },\r
18408 \r
18409     \r
18410     prepareData : function(data){\r
18411         return data;\r
18412     },\r
18413 \r
18414     \r
18415     collectData : function(records, startIndex){\r
18416         var r = [];\r
18417         for(var i = 0, len = records.length; i < len; i++){\r
18418             r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);\r
18419         }\r
18420         return r;\r
18421     },\r
18422 \r
18423     // private\r
18424     bufferRender : function(records){\r
18425         var div = document.createElement('div');\r
18426         this.tpl.overwrite(div, this.collectData(records));\r
18427         return Ext.query(this.itemSelector, div);\r
18428     },\r
18429 \r
18430     // private\r
18431     onUpdate : function(ds, record){\r
18432         var index = this.store.indexOf(record);\r
18433         var sel = this.isSelected(index);\r
18434         var original = this.all.elements[index];\r
18435         var node = this.bufferRender([record], index)[0];\r
18436 \r
18437         this.all.replaceElement(index, node, true);\r
18438         if(sel){\r
18439             this.selected.replaceElement(original, node);\r
18440             this.all.item(index).addClass(this.selectedClass);\r
18441         }\r
18442         this.updateIndexes(index, index);\r
18443     },\r
18444 \r
18445     // private\r
18446     onAdd : function(ds, records, index){\r
18447         if(this.all.getCount() == 0){\r
18448             this.refresh();\r
18449             return;\r
18450         }\r
18451         var nodes = this.bufferRender(records, index), n, a = this.all.elements;\r
18452         if(index < this.all.getCount()){\r
18453             n = this.all.item(index).insertSibling(nodes, 'before', true);\r
18454             a.splice.apply(a, [index, 0].concat(nodes));\r
18455         }else{\r
18456             n = this.all.last().insertSibling(nodes, 'after', true);\r
18457             a.push.apply(a, nodes);\r
18458         }\r
18459         this.updateIndexes(index);\r
18460     },\r
18461 \r
18462     // private\r
18463     onRemove : function(ds, record, index){\r
18464         this.deselect(index);\r
18465         this.all.removeElement(index, true);\r
18466         this.updateIndexes(index);\r
18467     },\r
18468 \r
18469     \r
18470     refreshNode : function(index){\r
18471         this.onUpdate(this.store, this.store.getAt(index));\r
18472     },\r
18473 \r
18474     // private\r
18475     updateIndexes : function(startIndex, endIndex){\r
18476         var ns = this.all.elements;\r
18477         startIndex = startIndex || 0;\r
18478         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));\r
18479         for(var i = startIndex; i <= endIndex; i++){\r
18480             ns[i].viewIndex = i;\r
18481         }\r
18482     },\r
18483     \r
18484     \r
18485     getStore : function(){\r
18486         return this.store;\r
18487     },\r
18488 \r
18489     \r
18490     setStore : function(store, initial){\r
18491         if(!initial && this.store){\r
18492             this.store.un("beforeload", this.onBeforeLoad, this);\r
18493             this.store.un("datachanged", this.refresh, this);\r
18494             this.store.un("add", this.onAdd, this);\r
18495             this.store.un("remove", this.onRemove, this);\r
18496             this.store.un("update", this.onUpdate, this);\r
18497             this.store.un("clear", this.refresh, this);\r
18498         }\r
18499         if(store){\r
18500             store = Ext.StoreMgr.lookup(store);\r
18501             store.on("beforeload", this.onBeforeLoad, this);\r
18502             store.on("datachanged", this.refresh, this);\r
18503             store.on("add", this.onAdd, this);\r
18504             store.on("remove", this.onRemove, this);\r
18505             store.on("update", this.onUpdate, this);\r
18506             store.on("clear", this.refresh, this);\r
18507         }\r
18508         this.store = store;\r
18509         if(store){\r
18510             this.refresh();\r
18511         }\r
18512     },\r
18513 \r
18514     \r
18515     findItemFromChild : function(node){\r
18516         return Ext.fly(node).findParent(this.itemSelector, this.el);\r
18517     },\r
18518 \r
18519     // private\r
18520     onClick : function(e){\r
18521         var item = e.getTarget(this.itemSelector, this.el);\r
18522         if(item){\r
18523             var index = this.indexOf(item);\r
18524             if(this.onItemClick(item, index, e) !== false){\r
18525                 this.fireEvent("click", this, index, item, e);\r
18526             }\r
18527         }else{\r
18528             if(this.fireEvent("containerclick", this, e) !== false){\r
18529                 this.clearSelections();\r
18530             }\r
18531         }\r
18532     },\r
18533 \r
18534     // private\r
18535     onContextMenu : function(e){\r
18536         var item = e.getTarget(this.itemSelector, this.el);\r
18537         if(item){\r
18538             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);\r
18539         }\r
18540     },\r
18541 \r
18542     // private\r
18543     onDblClick : function(e){\r
18544         var item = e.getTarget(this.itemSelector, this.el);\r
18545         if(item){\r
18546             this.fireEvent("dblclick", this, this.indexOf(item), item, e);\r
18547         }\r
18548     },\r
18549 \r
18550     // private\r
18551     onMouseOver : function(e){\r
18552         var item = e.getTarget(this.itemSelector, this.el);\r
18553         if(item && item !== this.lastItem){\r
18554             this.lastItem = item;\r
18555             Ext.fly(item).addClass(this.overClass);\r
18556             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);\r
18557         }\r
18558     },\r
18559 \r
18560     // private\r
18561     onMouseOut : function(e){\r
18562         if(this.lastItem){\r
18563             if(!e.within(this.lastItem, true, true)){\r
18564                 Ext.fly(this.lastItem).removeClass(this.overClass);\r
18565                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);\r
18566                 delete this.lastItem;\r
18567             }\r
18568         }\r
18569     },\r
18570 \r
18571     // private\r
18572     onItemClick : function(item, index, e){\r
18573         if(this.fireEvent("beforeclick", this, index, item, e) === false){\r
18574             return false;\r
18575         }\r
18576         if(this.multiSelect){\r
18577             this.doMultiSelection(item, index, e);\r
18578             e.preventDefault();\r
18579         }else if(this.singleSelect){\r
18580             this.doSingleSelection(item, index, e);\r
18581             e.preventDefault();\r
18582         }\r
18583         return true;\r
18584     },\r
18585 \r
18586     // private\r
18587     doSingleSelection : function(item, index, e){\r
18588         if(e.ctrlKey && this.isSelected(index)){\r
18589             this.deselect(index);\r
18590         }else{\r
18591             this.select(index, false);\r
18592         }\r
18593     },\r
18594 \r
18595     // private\r
18596     doMultiSelection : function(item, index, e){\r
18597         if(e.shiftKey && this.last !== false){\r
18598             var last = this.last;\r
18599             this.selectRange(last, index, e.ctrlKey);\r
18600             this.last = last; // reset the last\r
18601         }else{\r
18602             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){\r
18603                 this.deselect(index);\r
18604             }else{\r
18605                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);\r
18606             }\r
18607         }\r
18608     },\r
18609 \r
18610     \r
18611     getSelectionCount : function(){\r
18612         return this.selected.getCount()\r
18613     },\r
18614 \r
18615     \r
18616     getSelectedNodes : function(){\r
18617         return this.selected.elements;\r
18618     },\r
18619 \r
18620     \r
18621     getSelectedIndexes : function(){\r
18622         var indexes = [], s = this.selected.elements;\r
18623         for(var i = 0, len = s.length; i < len; i++){\r
18624             indexes.push(s[i].viewIndex);\r
18625         }\r
18626         return indexes;\r
18627     },\r
18628 \r
18629     \r
18630     getSelectedRecords : function(){\r
18631         var r = [], s = this.selected.elements;\r
18632         for(var i = 0, len = s.length; i < len; i++){\r
18633             r[r.length] = this.store.getAt(s[i].viewIndex);\r
18634         }\r
18635         return r;\r
18636     },\r
18637 \r
18638     \r
18639     getRecords : function(nodes){\r
18640         var r = [], s = nodes;\r
18641         for(var i = 0, len = s.length; i < len; i++){\r
18642             r[r.length] = this.store.getAt(s[i].viewIndex);\r
18643         }\r
18644         return r;\r
18645     },\r
18646 \r
18647     \r
18648     getRecord : function(node){\r
18649         return this.store.getAt(node.viewIndex);\r
18650     },\r
18651 \r
18652     \r
18653     clearSelections : function(suppressEvent, skipUpdate){\r
18654         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){\r
18655             if(!skipUpdate){\r
18656                 this.selected.removeClass(this.selectedClass);\r
18657             }\r
18658             this.selected.clear();\r
18659             this.last = false;\r
18660             if(!suppressEvent){\r
18661                 this.fireEvent("selectionchange", this, this.selected.elements);\r
18662             }\r
18663         }\r
18664     },\r
18665 \r
18666     \r
18667     isSelected : function(node){\r
18668         return this.selected.contains(this.getNode(node));\r
18669     },\r
18670 \r
18671     \r
18672     deselect : function(node){\r
18673         if(this.isSelected(node)){\r
18674             node = this.getNode(node);\r
18675             this.selected.removeElement(node);\r
18676             if(this.last == node.viewIndex){\r
18677                 this.last = false;\r
18678             }\r
18679             Ext.fly(node).removeClass(this.selectedClass);\r
18680             this.fireEvent("selectionchange", this, this.selected.elements);\r
18681         }\r
18682     },\r
18683 \r
18684     \r
18685     select : function(nodeInfo, keepExisting, suppressEvent){\r
18686         if(Ext.isArray(nodeInfo)){\r
18687             if(!keepExisting){\r
18688                 this.clearSelections(true);\r
18689             }\r
18690             for(var i = 0, len = nodeInfo.length; i < len; i++){\r
18691                 this.select(nodeInfo[i], true, true);\r
18692             }\r
18693                 if(!suppressEvent){\r
18694                     this.fireEvent("selectionchange", this, this.selected.elements);\r
18695                 }\r
18696         } else{\r
18697             var node = this.getNode(nodeInfo);\r
18698             if(!keepExisting){\r
18699                 this.clearSelections(true);\r
18700             }\r
18701             if(node && !this.isSelected(node)){\r
18702                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){\r
18703                     Ext.fly(node).addClass(this.selectedClass);\r
18704                     this.selected.add(node);\r
18705                     this.last = node.viewIndex;\r
18706                     if(!suppressEvent){\r
18707                         this.fireEvent("selectionchange", this, this.selected.elements);\r
18708                     }\r
18709                 }\r
18710             }\r
18711         }\r
18712     },\r
18713 \r
18714     \r
18715     selectRange : function(start, end, keepExisting){\r
18716         if(!keepExisting){\r
18717             this.clearSelections(true);\r
18718         }\r
18719         this.select(this.getNodes(start, end), true);\r
18720     },\r
18721 \r
18722     \r
18723     getNode : function(nodeInfo){\r
18724         if(typeof nodeInfo == "string"){\r
18725             return document.getElementById(nodeInfo);\r
18726         }else if(typeof nodeInfo == "number"){\r
18727             return this.all.elements[nodeInfo];\r
18728         }\r
18729         return nodeInfo;\r
18730     },\r
18731 \r
18732     \r
18733     getNodes : function(start, end){\r
18734         var ns = this.all.elements;\r
18735         start = start || 0;\r
18736         end = typeof end == "undefined" ? Math.max(ns.length - 1, 0) : end;\r
18737         var nodes = [], i;\r
18738         if(start <= end){\r
18739             for(i = start; i <= end && ns[i]; i++){\r
18740                 nodes.push(ns[i]);\r
18741             }\r
18742         } else{\r
18743             for(i = start; i >= end && ns[i]; i--){\r
18744                 nodes.push(ns[i]);\r
18745             }\r
18746         }\r
18747         return nodes;\r
18748     },\r
18749 \r
18750     \r
18751     indexOf : function(node){\r
18752         node = this.getNode(node);\r
18753         if(typeof node.viewIndex == "number"){\r
18754             return node.viewIndex;\r
18755         }\r
18756         return this.all.indexOf(node);\r
18757     },\r
18758 \r
18759     // private\r
18760     onBeforeLoad : function(){\r
18761         if(this.loadingText){\r
18762             this.clearSelections(false, true);\r
18763             this.el.update('<div class="loading-indicator">'+this.loadingText+'</div>');\r
18764             this.all.clear();\r
18765         }\r
18766     },\r
18767 \r
18768     onDestroy : function(){\r
18769         Ext.DataView.superclass.onDestroy.call(this);\r
18770         this.setStore(null);\r
18771     }\r
18772 });\r
18773 \r
18774 Ext.reg('dataview', Ext.DataView);\r
18775 \r
18776 Ext.ColorPalette = function(config){\r
18777     Ext.ColorPalette.superclass.constructor.call(this, config);\r
18778     this.addEvents(\r
18779         \r
18780         'select'\r
18781     );\r
18782 \r
18783     if(this.handler){\r
18784         this.on("select", this.handler, this.scope, true);\r
18785     }\r
18786 };\r
18787 Ext.extend(Ext.ColorPalette, Ext.Component, {\r
18788         \r
18789     \r
18790     itemCls : "x-color-palette",\r
18791     \r
18792     value : null,\r
18793     clickEvent:'click',\r
18794     // private\r
18795     ctype: "Ext.ColorPalette",\r
18796 \r
18797     \r
18798     allowReselect : false,\r
18799 \r
18800     \r
18801     colors : [\r
18802         "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",\r
18803         "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",\r
18804         "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",\r
18805         "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",\r
18806         "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"\r
18807     ],\r
18808 \r
18809     // private\r
18810     onRender : function(container, position){\r
18811         var t = this.tpl || new Ext.XTemplate(\r
18812             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'\r
18813         );\r
18814         var el = document.createElement("div");\r
18815         el.id = this.getId();\r
18816         el.className = this.itemCls;\r
18817         t.overwrite(el, this.colors);\r
18818         container.dom.insertBefore(el, position);\r
18819         this.el = Ext.get(el);\r
18820         this.el.on(this.clickEvent, this.handleClick,  this, {delegate: "a"});\r
18821         if(this.clickEvent != 'click'){\r
18822             this.el.on('click', Ext.emptyFn,  this, {delegate: "a", preventDefault:true});\r
18823         }\r
18824     },\r
18825 \r
18826     // private\r
18827     afterRender : function(){\r
18828         Ext.ColorPalette.superclass.afterRender.call(this);\r
18829         if(this.value){\r
18830             var s = this.value;\r
18831             this.value = null;\r
18832             this.select(s);\r
18833         }\r
18834     },\r
18835 \r
18836     // private\r
18837     handleClick : function(e, t){\r
18838         e.preventDefault();\r
18839         if(!this.disabled){\r
18840             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];\r
18841             this.select(c.toUpperCase());\r
18842         }\r
18843     },\r
18844 \r
18845     \r
18846     select : function(color){\r
18847         color = color.replace("#", "");\r
18848         if(color != this.value || this.allowReselect){\r
18849             var el = this.el;\r
18850             if(this.value){\r
18851                 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");\r
18852             }\r
18853             el.child("a.color-"+color).addClass("x-color-palette-sel");\r
18854             this.value = color;\r
18855             this.fireEvent("select", this, color);\r
18856         }\r
18857     }\r
18858 \r
18859     \r
18860 });\r
18861 Ext.reg('colorpalette', Ext.ColorPalette);\r
18862 \r
18863 Ext.DatePicker = Ext.extend(Ext.Component, {\r
18864     \r
18865     todayText : "Today",\r
18866     \r
18867     okText : "&#160;OK&#160;", // &#160; to give the user extra clicking room\r
18868     \r
18869     cancelText : "Cancel",\r
18870     \r
18871     todayTip : "{0} (Spacebar)",\r
18872     \r
18873     minText : "This date is before the minimum date",\r
18874     \r
18875     maxText : "This date is after the maximum date",\r
18876     \r
18877     format : "m/d/y",\r
18878     \r
18879     disabledDaysText : "Disabled",\r
18880     \r
18881     disabledDatesText : "Disabled",\r
18882     \r
18883     constrainToViewport : true,\r
18884     \r
18885     monthNames : Date.monthNames,\r
18886     \r
18887     dayNames : Date.dayNames,\r
18888     \r
18889     nextText: 'Next Month (Control+Right)',\r
18890     \r
18891     prevText: 'Previous Month (Control+Left)',\r
18892     \r
18893     monthYearText: 'Choose a month (Control+Up/Down to move years)',\r
18894     \r
18895     startDay : 0,\r
18896     \r
18897     showToday : true,\r
18898     \r
18899     \r
18900     \r
18901     \r
18902     \r
18903 \r
18904     // private\r
18905     initComponent : function(){\r
18906         Ext.DatePicker.superclass.initComponent.call(this);\r
18907 \r
18908         this.value = this.value ?\r
18909                  this.value.clearTime() : new Date().clearTime();\r
18910 \r
18911         this.addEvents(\r
18912             \r
18913             'select'\r
18914         );\r
18915 \r
18916         if(this.handler){\r
18917             this.on("select", this.handler,  this.scope || this);\r
18918         }\r
18919 \r
18920         this.initDisabledDays();\r
18921     },\r
18922 \r
18923     // private\r
18924     initDisabledDays : function(){\r
18925         if(!this.disabledDatesRE && this.disabledDates){\r
18926             var dd = this.disabledDates;\r
18927             var re = "(?:";\r
18928             for(var i = 0; i < dd.length; i++){\r
18929                 re += dd[i];\r
18930                 if(i != dd.length-1) re += "|";\r
18931             }\r
18932             this.disabledDatesRE = new RegExp(re + ")");\r
18933         }\r
18934     },\r
18935     \r
18936     \r
18937     setDisabledDates : function(dd){\r
18938         if(Ext.isArray(dd)){\r
18939             this.disabledDates = dd;\r
18940             this.disabledDatesRE = null;\r
18941         }else{\r
18942             this.disabledDatesRE = dd;\r
18943         }\r
18944         this.initDisabledDays();\r
18945         this.update(this.value, true);\r
18946     },\r
18947     \r
18948     \r
18949     setDisabledDays : function(dd){\r
18950         this.disabledDays = dd;\r
18951         this.update(this.value, true);\r
18952     },\r
18953     \r
18954     \r
18955     setMinDate : function(dt){\r
18956         this.minDate = dt;\r
18957         this.update(this.value, true);\r
18958     },\r
18959     \r
18960     \r
18961     setMaxDate : function(dt){\r
18962         this.maxDate = dt;\r
18963         this.update(this.value, true);\r
18964     },\r
18965 \r
18966     \r
18967     setValue : function(value){\r
18968         var old = this.value;\r
18969         this.value = value.clearTime(true);\r
18970         if(this.el){\r
18971             this.update(this.value);\r
18972         }\r
18973     },\r
18974 \r
18975     \r
18976     getValue : function(){\r
18977         return this.value;\r
18978     },\r
18979 \r
18980     // private\r
18981     focus : function(){\r
18982         if(this.el){\r
18983             this.update(this.activeDate);\r
18984         }\r
18985     },\r
18986 \r
18987     // private\r
18988     onRender : function(container, position){\r
18989         var m = [\r
18990              '<table cellspacing="0">',\r
18991                 '<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>',\r
18992                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];\r
18993         var dn = this.dayNames;\r
18994         for(var i = 0; i < 7; i++){\r
18995             var d = this.startDay+i;\r
18996             if(d > 6){\r
18997                 d = d-7;\r
18998             }\r
18999             m.push("<th><span>", dn[d].substr(0,1), "</span></th>");\r
19000         }\r
19001         m[m.length] = "</tr></thead><tbody><tr>";\r
19002         for(var i = 0; i < 42; i++) {\r
19003             if(i % 7 == 0 && i != 0){\r
19004                 m[m.length] = "</tr><tr>";\r
19005             }\r
19006             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';\r
19007         }\r
19008         m.push('</tr></tbody></table></td></tr>', \r
19009                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '', \r
19010                 '</table><div class="x-date-mp"></div>');\r
19011 \r
19012         var el = document.createElement("div");\r
19013         el.className = "x-date-picker";\r
19014         el.innerHTML = m.join("");\r
19015 \r
19016         container.dom.insertBefore(el, position);\r
19017 \r
19018         this.el = Ext.get(el);\r
19019         this.eventEl = Ext.get(el.firstChild);\r
19020 \r
19021         this.leftClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {\r
19022             handler: this.showPrevMonth,\r
19023             scope: this,\r
19024             preventDefault:true,\r
19025             stopDefault:true\r
19026         });\r
19027 \r
19028         this.rightClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {\r
19029             handler: this.showNextMonth,\r
19030             scope: this,\r
19031             preventDefault:true,\r
19032             stopDefault:true\r
19033         });\r
19034 \r
19035         this.eventEl.on("mousewheel", this.handleMouseWheel,  this);\r
19036 \r
19037         this.monthPicker = this.el.down('div.x-date-mp');\r
19038         this.monthPicker.enableDisplayMode('block');\r
19039         \r
19040         var kn = new Ext.KeyNav(this.eventEl, {\r
19041             "left" : function(e){\r
19042                 e.ctrlKey ?\r
19043                     this.showPrevMonth() :\r
19044                     this.update(this.activeDate.add("d", -1));\r
19045             },\r
19046 \r
19047             "right" : function(e){\r
19048                 e.ctrlKey ?\r
19049                     this.showNextMonth() :\r
19050                     this.update(this.activeDate.add("d", 1));\r
19051             },\r
19052 \r
19053             "up" : function(e){\r
19054                 e.ctrlKey ?\r
19055                     this.showNextYear() :\r
19056                     this.update(this.activeDate.add("d", -7));\r
19057             },\r
19058 \r
19059             "down" : function(e){\r
19060                 e.ctrlKey ?\r
19061                     this.showPrevYear() :\r
19062                     this.update(this.activeDate.add("d", 7));\r
19063             },\r
19064 \r
19065             "pageUp" : function(e){\r
19066                 this.showNextMonth();\r
19067             },\r
19068 \r
19069             "pageDown" : function(e){\r
19070                 this.showPrevMonth();\r
19071             },\r
19072 \r
19073             "enter" : function(e){\r
19074                 e.stopPropagation();\r
19075                 return true;\r
19076             },\r
19077 \r
19078             scope : this\r
19079         });\r
19080 \r
19081         this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});\r
19082 \r
19083         this.el.unselectable();\r
19084         \r
19085         this.cells = this.el.select("table.x-date-inner tbody td");\r
19086         this.textNodes = this.el.query("table.x-date-inner tbody span");\r
19087 \r
19088         this.mbtn = new Ext.Button({\r
19089             text: "&#160;",\r
19090             tooltip: this.monthYearText,\r
19091             renderTo: this.el.child("td.x-date-middle", true)\r
19092         });\r
19093 \r
19094         this.mbtn.on('click', this.showMonthPicker, this);\r
19095         this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");\r
19096 \r
19097         if(this.showToday){\r
19098             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);\r
19099             var today = (new Date()).dateFormat(this.format);\r
19100             this.todayBtn = new Ext.Button({\r
19101                 renderTo: this.el.child("td.x-date-bottom", true),\r
19102                 text: String.format(this.todayText, today),\r
19103                 tooltip: String.format(this.todayTip, today),\r
19104                 handler: this.selectToday,\r
19105                 scope: this\r
19106             });\r
19107         }\r
19108         \r
19109         if(Ext.isIE){\r
19110             this.el.repaint();\r
19111         }\r
19112         this.update(this.value);\r
19113     },\r
19114 \r
19115     // private\r
19116     createMonthPicker : function(){\r
19117         if(!this.monthPicker.dom.firstChild){\r
19118             var buf = ['<table border="0" cellspacing="0">'];\r
19119             for(var i = 0; i < 6; i++){\r
19120                 buf.push(\r
19121                     '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',\r
19122                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',\r
19123                     i == 0 ?\r
19124                     '<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>' :\r
19125                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'\r
19126                 );\r
19127             }\r
19128             buf.push(\r
19129                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',\r
19130                     this.okText,\r
19131                     '</button><button type="button" class="x-date-mp-cancel">',\r
19132                     this.cancelText,\r
19133                     '</button></td></tr>',\r
19134                 '</table>'\r
19135             );\r
19136             this.monthPicker.update(buf.join(''));\r
19137             this.monthPicker.on('click', this.onMonthClick, this);\r
19138             this.monthPicker.on('dblclick', this.onMonthDblClick, this);\r
19139 \r
19140             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');\r
19141             this.mpYears = this.monthPicker.select('td.x-date-mp-year');\r
19142 \r
19143             this.mpMonths.each(function(m, a, i){\r
19144                 i += 1;\r
19145                 if((i%2) == 0){\r
19146                     m.dom.xmonth = 5 + Math.round(i * .5);\r
19147                 }else{\r
19148                     m.dom.xmonth = Math.round((i-1) * .5);\r
19149                 }\r
19150             });\r
19151         }\r
19152     },\r
19153 \r
19154     // private\r
19155     showMonthPicker : function(){\r
19156         this.createMonthPicker();\r
19157         var size = this.el.getSize();\r
19158         this.monthPicker.setSize(size);\r
19159         this.monthPicker.child('table').setSize(size);\r
19160 \r
19161         this.mpSelMonth = (this.activeDate || this.value).getMonth();\r
19162         this.updateMPMonth(this.mpSelMonth);\r
19163         this.mpSelYear = (this.activeDate || this.value).getFullYear();\r
19164         this.updateMPYear(this.mpSelYear);\r
19165 \r
19166         this.monthPicker.slideIn('t', {duration:.2});\r
19167     },\r
19168 \r
19169     // private\r
19170     updateMPYear : function(y){\r
19171         this.mpyear = y;\r
19172         var ys = this.mpYears.elements;\r
19173         for(var i = 1; i <= 10; i++){\r
19174             var td = ys[i-1], y2;\r
19175             if((i%2) == 0){\r
19176                 y2 = y + Math.round(i * .5);\r
19177                 td.firstChild.innerHTML = y2;\r
19178                 td.xyear = y2;\r
19179             }else{\r
19180                 y2 = y - (5-Math.round(i * .5));\r
19181                 td.firstChild.innerHTML = y2;\r
19182                 td.xyear = y2;\r
19183             }\r
19184             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
19185         }\r
19186     },\r
19187 \r
19188     // private\r
19189     updateMPMonth : function(sm){\r
19190         this.mpMonths.each(function(m, a, i){\r
19191             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
19192         });\r
19193     },\r
19194 \r
19195     // private\r
19196     selectMPMonth: function(m){\r
19197         \r
19198     },\r
19199 \r
19200     // private\r
19201     onMonthClick : function(e, t){\r
19202         e.stopEvent();\r
19203         var el = new Ext.Element(t), pn;\r
19204         if(el.is('button.x-date-mp-cancel')){\r
19205             this.hideMonthPicker();\r
19206         }\r
19207         else if(el.is('button.x-date-mp-ok')){\r
19208             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\r
19209             if(d.getMonth() != this.mpSelMonth){\r
19210                 // "fix" the JS rolling date conversion if needed\r
19211                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();\r
19212             }\r
19213             this.update(d);\r
19214             this.hideMonthPicker();\r
19215         }\r
19216         else if(pn = el.up('td.x-date-mp-month', 2)){\r
19217             this.mpMonths.removeClass('x-date-mp-sel');\r
19218             pn.addClass('x-date-mp-sel');\r
19219             this.mpSelMonth = pn.dom.xmonth;\r
19220         }\r
19221         else if(pn = el.up('td.x-date-mp-year', 2)){\r
19222             this.mpYears.removeClass('x-date-mp-sel');\r
19223             pn.addClass('x-date-mp-sel');\r
19224             this.mpSelYear = pn.dom.xyear;\r
19225         }\r
19226         else if(el.is('a.x-date-mp-prev')){\r
19227             this.updateMPYear(this.mpyear-10);\r
19228         }\r
19229         else if(el.is('a.x-date-mp-next')){\r
19230             this.updateMPYear(this.mpyear+10);\r
19231         }\r
19232     },\r
19233 \r
19234     // private\r
19235     onMonthDblClick : function(e, t){\r
19236         e.stopEvent();\r
19237         var el = new Ext.Element(t), pn;\r
19238         if(pn = el.up('td.x-date-mp-month', 2)){\r
19239             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));\r
19240             this.hideMonthPicker();\r
19241         }\r
19242         else if(pn = el.up('td.x-date-mp-year', 2)){\r
19243             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\r
19244             this.hideMonthPicker();\r
19245         }\r
19246     },\r
19247 \r
19248     // private\r
19249     hideMonthPicker : function(disableAnim){\r
19250         if(this.monthPicker){\r
19251             if(disableAnim === true){\r
19252                 this.monthPicker.hide();\r
19253             }else{\r
19254                 this.monthPicker.slideOut('t', {duration:.2});\r
19255             }\r
19256         }\r
19257     },\r
19258 \r
19259     // private\r
19260     showPrevMonth : function(e){\r
19261         this.update(this.activeDate.add("mo", -1));\r
19262     },\r
19263 \r
19264     // private\r
19265     showNextMonth : function(e){\r
19266         this.update(this.activeDate.add("mo", 1));\r
19267     },\r
19268 \r
19269     // private\r
19270     showPrevYear : function(){\r
19271         this.update(this.activeDate.add("y", -1));\r
19272     },\r
19273 \r
19274     // private\r
19275     showNextYear : function(){\r
19276         this.update(this.activeDate.add("y", 1));\r
19277     },\r
19278 \r
19279     // private\r
19280     handleMouseWheel : function(e){\r
19281         var delta = e.getWheelDelta();\r
19282         if(delta > 0){\r
19283             this.showPrevMonth();\r
19284             e.stopEvent();\r
19285         } else if(delta < 0){\r
19286             this.showNextMonth();\r
19287             e.stopEvent();\r
19288         }\r
19289     },\r
19290 \r
19291     // private\r
19292     handleDateClick : function(e, t){\r
19293         e.stopEvent();\r
19294         if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){\r
19295             this.setValue(new Date(t.dateValue));\r
19296             this.fireEvent("select", this, this.value);\r
19297         }\r
19298     },\r
19299 \r
19300     // private\r
19301     selectToday : function(){\r
19302         if(this.todayBtn && !this.todayBtn.disabled){\r
19303                 this.setValue(new Date().clearTime());\r
19304                 this.fireEvent("select", this, this.value);\r
19305         }\r
19306     },\r
19307 \r
19308     // private\r
19309     update : function(date, forceRefresh){\r
19310         var vd = this.activeDate;\r
19311         this.activeDate = date;\r
19312         if(!forceRefresh && vd && this.el){\r
19313             var t = date.getTime();\r
19314             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){\r
19315                 this.cells.removeClass("x-date-selected");\r
19316                 this.cells.each(function(c){\r
19317                    if(c.dom.firstChild.dateValue == t){\r
19318                        c.addClass("x-date-selected");\r
19319                        setTimeout(function(){\r
19320                             try{c.dom.firstChild.focus();}catch(e){}\r
19321                        }, 50);\r
19322                        return false;\r
19323                    }\r
19324                 });\r
19325                 return;\r
19326             }\r
19327         }\r
19328         var days = date.getDaysInMonth();\r
19329         var firstOfMonth = date.getFirstDateOfMonth();\r
19330         var startingPos = firstOfMonth.getDay()-this.startDay;\r
19331 \r
19332         if(startingPos <= this.startDay){\r
19333             startingPos += 7;\r
19334         }\r
19335 \r
19336         var pm = date.add("mo", -1);\r
19337         var prevStart = pm.getDaysInMonth()-startingPos;\r
19338 \r
19339         var cells = this.cells.elements;\r
19340         var textEls = this.textNodes;\r
19341         days += startingPos;\r
19342 \r
19343         // convert everything to numbers so it's fast\r
19344         var day = 86400000;\r
19345         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();\r
19346         var today = new Date().clearTime().getTime();\r
19347         var sel = date.clearTime().getTime();\r
19348         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;\r
19349         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;\r
19350         var ddMatch = this.disabledDatesRE;\r
19351         var ddText = this.disabledDatesText;\r
19352         var ddays = this.disabledDays ? this.disabledDays.join("") : false;\r
19353         var ddaysText = this.disabledDaysText;\r
19354         var format = this.format;\r
19355         \r
19356         if(this.showToday){\r
19357             var td = new Date().clearTime();\r
19358             var disable = (td < min || td > max || \r
19359                 (ddMatch && format && ddMatch.test(td.dateFormat(format))) || \r
19360                 (ddays && ddays.indexOf(td.getDay()) != -1));\r
19361                         \r
19362             this.todayBtn.setDisabled(disable);\r
19363             this.todayKeyListener[disable ? 'disable' : 'enable']();\r
19364         }\r
19365 \r
19366         var setCellClass = function(cal, cell){\r
19367             cell.title = "";\r
19368             var t = d.getTime();\r
19369             cell.firstChild.dateValue = t;\r
19370             if(t == today){\r
19371                 cell.className += " x-date-today";\r
19372                 cell.title = cal.todayText;\r
19373             }\r
19374             if(t == sel){\r
19375                 cell.className += " x-date-selected";\r
19376                 setTimeout(function(){\r
19377                     try{cell.firstChild.focus();}catch(e){}\r
19378                 }, 50);\r
19379             }\r
19380             // disabling\r
19381             if(t < min) {\r
19382                 cell.className = " x-date-disabled";\r
19383                 cell.title = cal.minText;\r
19384                 return;\r
19385             }\r
19386             if(t > max) {\r
19387                 cell.className = " x-date-disabled";\r
19388                 cell.title = cal.maxText;\r
19389                 return;\r
19390             }\r
19391             if(ddays){\r
19392                 if(ddays.indexOf(d.getDay()) != -1){\r
19393                     cell.title = ddaysText;\r
19394                     cell.className = " x-date-disabled";\r
19395                 }\r
19396             }\r
19397             if(ddMatch && format){\r
19398                 var fvalue = d.dateFormat(format);\r
19399                 if(ddMatch.test(fvalue)){\r
19400                     cell.title = ddText.replace("%0", fvalue);\r
19401                     cell.className = " x-date-disabled";\r
19402                 }\r
19403             }\r
19404         };\r
19405 \r
19406         var i = 0;\r
19407         for(; i < startingPos; i++) {\r
19408             textEls[i].innerHTML = (++prevStart);\r
19409             d.setDate(d.getDate()+1);\r
19410             cells[i].className = "x-date-prevday";\r
19411             setCellClass(this, cells[i]);\r
19412         }\r
19413         for(; i < days; i++){\r
19414             var intDay = i - startingPos + 1;\r
19415             textEls[i].innerHTML = (intDay);\r
19416             d.setDate(d.getDate()+1);\r
19417             cells[i].className = "x-date-active";\r
19418             setCellClass(this, cells[i]);\r
19419         }\r
19420         var extraDays = 0;\r
19421         for(; i < 42; i++) {\r
19422              textEls[i].innerHTML = (++extraDays);\r
19423              d.setDate(d.getDate()+1);\r
19424              cells[i].className = "x-date-nextday";\r
19425              setCellClass(this, cells[i]);\r
19426         }\r
19427 \r
19428         this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());\r
19429 \r
19430         if(!this.internalRender){\r
19431             var main = this.el.dom.firstChild;\r
19432             var w = main.offsetWidth;\r
19433             this.el.setWidth(w + this.el.getBorderWidth("lr"));\r
19434             Ext.fly(main).setWidth(w);\r
19435             this.internalRender = true;\r
19436             // opera does not respect the auto grow header center column\r
19437             // then, after it gets a width opera refuses to recalculate\r
19438             // without a second pass\r
19439             if(Ext.isOpera && !this.secondPass){\r
19440                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";\r
19441                 this.secondPass = true;\r
19442                 this.update.defer(10, this, [date]);\r
19443             }\r
19444         }\r
19445     },\r
19446 \r
19447     // private\r
19448     beforeDestroy : function() {\r
19449         if(this.rendered){\r
19450             Ext.destroy(\r
19451                 this.leftClickRpt,\r
19452                 this.rightClickRpt,\r
19453                 this.monthPicker,\r
19454                 this.eventEl,\r
19455                 this.mbtn,\r
19456                 this.todayBtn\r
19457             );\r
19458         }\r
19459     }\r
19460 \r
19461     \r
19462 });\r
19463 Ext.reg('datepicker', Ext.DatePicker);\r
19464 \r
19465 Ext.TabPanel = Ext.extend(Ext.Panel,  {\r
19466     \r
19467     \r
19468     \r
19469     monitorResize : true,\r
19470     \r
19471     deferredRender : true,\r
19472     \r
19473     tabWidth: 120,\r
19474     \r
19475     minTabWidth: 30,\r
19476     \r
19477     resizeTabs:false,\r
19478     \r
19479     enableTabScroll: false,\r
19480     \r
19481     scrollIncrement : 0,\r
19482     \r
19483     scrollRepeatInterval : 400,\r
19484     \r
19485     scrollDuration : .35,\r
19486     \r
19487     animScroll : true,\r
19488     \r
19489     tabPosition: 'top',\r
19490     \r
19491     baseCls: 'x-tab-panel',\r
19492     \r
19493     autoTabs : false,\r
19494     \r
19495     autoTabSelector:'div.x-tab',\r
19496     \r
19497     activeTab : null,\r
19498     \r
19499     tabMargin : 2,\r
19500     \r
19501     plain: false,\r
19502     \r
19503     wheelIncrement : 20,\r
19504 \r
19505     \r
19506     idDelimiter : '__',\r
19507 \r
19508     // private\r
19509     itemCls : 'x-tab-item',\r
19510 \r
19511     // private config overrides\r
19512     elements: 'body',\r
19513     headerAsText: false,\r
19514     frame: false,\r
19515     hideBorders:true,\r
19516 \r
19517     // private\r
19518     initComponent : function(){\r
19519         this.frame = false;\r
19520         Ext.TabPanel.superclass.initComponent.call(this);\r
19521         this.addEvents(\r
19522             \r
19523             'beforetabchange',\r
19524             \r
19525             'tabchange',\r
19526             \r
19527             'contextmenu'\r
19528         );\r
19529         this.setLayout(new Ext.layout.CardLayout({\r
19530             deferredRender: this.deferredRender\r
19531         }));\r
19532         if(this.tabPosition == 'top'){\r
19533             this.elements += ',header';\r
19534             this.stripTarget = 'header';\r
19535         }else {\r
19536             this.elements += ',footer';\r
19537             this.stripTarget = 'footer';\r
19538         }\r
19539         if(!this.stack){\r
19540             this.stack = Ext.TabPanel.AccessStack();\r
19541         }\r
19542         this.initItems();\r
19543     },\r
19544 \r
19545     // private\r
19546     render : function(){\r
19547         Ext.TabPanel.superclass.render.apply(this, arguments);\r
19548         if(this.activeTab !== undefined){\r
19549             var item = this.activeTab;\r
19550             delete this.activeTab;\r
19551             this.setActiveTab(item);\r
19552         }\r
19553     },\r
19554 \r
19555     // private\r
19556     onRender : function(ct, position){\r
19557         Ext.TabPanel.superclass.onRender.call(this, ct, position);\r
19558 \r
19559         if(this.plain){\r
19560             var pos = this.tabPosition == 'top' ? 'header' : 'footer';\r
19561             this[pos].addClass('x-tab-panel-'+pos+'-plain');\r
19562         }\r
19563 \r
19564         var st = this[this.stripTarget];\r
19565 \r
19566         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{\r
19567             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});\r
19568 \r
19569         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);\r
19570         this.stripSpacer = st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);\r
19571         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);\r
19572 \r
19573         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});\r
19574         this.strip.createChild({cls:'x-clear'});\r
19575 \r
19576         this.body.addClass('x-tab-panel-body-'+this.tabPosition);\r
19577 \r
19578         if(!this.itemTpl){\r
19579             var tt = new Ext.Template(\r
19580                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close" onclick="return false;"></a>',\r
19581                  '<a class="x-tab-right" href="#" onclick="return false;"><em class="x-tab-left">',\r
19582                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',\r
19583                  '</em></a></li>'\r
19584             );\r
19585             tt.disableFormats = true;\r
19586             tt.compile();\r
19587             Ext.TabPanel.prototype.itemTpl = tt;\r
19588         }\r
19589 \r
19590         this.items.each(this.initTab, this);\r
19591     },\r
19592 \r
19593     // private\r
19594     afterRender : function(){\r
19595         Ext.TabPanel.superclass.afterRender.call(this);\r
19596         if(this.autoTabs){\r
19597             this.readTabs(false);\r
19598         }\r
19599     },\r
19600 \r
19601     // private\r
19602     initEvents : function(){\r
19603         Ext.TabPanel.superclass.initEvents.call(this);\r
19604         this.on('add', this.onAdd, this);\r
19605         this.on('remove', this.onRemove, this);\r
19606 \r
19607         this.strip.on('mousedown', this.onStripMouseDown, this);\r
19608         this.strip.on('contextmenu', this.onStripContextMenu, this);\r
19609         if(this.enableTabScroll){\r
19610             this.strip.on('mousewheel', this.onWheel, this);\r
19611         }\r
19612     },\r
19613 \r
19614     // private\r
19615     findTargets : function(e){\r
19616         var item = null;\r
19617         var itemEl = e.getTarget('li', this.strip);\r
19618         if(itemEl){\r
19619             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);\r
19620             if(item.disabled){\r
19621                 return {\r
19622                     close : null,\r
19623                     item : null,\r
19624                     el : null\r
19625                 };\r
19626             }\r
19627         }\r
19628         return {\r
19629             close : e.getTarget('.x-tab-strip-close', this.strip),\r
19630             item : item,\r
19631             el : itemEl\r
19632         };\r
19633     },\r
19634 \r
19635     // private\r
19636     onStripMouseDown : function(e){\r
19637         if(e.button != 0){\r
19638             return;\r
19639         }\r
19640         e.preventDefault();\r
19641         var t = this.findTargets(e);\r
19642         if(t.close){\r
19643             this.remove(t.item);\r
19644             return;\r
19645         }\r
19646         if(t.item && t.item != this.activeTab){\r
19647             this.setActiveTab(t.item);\r
19648         }\r
19649     },\r
19650 \r
19651     // private\r
19652     onStripContextMenu : function(e){\r
19653         e.preventDefault();\r
19654         var t = this.findTargets(e);\r
19655         if(t.item){\r
19656             this.fireEvent('contextmenu', this, t.item, e);\r
19657         }\r
19658     },\r
19659 \r
19660     \r
19661     readTabs : function(removeExisting){\r
19662         if(removeExisting === true){\r
19663             this.items.each(function(item){\r
19664                 this.remove(item);\r
19665             }, this);\r
19666         }\r
19667         var tabs = this.el.query(this.autoTabSelector);\r
19668         for(var i = 0, len = tabs.length; i < len; i++){\r
19669             var tab = tabs[i];\r
19670             var title = tab.getAttribute('title');\r
19671             tab.removeAttribute('title');\r
19672             this.add({\r
19673                 title: title,\r
19674                 el: tab\r
19675             });\r
19676         }\r
19677     },\r
19678 \r
19679     // private\r
19680     initTab : function(item, index){\r
19681         var before = this.strip.dom.childNodes[index];\r
19682         var cls = item.closable ? 'x-tab-strip-closable' : '';\r
19683         if(item.disabled){\r
19684             cls += ' x-item-disabled';\r
19685         }\r
19686         if(item.iconCls){\r
19687             cls += ' x-tab-with-icon';\r
19688         }\r
19689         if(item.tabCls){\r
19690             cls += ' ' + item.tabCls;\r
19691         }\r
19692 \r
19693         var p = {\r
19694             id: this.id + this.idDelimiter + item.getItemId(),\r
19695             text: item.title,\r
19696             cls: cls,\r
19697             iconCls: item.iconCls || ''\r
19698         };\r
19699         var el = before ?\r
19700                  this.itemTpl.insertBefore(before, p) :\r
19701                  this.itemTpl.append(this.strip, p);\r
19702 \r
19703         Ext.fly(el).addClassOnOver('x-tab-strip-over');\r
19704 \r
19705         if(item.tabTip){\r
19706             Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;\r
19707         }\r
19708         item.tabEl = el;\r
19709 \r
19710         item.on('disable', this.onItemDisabled, this);\r
19711         item.on('enable', this.onItemEnabled, this);\r
19712         item.on('titlechange', this.onItemTitleChanged, this);\r
19713         item.on('iconchange', this.onItemIconChanged, this);\r
19714         item.on('beforeshow', this.onBeforeShowItem, this);\r
19715     },\r
19716 \r
19717     // private\r
19718     onAdd : function(tp, item, index){\r
19719         this.initTab(item, index);\r
19720         if(this.items.getCount() == 1){\r
19721             this.syncSize();\r
19722         }\r
19723         this.delegateUpdates();\r
19724     },\r
19725 \r
19726     // private\r
19727     onBeforeAdd : function(item){\r
19728         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);\r
19729         if(existing){\r
19730             this.setActiveTab(item);\r
19731             return false;\r
19732         }\r
19733         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);\r
19734         var es = item.elements;\r
19735         item.elements = es ? es.replace(',header', '') : es;\r
19736         item.border = (item.border === true);\r
19737     },\r
19738 \r
19739     // private\r
19740     onRemove : function(tp, item){\r
19741         Ext.destroy(Ext.get(this.getTabEl(item)));\r
19742         this.stack.remove(item);\r
19743         item.un('disable', this.onItemDisabled, this);\r
19744         item.un('enable', this.onItemEnabled, this);\r
19745         item.un('titlechange', this.onItemTitleChanged, this);\r
19746         item.un('iconchange', this.onItemIconChanged, this);\r
19747         item.un('beforeshow', this.onBeforeShowItem, this);\r
19748         if(item == this.activeTab){\r
19749             var next = this.stack.next();\r
19750             if(next){\r
19751                 this.setActiveTab(next);\r
19752             }else if(this.items.getCount() > 0){\r
19753                 this.setActiveTab(0);\r
19754             }else{\r
19755                 this.activeTab = null;\r
19756             }\r
19757         }\r
19758         this.delegateUpdates();\r
19759     },\r
19760 \r
19761     // private\r
19762     onBeforeShowItem : function(item){\r
19763         if(item != this.activeTab){\r
19764             this.setActiveTab(item);\r
19765             return false;\r
19766         }\r
19767     },\r
19768 \r
19769     // private\r
19770     onItemDisabled : function(item){\r
19771         var el = this.getTabEl(item);\r
19772         if(el){\r
19773             Ext.fly(el).addClass('x-item-disabled');\r
19774         }\r
19775         this.stack.remove(item);\r
19776     },\r
19777 \r
19778     // private\r
19779     onItemEnabled : function(item){\r
19780         var el = this.getTabEl(item);\r
19781         if(el){\r
19782             Ext.fly(el).removeClass('x-item-disabled');\r
19783         }\r
19784     },\r
19785 \r
19786     // private\r
19787     onItemTitleChanged : function(item){\r
19788         var el = this.getTabEl(item);\r
19789         if(el){\r
19790             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;\r
19791         }\r
19792     },\r
19793     \r
19794     //private\r
19795     onItemIconChanged: function(item, iconCls, oldCls){\r
19796         var el = this.getTabEl(item);\r
19797         if(el){\r
19798             Ext.fly(el).child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);\r
19799         }\r
19800     },\r
19801 \r
19802     \r
19803     getTabEl : function(item){\r
19804         var itemId = (typeof item === 'number')?this.items.items[item].getItemId() : item.getItemId();\r
19805         return document.getElementById(this.id+this.idDelimiter+itemId);\r
19806     },\r
19807 \r
19808     // private\r
19809     onResize : function(){\r
19810         Ext.TabPanel.superclass.onResize.apply(this, arguments);\r
19811         this.delegateUpdates();\r
19812     },\r
19813 \r
19814     \r
19815     beginUpdate : function(){\r
19816         this.suspendUpdates = true;\r
19817     },\r
19818 \r
19819     \r
19820     endUpdate : function(){\r
19821         this.suspendUpdates = false;\r
19822         this.delegateUpdates();\r
19823     },\r
19824 \r
19825     \r
19826     hideTabStripItem : function(item){\r
19827         item = this.getComponent(item);\r
19828         var el = this.getTabEl(item);\r
19829         if(el){\r
19830             el.style.display = 'none';\r
19831             this.delegateUpdates();\r
19832         }\r
19833         this.stack.remove(item);\r
19834     },\r
19835 \r
19836     \r
19837     unhideTabStripItem : function(item){\r
19838         item = this.getComponent(item);\r
19839         var el = this.getTabEl(item);\r
19840         if(el){\r
19841             el.style.display = '';\r
19842             this.delegateUpdates();\r
19843         }\r
19844     },\r
19845 \r
19846     // private\r
19847     delegateUpdates : function(){\r
19848         if(this.suspendUpdates){\r
19849             return;\r
19850         }\r
19851         if(this.resizeTabs && this.rendered){\r
19852             this.autoSizeTabs();\r
19853         }\r
19854         if(this.enableTabScroll && this.rendered){\r
19855             this.autoScrollTabs();\r
19856         }\r
19857     },\r
19858 \r
19859     // private\r
19860     autoSizeTabs : function(){\r
19861         var count = this.items.length;\r
19862         var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';\r
19863         var ow = this[ce].dom.offsetWidth;\r
19864         var aw = this[ce].dom.clientWidth;\r
19865 \r
19866         if(!this.resizeTabs || count < 1 || !aw){ // !aw for display:none\r
19867             return;\r
19868         }\r
19869 \r
19870         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); // -4 for float errors in IE\r
19871         this.lastTabWidth = each;\r
19872         var lis = this.stripWrap.dom.getElementsByTagName('li');\r
19873         for(var i = 0, len = lis.length-1; i < len; i++) { // -1 for the "edge" li\r
19874             var li = lis[i];\r
19875             var inner = li.childNodes[1].firstChild.firstChild;\r
19876             var tw = li.offsetWidth;\r
19877             var iw = inner.offsetWidth;\r
19878             inner.style.width = (each - (tw-iw)) + 'px';\r
19879         }\r
19880     },\r
19881 \r
19882     // private\r
19883     adjustBodyWidth : function(w){\r
19884         if(this.header){\r
19885             this.header.setWidth(w);\r
19886         }\r
19887         if(this.footer){\r
19888             this.footer.setWidth(w);\r
19889         }\r
19890         return w;\r
19891     },\r
19892 \r
19893     \r
19894     setActiveTab : function(item){\r
19895         item = this.getComponent(item);\r
19896         if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){\r
19897             return;\r
19898         }\r
19899         if(!this.rendered){\r
19900             this.activeTab = item;\r
19901             return;\r
19902         }\r
19903         if(this.activeTab != item){\r
19904             if(this.activeTab){\r
19905                 var oldEl = this.getTabEl(this.activeTab);\r
19906                 if(oldEl){\r
19907                     Ext.fly(oldEl).removeClass('x-tab-strip-active');\r
19908                 }\r
19909                 this.activeTab.fireEvent('deactivate', this.activeTab);\r
19910             }\r
19911             var el = this.getTabEl(item);\r
19912             Ext.fly(el).addClass('x-tab-strip-active');\r
19913             this.activeTab = item;\r
19914             this.stack.add(item);\r
19915 \r
19916             this.layout.setActiveItem(item);\r
19917             if(this.layoutOnTabChange && item.doLayout){\r
19918                 item.doLayout();\r
19919             }\r
19920             if(this.scrolling){\r
19921                 this.scrollToTab(item, this.animScroll);\r
19922             }\r
19923 \r
19924             item.fireEvent('activate', item);\r
19925             this.fireEvent('tabchange', this, item);\r
19926         }\r
19927     },\r
19928 \r
19929     \r
19930     getActiveTab : function(){\r
19931         return this.activeTab || null;\r
19932     },\r
19933 \r
19934     \r
19935     getItem : function(item){\r
19936         return this.getComponent(item);\r
19937     },\r
19938 \r
19939     // private\r
19940     autoScrollTabs : function(){\r
19941         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;\r
19942         var count = this.items.length;\r
19943         var ow = this.pos.dom.offsetWidth;\r
19944         var tw = this.pos.dom.clientWidth;\r
19945 \r
19946         var wrap = this.stripWrap;\r
19947         var wd = wrap.dom;\r
19948         var cw = wd.offsetWidth;\r
19949         var pos = this.getScrollPos();\r
19950         var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;\r
19951 \r
19952         if(!this.enableTabScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues\r
19953             return;\r
19954         }\r
19955         if(l <= tw){\r
19956             wd.scrollLeft = 0;\r
19957             wrap.setWidth(tw);\r
19958             if(this.scrolling){\r
19959                 this.scrolling = false;\r
19960                 this.pos.removeClass('x-tab-scrolling');\r
19961                 this.scrollLeft.hide();\r
19962                 this.scrollRight.hide();\r
19963                 if(Ext.isAir || Ext.isSafari){\r
19964                     wd.style.marginLeft = '';\r
19965                     wd.style.marginRight = '';\r
19966                 }\r
19967             }\r
19968         }else{\r
19969             if(!this.scrolling){\r
19970                 this.pos.addClass('x-tab-scrolling');\r
19971                 if(Ext.isAir || Ext.isSafari){\r
19972                     wd.style.marginLeft = '18px';\r
19973                     wd.style.marginRight = '18px';\r
19974                 }\r
19975             }\r
19976             tw -= wrap.getMargins('lr');\r
19977             wrap.setWidth(tw > 20 ? tw : 20);\r
19978             if(!this.scrolling){\r
19979                 if(!this.scrollLeft){\r
19980                     this.createScrollers();\r
19981                 }else{\r
19982                     this.scrollLeft.show();\r
19983                     this.scrollRight.show();\r
19984                 }\r
19985             }\r
19986             this.scrolling = true;\r
19987             if(pos > (l-tw)){ // ensure it stays within bounds\r
19988                 wd.scrollLeft = l-tw;\r
19989             }else{ // otherwise, make sure the active tab is still visible\r
19990                 this.scrollToTab(this.activeTab, false);\r
19991             }\r
19992             this.updateScrollButtons();\r
19993         }\r
19994     },\r
19995 \r
19996     // private\r
19997     createScrollers : function(){\r
19998         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);\r
19999         var h = this.stripWrap.dom.offsetHeight;\r
20000 \r
20001         // left\r
20002         var sl = this.pos.insertFirst({\r
20003             cls:'x-tab-scroller-left'\r
20004         });\r
20005         sl.setHeight(h);\r
20006         sl.addClassOnOver('x-tab-scroller-left-over');\r
20007         this.leftRepeater = new Ext.util.ClickRepeater(sl, {\r
20008             interval : this.scrollRepeatInterval,\r
20009             handler: this.onScrollLeft,\r
20010             scope: this\r
20011         });\r
20012         this.scrollLeft = sl;\r
20013 \r
20014         // right\r
20015         var sr = this.pos.insertFirst({\r
20016             cls:'x-tab-scroller-right'\r
20017         });\r
20018         sr.setHeight(h);\r
20019         sr.addClassOnOver('x-tab-scroller-right-over');\r
20020         this.rightRepeater = new Ext.util.ClickRepeater(sr, {\r
20021             interval : this.scrollRepeatInterval,\r
20022             handler: this.onScrollRight,\r
20023             scope: this\r
20024         });\r
20025         this.scrollRight = sr;\r
20026     },\r
20027 \r
20028     // private\r
20029     getScrollWidth : function(){\r
20030         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();\r
20031     },\r
20032 \r
20033     // private\r
20034     getScrollPos : function(){\r
20035         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;\r
20036     },\r
20037 \r
20038     // private\r
20039     getScrollArea : function(){\r
20040         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;\r
20041     },\r
20042 \r
20043     // private\r
20044     getScrollAnim : function(){\r
20045         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};\r
20046     },\r
20047 \r
20048     // private\r
20049     getScrollIncrement : function(){\r
20050         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);\r
20051     },\r
20052 \r
20053     \r
20054 \r
20055     scrollToTab : function(item, animate){\r
20056         if(!item){ return; }\r
20057         var el = this.getTabEl(item);\r
20058         var pos = this.getScrollPos(), area = this.getScrollArea();\r
20059         var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;\r
20060         var right = left + el.offsetWidth;\r
20061         if(left < pos){\r
20062             this.scrollTo(left, animate);\r
20063         }else if(right > (pos + area)){\r
20064             this.scrollTo(right - area, animate);\r
20065         }\r
20066     },\r
20067 \r
20068     // private\r
20069     scrollTo : function(pos, animate){\r
20070         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);\r
20071         if(!animate){\r
20072             this.updateScrollButtons();\r
20073         }\r
20074     },\r
20075 \r
20076     onWheel : function(e){\r
20077         var d = e.getWheelDelta()*this.wheelIncrement*-1;\r
20078         e.stopEvent();\r
20079 \r
20080         var pos = this.getScrollPos();\r
20081         var newpos = pos + d;\r
20082         var sw = this.getScrollWidth()-this.getScrollArea();\r
20083 \r
20084         var s = Math.max(0, Math.min(sw, newpos));\r
20085         if(s != pos){\r
20086             this.scrollTo(s, false);\r
20087         }\r
20088     },\r
20089 \r
20090     // private\r
20091     onScrollRight : function(){\r
20092         var sw = this.getScrollWidth()-this.getScrollArea();\r
20093         var pos = this.getScrollPos();\r
20094         var s = Math.min(sw, pos + this.getScrollIncrement());\r
20095         if(s != pos){\r
20096             this.scrollTo(s, this.animScroll);\r
20097         }\r
20098     },\r
20099 \r
20100     // private\r
20101     onScrollLeft : function(){\r
20102         var pos = this.getScrollPos();\r
20103         var s = Math.max(0, pos - this.getScrollIncrement());\r
20104         if(s != pos){\r
20105             this.scrollTo(s, this.animScroll);\r
20106         }\r
20107     },\r
20108 \r
20109     // private\r
20110     updateScrollButtons : function(){\r
20111         var pos = this.getScrollPos();\r
20112         this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');\r
20113         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');\r
20114     },\r
20115 \r
20116     // private\r
20117     beforeDestroy : function() {\r
20118         if(this.items){\r
20119             this.items.each(function(item){\r
20120                 if(item && item.tabEl){\r
20121                     Ext.get(item.tabEl).removeAllListeners();\r
20122                     item.tabEl = null;\r
20123                 }\r
20124             }, this);\r
20125         }\r
20126         if(this.strip){\r
20127             this.strip.removeAllListeners();\r
20128         }\r
20129         Ext.TabPanel.superclass.beforeDestroy.apply(this);\r
20130     }\r
20131 \r
20132     \r
20133     \r
20134     \r
20135     \r
20136     \r
20137     \r
20138     \r
20139     \r
20140     \r
20141     \r
20142     \r
20143 \r
20144 });\r
20145 Ext.reg('tabpanel', Ext.TabPanel);\r
20146 \r
20147 \r
20148 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;\r
20149 \r
20150 // private utility class used by TabPanel\r
20151 Ext.TabPanel.AccessStack = function(){\r
20152     var items = [];\r
20153     return {\r
20154         add : function(item){\r
20155             items.push(item);\r
20156             if(items.length > 10){\r
20157                 items.shift();\r
20158             }\r
20159         },\r
20160 \r
20161         remove : function(item){\r
20162             var s = [];\r
20163             for(var i = 0, len = items.length; i < len; i++) {\r
20164                 if(items[i] != item){\r
20165                     s.push(items[i]);\r
20166                 }\r
20167             }\r
20168             items = s;\r
20169         },\r
20170 \r
20171         next : function(){\r
20172             return items.pop();\r
20173         }\r
20174     };\r
20175 };\r
20176 \r
20177 \r
20178 \r
20179 \r
20180 Ext.Button = Ext.extend(Ext.Component, {\r
20181     \r
20182     hidden : false,\r
20183     \r
20184     disabled : false,\r
20185     \r
20186     pressed : false,\r
20187     \r
20188 \r
20189     \r
20190 \r
20191     \r
20192 \r
20193     \r
20194     enableToggle: false,\r
20195     \r
20196     \r
20197     \r
20198     menuAlign : "tl-bl?",\r
20199 \r
20200     \r
20201     \r
20202     type : 'button',\r
20203 \r
20204     // private\r
20205     menuClassTarget: 'tr',\r
20206 \r
20207     \r
20208     clickEvent : 'click',\r
20209 \r
20210     \r
20211     handleMouseEvents : true,\r
20212 \r
20213     \r
20214     tooltipType : 'qtip',\r
20215 \r
20216     \r
20217     buttonSelector : "button:first-child",\r
20218 \r
20219     \r
20220     \r
20221 \r
20222     initComponent : function(){\r
20223         Ext.Button.superclass.initComponent.call(this);\r
20224 \r
20225         this.addEvents(\r
20226             \r
20227             "click",\r
20228             \r
20229             "toggle",\r
20230             \r
20231             'mouseover',\r
20232             \r
20233             'mouseout',\r
20234             \r
20235             'menushow',\r
20236             \r
20237             'menuhide',\r
20238             \r
20239             'menutriggerover',\r
20240             \r
20241             'menutriggerout'\r
20242         );\r
20243         if(this.menu){\r
20244             this.menu = Ext.menu.MenuMgr.get(this.menu);\r
20245         }\r
20246         if(typeof this.toggleGroup === 'string'){\r
20247             this.enableToggle = true;\r
20248         }\r
20249     },\r
20250 \r
20251     // private\r
20252     onRender : function(ct, position){\r
20253         if(!this.template){\r
20254             if(!Ext.Button.buttonTemplate){\r
20255                 // hideous table template\r
20256                 Ext.Button.buttonTemplate = new Ext.Template(\r
20257                     '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',\r
20258                     '<td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i>&#160;</i></td>',\r
20259                     "</tr></tbody></table>");\r
20260             }\r
20261             this.template = Ext.Button.buttonTemplate;\r
20262         }\r
20263         var btn, targs = [this.text || '&#160;', this.type];\r
20264 \r
20265         if(position){\r
20266             btn = this.template.insertBefore(position, targs, true);\r
20267         }else{\r
20268             btn = this.template.append(ct, targs, true);\r
20269         }\r
20270         var btnEl = btn.child(this.buttonSelector);\r
20271         btnEl.on('focus', this.onFocus, this);\r
20272         btnEl.on('blur', this.onBlur, this);\r
20273 \r
20274         this.initButtonEl(btn, btnEl);\r
20275 \r
20276         if(this.menu){\r
20277             this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");\r
20278         }\r
20279         Ext.ButtonToggleMgr.register(this);\r
20280     },\r
20281 \r
20282     // private\r
20283     initButtonEl : function(btn, btnEl){\r
20284 \r
20285         this.el = btn;\r
20286         btn.addClass("x-btn");\r
20287 \r
20288         if(this.id){\r
20289             this.el.dom.id = this.el.id = this.id;\r
20290         }\r
20291         if(this.icon){\r
20292             btnEl.setStyle('background-image', 'url(' +this.icon +')');\r
20293         }\r
20294         if(this.iconCls){\r
20295             btnEl.addClass(this.iconCls);\r
20296             if(!this.cls){\r
20297                 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');\r
20298             }\r
20299         }\r
20300         if(this.tabIndex !== undefined){\r
20301             btnEl.dom.tabIndex = this.tabIndex;\r
20302         }\r
20303         if(this.tooltip){\r
20304             if(typeof this.tooltip == 'object'){\r
20305                 Ext.QuickTips.register(Ext.apply({\r
20306                       target: btnEl.id\r
20307                 }, this.tooltip));\r
20308             } else {\r
20309                 btnEl.dom[this.tooltipType] = this.tooltip;\r
20310             }\r
20311         }\r
20312 \r
20313         if(this.pressed){\r
20314             this.el.addClass("x-btn-pressed");\r
20315         }\r
20316 \r
20317         if(this.handleMouseEvents){\r
20318             btn.on("mouseover", this.onMouseOver, this);\r
20319             // new functionality for monitoring on the document level\r
20320             //btn.on("mouseout", this.onMouseOut, this);\r
20321             btn.on("mousedown", this.onMouseDown, this);\r
20322         }\r
20323 \r
20324         if(this.menu){\r
20325             this.menu.on("show", this.onMenuShow, this);\r
20326             this.menu.on("hide", this.onMenuHide, this);\r
20327         }\r
20328 \r
20329         if(this.repeat){\r
20330             var repeater = new Ext.util.ClickRepeater(btn,\r
20331                 typeof this.repeat == "object" ? this.repeat : {}\r
20332             );\r
20333             repeater.on("click", this.onClick,  this);\r
20334         }\r
20335 \r
20336         btn.on(this.clickEvent, this.onClick, this);\r
20337     },\r
20338 \r
20339     // private\r
20340     afterRender : function(){\r
20341         Ext.Button.superclass.afterRender.call(this);\r
20342         if(Ext.isIE6){\r
20343             this.autoWidth.defer(1, this);\r
20344         }else{\r
20345             this.autoWidth();\r
20346         }\r
20347     },\r
20348 \r
20349     \r
20350     setIconClass : function(cls){\r
20351         if(this.el){\r
20352             this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);\r
20353         }\r
20354         this.iconCls = cls;\r
20355     },\r
20356 \r
20357     // private\r
20358     beforeDestroy: function(){\r
20359         if(this.rendered){\r
20360             var btnEl = this.el.child(this.buttonSelector);\r
20361             if(btnEl){\r
20362                 if(this.tooltip){\r
20363                     Ext.QuickTips.unregister(btnEl);\r
20364                 }\r
20365                 btnEl.removeAllListeners();\r
20366             }\r
20367             }\r
20368         if(this.menu){\r
20369             Ext.destroy(this.menu);\r
20370         }\r
20371     },\r
20372 \r
20373     // private\r
20374     onDestroy : function(){\r
20375         if(this.rendered){\r
20376             Ext.ButtonToggleMgr.unregister(this);\r
20377         }\r
20378     },\r
20379 \r
20380     // private\r
20381     autoWidth : function(){\r
20382         if(this.el){\r
20383             this.el.setWidth("auto");\r
20384             if(Ext.isIE7 && Ext.isStrict){\r
20385                 var ib = this.el.child(this.buttonSelector);\r
20386                 if(ib && ib.getWidth() > 20){\r
20387                     ib.clip();\r
20388                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));\r
20389                 }\r
20390             }\r
20391             if(this.minWidth){\r
20392                 if(this.el.getWidth() < this.minWidth){\r
20393                     this.el.setWidth(this.minWidth);\r
20394                 }\r
20395             }\r
20396         }\r
20397     },\r
20398 \r
20399     \r
20400     setHandler : function(handler, scope){\r
20401         this.handler = handler;\r
20402         this.scope = scope;\r
20403     },\r
20404 \r
20405     \r
20406     setText : function(text){\r
20407         this.text = text;\r
20408         if(this.el){\r
20409             this.el.child("td.x-btn-center " + this.buttonSelector).update(text);\r
20410         }\r
20411         this.autoWidth();\r
20412     },\r
20413 \r
20414     \r
20415     getText : function(){\r
20416         return this.text;\r
20417     },\r
20418 \r
20419     \r
20420     toggle : function(state){\r
20421         state = state === undefined ? !this.pressed : state;\r
20422         if(state != this.pressed){\r
20423             if(state){\r
20424                 this.el.addClass("x-btn-pressed");\r
20425                 this.pressed = true;\r
20426                 this.fireEvent("toggle", this, true);\r
20427             }else{\r
20428                 this.el.removeClass("x-btn-pressed");\r
20429                 this.pressed = false;\r
20430                 this.fireEvent("toggle", this, false);\r
20431             }\r
20432             if(this.toggleHandler){\r
20433                 this.toggleHandler.call(this.scope || this, this, state);\r
20434             }\r
20435         }\r
20436     },\r
20437 \r
20438     \r
20439     focus : function(){\r
20440         this.el.child(this.buttonSelector).focus();\r
20441     },\r
20442 \r
20443     // private\r
20444     onDisable : function(){\r
20445         if(this.el){\r
20446             if(!Ext.isIE6 || !this.text){\r
20447                 this.el.addClass(this.disabledClass);\r
20448             }\r
20449             this.el.dom.disabled = true;\r
20450         }\r
20451         this.disabled = true;\r
20452     },\r
20453 \r
20454     // private\r
20455     onEnable : function(){\r
20456         if(this.el){\r
20457             if(!Ext.isIE6 || !this.text){\r
20458                 this.el.removeClass(this.disabledClass);\r
20459             }\r
20460             this.el.dom.disabled = false;\r
20461         }\r
20462         this.disabled = false;\r
20463     },\r
20464 \r
20465     \r
20466     showMenu : function(){\r
20467         if(this.menu){\r
20468             this.menu.show(this.el, this.menuAlign);\r
20469         }\r
20470         return this;\r
20471     },\r
20472 \r
20473     \r
20474     hideMenu : function(){\r
20475         if(this.menu){\r
20476             this.menu.hide();\r
20477         }\r
20478         return this;\r
20479     },\r
20480 \r
20481     \r
20482     hasVisibleMenu : function(){\r
20483         return this.menu && this.menu.isVisible();\r
20484     },\r
20485 \r
20486     // private\r
20487     onClick : function(e){\r
20488         if(e){\r
20489             e.preventDefault();\r
20490         }\r
20491         if(e.button != 0){\r
20492             return;\r
20493         }\r
20494         if(!this.disabled){\r
20495             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){\r
20496                 this.toggle();\r
20497             }\r
20498             if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){\r
20499                 this.showMenu();\r
20500             }\r
20501             this.fireEvent("click", this, e);\r
20502             if(this.handler){\r
20503                 //this.el.removeClass("x-btn-over");\r
20504                 this.handler.call(this.scope || this, this, e);\r
20505             }\r
20506         }\r
20507     },\r
20508 \r
20509     // private\r
20510     isMenuTriggerOver : function(e, internal){\r
20511         return this.menu && !internal;\r
20512     },\r
20513 \r
20514     // private\r
20515     isMenuTriggerOut : function(e, internal){\r
20516         return this.menu && !internal;\r
20517     },\r
20518 \r
20519     // private\r
20520     onMouseOver : function(e){\r
20521         if(!this.disabled){\r
20522             var internal = e.within(this.el,  true);\r
20523             if(!internal){\r
20524                 this.el.addClass("x-btn-over");\r
20525                 if(!this.monitoringMouseOver){\r
20526                     Ext.getDoc().on('mouseover', this.monitorMouseOver, this);\r
20527                     this.monitoringMouseOver = true;\r
20528                 }\r
20529                 this.fireEvent('mouseover', this, e);\r
20530             }\r
20531             if(this.isMenuTriggerOver(e, internal)){\r
20532                 this.fireEvent('menutriggerover', this, this.menu, e);\r
20533             }\r
20534         }\r
20535     },\r
20536 \r
20537     // private\r
20538     monitorMouseOver : function(e){\r
20539         if(e.target != this.el.dom && !e.within(this.el)){\r
20540             if(this.monitoringMouseOver){\r
20541                 Ext.getDoc().un('mouseover', this.monitorMouseOver, this);\r
20542                 this.monitoringMouseOver = false;\r
20543             }\r
20544             this.onMouseOut(e);\r
20545         }\r
20546     },\r
20547 \r
20548     // private\r
20549     onMouseOut : function(e){\r
20550         var internal = e.within(this.el) && e.target != this.el.dom;\r
20551         this.el.removeClass("x-btn-over");\r
20552         this.fireEvent('mouseout', this, e);\r
20553         if(this.isMenuTriggerOut(e, internal)){\r
20554             this.fireEvent('menutriggerout', this, this.menu, e);\r
20555         }\r
20556     },\r
20557     // private\r
20558     onFocus : function(e){\r
20559         if(!this.disabled){\r
20560             this.el.addClass("x-btn-focus");\r
20561         }\r
20562     },\r
20563     // private\r
20564     onBlur : function(e){\r
20565         this.el.removeClass("x-btn-focus");\r
20566     },\r
20567 \r
20568     // private\r
20569     getClickEl : function(e, isUp){\r
20570        return this.el;\r
20571     },\r
20572 \r
20573     // private\r
20574     onMouseDown : function(e){\r
20575         if(!this.disabled && e.button == 0){\r
20576             this.getClickEl(e).addClass("x-btn-click");\r
20577             Ext.getDoc().on('mouseup', this.onMouseUp, this);\r
20578         }\r
20579     },\r
20580     // private\r
20581     onMouseUp : function(e){\r
20582         if(e.button == 0){\r
20583             this.getClickEl(e, true).removeClass("x-btn-click");\r
20584             Ext.getDoc().un('mouseup', this.onMouseUp, this);\r
20585         }\r
20586     },\r
20587     // private\r
20588     onMenuShow : function(e){\r
20589         this.ignoreNextClick = 0;\r
20590         this.el.addClass("x-btn-menu-active");\r
20591         this.fireEvent('menushow', this, this.menu);\r
20592     },\r
20593     // private\r
20594     onMenuHide : function(e){\r
20595         this.el.removeClass("x-btn-menu-active");\r
20596         this.ignoreNextClick = this.restoreClick.defer(250, this);\r
20597         this.fireEvent('menuhide', this, this.menu);\r
20598     },\r
20599 \r
20600     // private\r
20601     restoreClick : function(){\r
20602         this.ignoreNextClick = 0;\r
20603     }\r
20604 \r
20605 \r
20606 \r
20607     \r
20608 });\r
20609 Ext.reg('button', Ext.Button);\r
20610 \r
20611 // Private utility class used by Button\r
20612 Ext.ButtonToggleMgr = function(){\r
20613    var groups = {};\r
20614 \r
20615    function toggleGroup(btn, state){\r
20616        if(state){\r
20617            var g = groups[btn.toggleGroup];\r
20618            for(var i = 0, l = g.length; i < l; i++){\r
20619                if(g[i] != btn){\r
20620                    g[i].toggle(false);\r
20621                }\r
20622            }\r
20623        }\r
20624    }\r
20625 \r
20626    return {\r
20627        register : function(btn){\r
20628            if(!btn.toggleGroup){\r
20629                return;\r
20630            }\r
20631            var g = groups[btn.toggleGroup];\r
20632            if(!g){\r
20633                g = groups[btn.toggleGroup] = [];\r
20634            }\r
20635            g.push(btn);\r
20636            btn.on("toggle", toggleGroup);\r
20637        },\r
20638 \r
20639        unregister : function(btn){\r
20640            if(!btn.toggleGroup){\r
20641                return;\r
20642            }\r
20643            var g = groups[btn.toggleGroup];\r
20644            if(g){\r
20645                g.remove(btn);\r
20646                btn.un("toggle", toggleGroup);\r
20647            }\r
20648        }\r
20649    };\r
20650 }();\r
20651 \r
20652 Ext.SplitButton = Ext.extend(Ext.Button, {\r
20653         // private\r
20654     arrowSelector : 'button:last',\r
20655 \r
20656     // private\r
20657     initComponent : function(){\r
20658         Ext.SplitButton.superclass.initComponent.call(this);\r
20659         \r
20660         this.addEvents("arrowclick");\r
20661     },\r
20662 \r
20663     // private\r
20664     onRender : function(ct, position){\r
20665         // this is one sweet looking template!\r
20666         var tpl = new Ext.Template(\r
20667             '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',\r
20668             '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',\r
20669             '<tr><td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>',\r
20670             "</tbody></table></td><td>",\r
20671             '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',\r
20672             '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button">&#160;</button></td><td class="x-btn-right"><i>&#160;</i></td></tr>',\r
20673             "</tbody></table></td></tr></table>"\r
20674         );\r
20675         var btn, targs = [this.text || '&#160;', this.type];\r
20676         if(position){\r
20677             btn = tpl.insertBefore(position, targs, true);\r
20678         }else{\r
20679             btn = tpl.append(ct, targs, true);\r
20680         }\r
20681         var btnEl = btn.child(this.buttonSelector);\r
20682 \r
20683         this.initButtonEl(btn, btnEl);\r
20684         this.arrowBtnTable = btn.child("table:last");\r
20685         if(this.arrowTooltip){\r
20686             btn.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;\r
20687         }\r
20688     },\r
20689 \r
20690     // private\r
20691     autoWidth : function(){\r
20692         if(this.el){\r
20693             var tbl = this.el.child("table:first");\r
20694             var tbl2 = this.el.child("table:last");\r
20695             this.el.setWidth("auto");\r
20696             tbl.setWidth("auto");\r
20697             if(Ext.isIE7 && Ext.isStrict){\r
20698                 var ib = this.el.child(this.buttonSelector);\r
20699                 if(ib && ib.getWidth() > 20){\r
20700                     ib.clip();\r
20701                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));\r
20702                 }\r
20703             }\r
20704             if(this.minWidth){\r
20705                 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){\r
20706                     tbl.setWidth(this.minWidth-tbl2.getWidth());\r
20707                 }\r
20708             }\r
20709             this.el.setWidth(tbl.getWidth()+tbl2.getWidth());\r
20710         } \r
20711     },\r
20712 \r
20713     \r
20714     setArrowHandler : function(handler, scope){\r
20715         this.arrowHandler = handler;\r
20716         this.scope = scope;  \r
20717     },\r
20718 \r
20719     // private\r
20720     onClick : function(e){\r
20721         e.preventDefault();\r
20722         if(!this.disabled){\r
20723             if(e.getTarget(".x-btn-menu-arrow-wrap")){\r
20724                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){\r
20725                     this.showMenu();\r
20726                 }\r
20727                 this.fireEvent("arrowclick", this, e);\r
20728                 if(this.arrowHandler){\r
20729                     this.arrowHandler.call(this.scope || this, this, e);\r
20730                 }\r
20731             }else{\r
20732                 if(this.enableToggle){\r
20733                     this.toggle();\r
20734                 }\r
20735                 this.fireEvent("click", this, e);\r
20736                 if(this.handler){\r
20737                     this.handler.call(this.scope || this, this, e);\r
20738                 }\r
20739             }\r
20740         }\r
20741     },\r
20742 \r
20743     // private\r
20744     getClickEl : function(e, isUp){\r
20745         if(!isUp){\r
20746             return (this.lastClickEl = e.getTarget("table", 10, true));\r
20747         }\r
20748         return this.lastClickEl;\r
20749     },\r
20750 \r
20751     // private\r
20752     onDisable : function(){\r
20753         if(this.el){\r
20754             if(!Ext.isIE6){\r
20755                 this.el.addClass("x-item-disabled");\r
20756             }\r
20757             this.el.child(this.buttonSelector).dom.disabled = true;\r
20758             this.el.child(this.arrowSelector).dom.disabled = true;\r
20759         }\r
20760         this.disabled = true;\r
20761     },\r
20762 \r
20763     // private\r
20764     onEnable : function(){\r
20765         if(this.el){\r
20766             if(!Ext.isIE6){\r
20767                 this.el.removeClass("x-item-disabled");\r
20768             }\r
20769             this.el.child(this.buttonSelector).dom.disabled = false;\r
20770             this.el.child(this.arrowSelector).dom.disabled = false;\r
20771         }\r
20772         this.disabled = false;\r
20773     },\r
20774 \r
20775     // private\r
20776     isMenuTriggerOver : function(e){\r
20777         return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);\r
20778     },\r
20779 \r
20780     // private\r
20781     isMenuTriggerOut : function(e, internal){\r
20782         return this.menu && !e.within(this.arrowBtnTable);\r
20783     },\r
20784 \r
20785     // private\r
20786     onDestroy : function(){\r
20787         Ext.destroy(this.arrowBtnTable);\r
20788         Ext.SplitButton.superclass.onDestroy.call(this);\r
20789     }\r
20790 });\r
20791 \r
20792 // backwards compat\r
20793 Ext.MenuButton = Ext.SplitButton;\r
20794 \r
20795 \r
20796 Ext.reg('splitbutton', Ext.SplitButton);\r
20797 \r
20798 Ext.CycleButton = Ext.extend(Ext.SplitButton, {\r
20799     \r
20800     \r
20801     \r
20802     \r
20803         \r
20804 \r
20805     // private\r
20806     getItemText : function(item){\r
20807         if(item && this.showText === true){\r
20808             var text = '';\r
20809             if(this.prependText){\r
20810                 text += this.prependText;\r
20811             }\r
20812             text += item.text;\r
20813             return text;\r
20814         }\r
20815         return undefined;\r
20816     },\r
20817 \r
20818     \r
20819     setActiveItem : function(item, suppressEvent){\r
20820         if(typeof item != 'object'){\r
20821             item = this.menu.items.get(item);\r
20822         }\r
20823         if(item){\r
20824             if(!this.rendered){\r
20825                 this.text = this.getItemText(item);\r
20826                 this.iconCls = item.iconCls;\r
20827             }else{\r
20828                 var t = this.getItemText(item);\r
20829                 if(t){\r
20830                     this.setText(t);\r
20831                 }\r
20832                 this.setIconClass(item.iconCls);\r
20833             }\r
20834             this.activeItem = item;\r
20835             if(!item.checked){\r
20836                 item.setChecked(true, true);\r
20837             }\r
20838             if(this.forceIcon){\r
20839                 this.setIconClass(this.forceIcon);\r
20840             }\r
20841             if(!suppressEvent){\r
20842                 this.fireEvent('change', this, item);\r
20843             }\r
20844         }\r
20845     },\r
20846 \r
20847     \r
20848     getActiveItem : function(){\r
20849         return this.activeItem;\r
20850     },\r
20851 \r
20852     // private\r
20853     initComponent : function(){\r
20854         this.addEvents(\r
20855             \r
20856             "change"\r
20857         );\r
20858 \r
20859         if(this.changeHandler){\r
20860             this.on('change', this.changeHandler, this.scope||this);\r
20861             delete this.changeHandler;\r
20862         }\r
20863 \r
20864         this.itemCount = this.items.length;\r
20865 \r
20866         this.menu = {cls:'x-cycle-menu', items:[]};\r
20867         var checked;\r
20868         for(var i = 0, len = this.itemCount; i < len; i++){\r
20869             var item = this.items[i];\r
20870             item.group = item.group || this.id;\r
20871             item.itemIndex = i;\r
20872             item.checkHandler = this.checkHandler;\r
20873             item.scope = this;\r
20874             item.checked = item.checked || false;\r
20875             this.menu.items.push(item);\r
20876             if(item.checked){\r
20877                 checked = item;\r
20878             }\r
20879         }\r
20880         this.setActiveItem(checked, true);\r
20881         Ext.CycleButton.superclass.initComponent.call(this);\r
20882 \r
20883         this.on('click', this.toggleSelected, this);\r
20884     },\r
20885 \r
20886     // private\r
20887     checkHandler : function(item, pressed){\r
20888         if(pressed){\r
20889             this.setActiveItem(item);\r
20890         }\r
20891     },\r
20892 \r
20893     \r
20894     toggleSelected : function(){\r
20895         this.menu.render();\r
20896                 \r
20897                 var nextIdx, checkItem;\r
20898                 for (var i = 1; i < this.itemCount; i++) {\r
20899                         nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;\r
20900                         // check the potential item\r
20901                         checkItem = this.menu.items.itemAt(nextIdx);\r
20902                         // if its not disabled then check it.\r
20903                         if (!checkItem.disabled) {\r
20904                                 checkItem.setChecked(true);\r
20905                                 break;\r
20906                         }\r
20907                 }\r
20908     }\r
20909 });\r
20910 Ext.reg('cycle', Ext.CycleButton);\r
20911  \r
20912  Ext.Toolbar = function(config){\r
20913     if(Ext.isArray(config)){\r
20914         config = {buttons:config};\r
20915     }\r
20916     Ext.Toolbar.superclass.constructor.call(this, config);\r
20917 };\r
20918 \r
20919 (function(){\r
20920 \r
20921 var T = Ext.Toolbar;\r
20922 \r
20923 Ext.extend(T, Ext.BoxComponent, {\r
20924 \r
20925     trackMenus : true,\r
20926 \r
20927     // private\r
20928     initComponent : function(){\r
20929         T.superclass.initComponent.call(this);\r
20930 \r
20931         if(this.items){\r
20932             this.buttons = this.items;\r
20933         }\r
20934         \r
20935         this.items = new Ext.util.MixedCollection(false, function(o){\r
20936             return o.itemId || o.id || Ext.id();\r
20937         });\r
20938     },\r
20939 \r
20940     // private\r
20941     autoCreate: {\r
20942         cls:'x-toolbar x-small-editor',\r
20943         html:'<table cellspacing="0"><tr></tr></table>'\r
20944     },\r
20945 \r
20946     // private\r
20947     onRender : function(ct, position){\r
20948         this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);\r
20949         this.tr = this.el.child("tr", true);\r
20950     },\r
20951 \r
20952     // private\r
20953     afterRender : function(){\r
20954         T.superclass.afterRender.call(this);\r
20955         if(this.buttons){\r
20956             this.add.apply(this, this.buttons);\r
20957             delete this.buttons;\r
20958         }\r
20959     },\r
20960 \r
20961     \r
20962     add : function(){\r
20963         var a = arguments, l = a.length;\r
20964         for(var i = 0; i < l; i++){\r
20965             var el = a[i];\r
20966             if(el.isFormField){ // some kind of form field\r
20967                 this.addField(el);\r
20968             }else if(el.render){ // some kind of Toolbar.Item\r
20969                 this.addItem(el);\r
20970             }else if(typeof el == "string"){ // string\r
20971                 if(el == "separator" || el == "-"){\r
20972                     this.addSeparator();\r
20973                 }else if(el == " "){\r
20974                     this.addSpacer();\r
20975                 }else if(el == "->"){\r
20976                     this.addFill();\r
20977                 }else{\r
20978                     this.addText(el);\r
20979                 }\r
20980             }else if(el.tagName){ // element\r
20981                 this.addElement(el);\r
20982             }else if(typeof el == "object"){ // must be button config?\r
20983                 if(el.xtype){\r
20984                     this.addField(Ext.ComponentMgr.create(el, 'button'));\r
20985                 }else{\r
20986                     this.addButton(el);\r
20987                 }\r
20988             }\r
20989         }\r
20990     },\r
20991     \r
20992     \r
20993     addSeparator : function(){\r
20994         return this.addItem(new T.Separator());\r
20995     },\r
20996 \r
20997     \r
20998     addSpacer : function(){\r
20999         return this.addItem(new T.Spacer());\r
21000     },\r
21001 \r
21002     \r
21003     addFill : function(){\r
21004         return this.addItem(new T.Fill());\r
21005     },\r
21006 \r
21007     \r
21008     addElement : function(el){\r
21009         return this.addItem(new T.Item(el));\r
21010     },\r
21011     \r
21012     \r
21013     addItem : function(item){\r
21014         var td = this.nextBlock();\r
21015         this.initMenuTracking(item);\r
21016         item.render(td);\r
21017         this.items.add(item);\r
21018         return item;\r
21019     },\r
21020     \r
21021     \r
21022     addButton : function(config){\r
21023         if(Ext.isArray(config)){\r
21024             var buttons = [];\r
21025             for(var i = 0, len = config.length; i < len; i++) {\r
21026                 buttons.push(this.addButton(config[i]));\r
21027             }\r
21028             return buttons;\r
21029         }\r
21030         var b = config;\r
21031         if(!(config instanceof T.Button)){\r
21032             b = config.split ? \r
21033                 new T.SplitButton(config) :\r
21034                 new T.Button(config);\r
21035         }\r
21036         var td = this.nextBlock();\r
21037         this.initMenuTracking(b);\r
21038         b.render(td);\r
21039         this.items.add(b);\r
21040         return b;\r
21041     },\r
21042 \r
21043     // private\r
21044     initMenuTracking : function(item){\r
21045         if(this.trackMenus && item.menu){\r
21046             item.on({\r
21047                 'menutriggerover' : this.onButtonTriggerOver,\r
21048                 'menushow' : this.onButtonMenuShow,\r
21049                 'menuhide' : this.onButtonMenuHide,\r
21050                 scope: this\r
21051             })\r
21052         }\r
21053     },\r
21054 \r
21055     \r
21056     addText : function(text){\r
21057         return this.addItem(new T.TextItem(text));\r
21058     },\r
21059     \r
21060     \r
21061     insertButton : function(index, item){\r
21062         if(Ext.isArray(item)){\r
21063             var buttons = [];\r
21064             for(var i = 0, len = item.length; i < len; i++) {\r
21065                buttons.push(this.insertButton(index + i, item[i]));\r
21066             }\r
21067             return buttons;\r
21068         }\r
21069         if (!(item instanceof T.Button)){\r
21070            item = new T.Button(item);\r
21071         }\r
21072         var td = document.createElement("td");\r
21073         this.tr.insertBefore(td, this.tr.childNodes[index]);\r
21074         this.initMenuTracking(item);\r
21075         item.render(td);\r
21076         this.items.insert(index, item);\r
21077         return item;\r
21078     },\r
21079     \r
21080     \r
21081     addDom : function(config, returnEl){\r
21082         var td = this.nextBlock();\r
21083         Ext.DomHelper.overwrite(td, config);\r
21084         var ti = new T.Item(td.firstChild);\r
21085         ti.render(td);\r
21086         this.items.add(ti);\r
21087         return ti;\r
21088     },\r
21089 \r
21090     \r
21091     addField : function(field){\r
21092         var td = this.nextBlock();\r
21093         field.render(td);\r
21094         var ti = new T.Item(td.firstChild);\r
21095         ti.render(td);\r
21096         this.items.add(field);\r
21097         return ti;\r
21098     },\r
21099 \r
21100     // private\r
21101     nextBlock : function(){\r
21102         var td = document.createElement("td");\r
21103         this.tr.appendChild(td);\r
21104         return td;\r
21105     },\r
21106 \r
21107     // private\r
21108     onDestroy : function(){\r
21109         Ext.Toolbar.superclass.onDestroy.call(this);\r
21110         if(this.rendered){\r
21111             if(this.items){ // rendered?\r
21112                 Ext.destroy.apply(Ext, this.items.items);\r
21113             }\r
21114             Ext.Element.uncache(this.tr);\r
21115         }\r
21116     },\r
21117 \r
21118     // private\r
21119     onDisable : function(){\r
21120         this.items.each(function(item){\r
21121              if(item.disable){\r
21122                  item.disable();\r
21123              }\r
21124         });\r
21125     },\r
21126 \r
21127     // private\r
21128     onEnable : function(){\r
21129         this.items.each(function(item){\r
21130              if(item.enable){\r
21131                  item.enable();\r
21132              }\r
21133         });\r
21134     },\r
21135 \r
21136     // private\r
21137     onButtonTriggerOver : function(btn){\r
21138         if(this.activeMenuBtn && this.activeMenuBtn != btn){\r
21139             this.activeMenuBtn.hideMenu();\r
21140             btn.showMenu();\r
21141             this.activeMenuBtn = btn;\r
21142         }\r
21143     },\r
21144 \r
21145     // private\r
21146     onButtonMenuShow : function(btn){\r
21147         this.activeMenuBtn = btn;\r
21148     },\r
21149 \r
21150     // private\r
21151     onButtonMenuHide : function(btn){\r
21152         delete this.activeMenuBtn;\r
21153     }\r
21154 \r
21155     \r
21156 });\r
21157 Ext.reg('toolbar', Ext.Toolbar);\r
21158 \r
21159 \r
21160 T.Item = function(el){\r
21161     this.el = Ext.getDom(el);\r
21162     this.id = Ext.id(this.el);\r
21163     this.hidden = false;\r
21164 };\r
21165 \r
21166 T.Item.prototype = {\r
21167     \r
21168     \r
21169     getEl : function(){\r
21170        return this.el;  \r
21171     },\r
21172 \r
21173     // private\r
21174     render : function(td){\r
21175         this.td = td;\r
21176         td.appendChild(this.el);\r
21177     },\r
21178     \r
21179     \r
21180     destroy : function(){\r
21181         if(this.el){\r
21182             var el = Ext.get(this.el);\r
21183             Ext.destroy(el);\r
21184         }\r
21185         Ext.removeNode(this.td);\r
21186     },\r
21187     \r
21188     \r
21189     show: function(){\r
21190         this.hidden = false;\r
21191         this.td.style.display = "";\r
21192     },\r
21193     \r
21194     \r
21195     hide: function(){\r
21196         this.hidden = true;\r
21197         this.td.style.display = "none";\r
21198     },\r
21199     \r
21200     \r
21201     setVisible: function(visible){\r
21202         if(visible) {\r
21203             this.show();\r
21204         }else{\r
21205             this.hide();\r
21206         }\r
21207     },\r
21208     \r
21209     \r
21210     focus : function(){\r
21211         Ext.fly(this.el).focus();\r
21212     },\r
21213     \r
21214     \r
21215     disable : function(){\r
21216         Ext.fly(this.td).addClass("x-item-disabled");\r
21217         this.disabled = true;\r
21218         this.el.disabled = true;\r
21219     },\r
21220     \r
21221     \r
21222     enable : function(){\r
21223         Ext.fly(this.td).removeClass("x-item-disabled");\r
21224         this.disabled = false;\r
21225         this.el.disabled = false;\r
21226     }\r
21227 };\r
21228 Ext.reg('tbitem', T.Item);\r
21229 \r
21230 \r
21231 \r
21232 T.Separator = function(){\r
21233     var s = document.createElement("span");\r
21234     s.className = "ytb-sep";\r
21235     T.Separator.superclass.constructor.call(this, s);\r
21236 };\r
21237 Ext.extend(T.Separator, T.Item, {\r
21238     enable:Ext.emptyFn,\r
21239     disable:Ext.emptyFn,\r
21240     focus:Ext.emptyFn\r
21241 });\r
21242 Ext.reg('tbseparator', T.Separator);\r
21243 \r
21244 \r
21245 T.Spacer = function(){\r
21246     var s = document.createElement("div");\r
21247     s.className = "ytb-spacer";\r
21248     T.Spacer.superclass.constructor.call(this, s);\r
21249 };\r
21250 Ext.extend(T.Spacer, T.Item, {\r
21251     enable:Ext.emptyFn,\r
21252     disable:Ext.emptyFn,\r
21253     focus:Ext.emptyFn\r
21254 });\r
21255 \r
21256 Ext.reg('tbspacer', T.Spacer);\r
21257 \r
21258 \r
21259 T.Fill = Ext.extend(T.Spacer, {\r
21260     // private\r
21261     render : function(td){\r
21262         td.style.width = '100%';\r
21263         T.Fill.superclass.render.call(this, td);\r
21264     }\r
21265 });\r
21266 Ext.reg('tbfill', T.Fill);\r
21267 \r
21268 \r
21269 T.TextItem = function(t){\r
21270     var s = document.createElement("span");\r
21271     s.className = "ytb-text";\r
21272     s.innerHTML = t.text ? t.text : t;\r
21273     T.TextItem.superclass.constructor.call(this, s);\r
21274 };\r
21275 Ext.extend(T.TextItem, T.Item, {\r
21276     enable:Ext.emptyFn,\r
21277     disable:Ext.emptyFn,\r
21278     focus:Ext.emptyFn\r
21279 });\r
21280 Ext.reg('tbtext', T.TextItem);\r
21281 \r
21282 \r
21283 \r
21284 T.Button = Ext.extend(Ext.Button, {\r
21285     hideParent : true,\r
21286 \r
21287     onDestroy : function(){\r
21288         T.Button.superclass.onDestroy.call(this);\r
21289         if(this.container){\r
21290             this.container.remove();\r
21291         }\r
21292     }\r
21293 });\r
21294 Ext.reg('tbbutton', T.Button);\r
21295 \r
21296 \r
21297 T.SplitButton = Ext.extend(Ext.SplitButton, {\r
21298     hideParent : true,\r
21299 \r
21300     onDestroy : function(){\r
21301         T.SplitButton.superclass.onDestroy.call(this);\r
21302         if(this.container){\r
21303             this.container.remove();\r
21304         }\r
21305     }\r
21306 });\r
21307 \r
21308 Ext.reg('tbsplit', T.SplitButton);\r
21309 // backwards compat\r
21310 T.MenuButton = T.SplitButton;\r
21311 \r
21312 })();\r
21313 \r
21314 \r
21315 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {\r
21316     \r
21317     \r
21318     \r
21319     pageSize: 20,\r
21320     \r
21321     displayMsg : 'Displaying {0} - {1} of {2}',\r
21322     \r
21323     emptyMsg : 'No data to display',\r
21324     \r
21325     beforePageText : "Page",\r
21326     \r
21327     afterPageText : "of {0}",\r
21328     \r
21329     firstText : "First Page",\r
21330     \r
21331     prevText : "Previous Page",\r
21332     \r
21333     nextText : "Next Page",\r
21334     \r
21335     lastText : "Last Page",\r
21336     \r
21337     refreshText : "Refresh",\r
21338 \r
21339     \r
21340     paramNames : {start: 'start', limit: 'limit'},\r
21341 \r
21342     // private\r
21343     initComponent : function(){\r
21344         this.addEvents(\r
21345             \r
21346             'change',\r
21347             \r
21348             'beforechange'\r
21349         );\r
21350         Ext.PagingToolbar.superclass.initComponent.call(this);\r
21351         this.cursor = 0;\r
21352         this.bind(this.store);\r
21353     },\r
21354 \r
21355     // private\r
21356     onRender : function(ct, position){\r
21357         Ext.PagingToolbar.superclass.onRender.call(this, ct, position);\r
21358         this.first = this.addButton({\r
21359             tooltip: this.firstText,\r
21360             iconCls: "x-tbar-page-first",\r
21361             disabled: true,\r
21362             handler: this.onClick.createDelegate(this, ["first"])\r
21363         });\r
21364         this.prev = this.addButton({\r
21365             tooltip: this.prevText,\r
21366             iconCls: "x-tbar-page-prev",\r
21367             disabled: true,\r
21368             handler: this.onClick.createDelegate(this, ["prev"])\r
21369         });\r
21370         this.addSeparator();\r
21371         this.add(this.beforePageText);\r
21372         this.field = Ext.get(this.addDom({\r
21373            tag: "input",\r
21374            type: "text",\r
21375            size: "3",\r
21376            value: "1",\r
21377            cls: "x-tbar-page-number"\r
21378         }).el);\r
21379         this.field.on("keydown", this.onPagingKeydown, this);\r
21380         this.field.on("focus", function(){this.dom.select();});\r
21381         this.field.on("blur", this.onPagingBlur, this);\r
21382         this.afterTextEl = this.addText(String.format(this.afterPageText, 1));\r
21383         this.field.setHeight(18);\r
21384         this.addSeparator();\r
21385         this.next = this.addButton({\r
21386             tooltip: this.nextText,\r
21387             iconCls: "x-tbar-page-next",\r
21388             disabled: true,\r
21389             handler: this.onClick.createDelegate(this, ["next"])\r
21390         });\r
21391         this.last = this.addButton({\r
21392             tooltip: this.lastText,\r
21393             iconCls: "x-tbar-page-last",\r
21394             disabled: true,\r
21395             handler: this.onClick.createDelegate(this, ["last"])\r
21396         });\r
21397         this.addSeparator();\r
21398         this.loading = this.addButton({\r
21399             tooltip: this.refreshText,\r
21400             iconCls: "x-tbar-loading",\r
21401             handler: this.onClick.createDelegate(this, ["refresh"])\r
21402         });\r
21403 \r
21404         if(this.displayInfo){\r
21405             this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});\r
21406         }\r
21407         if(this.dsLoaded){\r
21408             this.onLoad.apply(this, this.dsLoaded);\r
21409         }\r
21410     },\r
21411 \r
21412     // private\r
21413     updateInfo : function(){\r
21414         if(this.displayEl){\r
21415             var count = this.store.getCount();\r
21416             var msg = count == 0 ?\r
21417                 this.emptyMsg :\r
21418                 String.format(\r
21419                     this.displayMsg,\r
21420                     this.cursor+1, this.cursor+count, this.store.getTotalCount()\r
21421                 );\r
21422             this.displayEl.update(msg);\r
21423         }\r
21424     },\r
21425 \r
21426     // private\r
21427     onLoad : function(store, r, o){\r
21428         if(!this.rendered){\r
21429             this.dsLoaded = [store, r, o];\r
21430             return;\r
21431         }\r
21432        this.cursor = o.params ? o.params[this.paramNames.start] : 0;\r
21433        var d = this.getPageData(), ap = d.activePage, ps = d.pages;\r
21434 \r
21435         this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);\r
21436         this.field.dom.value = ap;\r
21437         this.first.setDisabled(ap == 1);\r
21438         this.prev.setDisabled(ap == 1);\r
21439         this.next.setDisabled(ap == ps);\r
21440         this.last.setDisabled(ap == ps);\r
21441         this.loading.enable();\r
21442         this.updateInfo();\r
21443         this.fireEvent('change', this, d);\r
21444     },\r
21445 \r
21446     // private\r
21447     getPageData : function(){\r
21448         var total = this.store.getTotalCount();\r
21449         return {\r
21450             total : total,\r
21451             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),\r
21452             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)\r
21453         };\r
21454     },\r
21455 \r
21456     // private\r
21457     onLoadError : function(){\r
21458         if(!this.rendered){\r
21459             return;\r
21460         }\r
21461         this.loading.enable();\r
21462     },\r
21463 \r
21464     // private\r
21465     readPage : function(d){\r
21466         var v = this.field.dom.value, pageNum;\r
21467         if (!v || isNaN(pageNum = parseInt(v, 10))) {\r
21468             this.field.dom.value = d.activePage;\r
21469             return false;\r
21470         }\r
21471         return pageNum;\r
21472     },\r
21473 \r
21474     //private\r
21475     onPagingBlur: function(e){\r
21476         this.field.dom.value = this.getPageData().activePage;\r
21477     },\r
21478 \r
21479     // private\r
21480     onPagingKeydown : function(e){\r
21481         var k = e.getKey(), d = this.getPageData(), pageNum;\r
21482         if (k == e.RETURN) {\r
21483             e.stopEvent();\r
21484             pageNum = this.readPage(d);\r
21485             if(pageNum !== false){\r
21486                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;\r
21487                 this.doLoad(pageNum * this.pageSize);\r
21488             }\r
21489         }else if (k == e.HOME || k == e.END){\r
21490             e.stopEvent();\r
21491             pageNum = k == e.HOME ? 1 : d.pages;\r
21492             this.field.dom.value = pageNum;\r
21493         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){\r
21494             e.stopEvent();\r
21495             if(pageNum = this.readPage(d)){\r
21496                 var increment = e.shiftKey ? 10 : 1;\r
21497                 if(k == e.DOWN || k == e.PAGEDOWN){\r
21498                     increment *= -1;\r
21499                 }\r
21500                 pageNum += increment;\r
21501                 if(pageNum >= 1 & pageNum <= d.pages){\r
21502                     this.field.dom.value = pageNum;\r
21503                 }\r
21504             }\r
21505         }\r
21506     },\r
21507 \r
21508     // private\r
21509     beforeLoad : function(){\r
21510         if(this.rendered && this.loading){\r
21511             this.loading.disable();\r
21512         }\r
21513     },\r
21514 \r
21515     // private\r
21516     doLoad : function(start){\r
21517         var o = {}, pn = this.paramNames;\r
21518         o[pn.start] = start;\r
21519         o[pn.limit] = this.pageSize;\r
21520         if(this.fireEvent('beforechange', this, o) !== false){\r
21521             this.store.load({params:o});\r
21522         }\r
21523     },\r
21524 \r
21525     \r
21526     changePage: function(page){\r
21527         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));\r
21528     },\r
21529 \r
21530     // private\r
21531     onClick : function(which){\r
21532         var store = this.store;\r
21533         switch(which){\r
21534             case "first":\r
21535                 this.doLoad(0);\r
21536             break;\r
21537             case "prev":\r
21538                 this.doLoad(Math.max(0, this.cursor-this.pageSize));\r
21539             break;\r
21540             case "next":\r
21541                 this.doLoad(this.cursor+this.pageSize);\r
21542             break;\r
21543             case "last":\r
21544                 var total = store.getTotalCount();\r
21545                 var extra = total % this.pageSize;\r
21546                 var lastStart = extra ? (total - extra) : total-this.pageSize;\r
21547                 this.doLoad(lastStart);\r
21548             break;\r
21549             case "refresh":\r
21550                 this.doLoad(this.cursor);\r
21551             break;\r
21552         }\r
21553     },\r
21554 \r
21555     \r
21556     unbind : function(store){\r
21557         store = Ext.StoreMgr.lookup(store);\r
21558         store.un("beforeload", this.beforeLoad, this);\r
21559         store.un("load", this.onLoad, this);\r
21560         store.un("loadexception", this.onLoadError, this);\r
21561         this.store = undefined;\r
21562     },\r
21563 \r
21564     \r
21565     bind : function(store){\r
21566         store = Ext.StoreMgr.lookup(store);\r
21567         store.on("beforeload", this.beforeLoad, this);\r
21568         store.on("load", this.onLoad, this);\r
21569         store.on("loadexception", this.onLoadError, this);\r
21570         this.store = store;\r
21571     },\r
21572 \r
21573     // private\r
21574     onDestroy : function(){\r
21575         if(this.store){\r
21576             this.unbind(this.store);\r
21577         }\r
21578         Ext.PagingToolbar.superclass.onDestroy.call(this);\r
21579     }\r
21580 });\r
21581 Ext.reg('paging', Ext.PagingToolbar);\r
21582 \r
21583 Ext.Resizable = function(el, config){\r
21584     this.el = Ext.get(el);\r
21585     \r
21586     if(config && config.wrap){\r
21587         config.resizeChild = this.el;\r
21588         this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});\r
21589         this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";\r
21590         this.el.setStyle("overflow", "hidden");\r
21591         this.el.setPositioning(config.resizeChild.getPositioning());\r
21592         config.resizeChild.clearPositioning();\r
21593         if(!config.width || !config.height){\r
21594             var csize = config.resizeChild.getSize();\r
21595             this.el.setSize(csize.width, csize.height);\r
21596         }\r
21597         if(config.pinned && !config.adjustments){\r
21598             config.adjustments = "auto";\r
21599         }\r
21600     }\r
21601 \r
21602     \r
21603     this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"}, Ext.getBody());\r
21604     this.proxy.unselectable();\r
21605     this.proxy.enableDisplayMode('block');\r
21606 \r
21607     Ext.apply(this, config);\r
21608     \r
21609     if(this.pinned){\r
21610         this.disableTrackOver = true;\r
21611         this.el.addClass("x-resizable-pinned");\r
21612     }\r
21613     // if the element isn't positioned, make it relative\r
21614     var position = this.el.getStyle("position");\r
21615     if(position != "absolute" && position != "fixed"){\r
21616         this.el.setStyle("position", "relative");\r
21617     }\r
21618     if(!this.handles){ // no handles passed, must be legacy style\r
21619         this.handles = 's,e,se';\r
21620         if(this.multiDirectional){\r
21621             this.handles += ',n,w';\r
21622         }\r
21623     }\r
21624     if(this.handles == "all"){\r
21625         this.handles = "n s e w ne nw se sw";\r
21626     }\r
21627     var hs = this.handles.split(/\s*?[,;]\s*?| /);\r
21628     var ps = Ext.Resizable.positions;\r
21629     for(var i = 0, len = hs.length; i < len; i++){\r
21630         if(hs[i] && ps[hs[i]]){\r
21631             var pos = ps[hs[i]];\r
21632             this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);\r
21633         }\r
21634     }\r
21635     // legacy\r
21636     this.corner = this.southeast;\r
21637     \r
21638     if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){\r
21639         this.updateBox = true;\r
21640     }   \r
21641    \r
21642     this.activeHandle = null;\r
21643     \r
21644     if(this.resizeChild){\r
21645         if(typeof this.resizeChild == "boolean"){\r
21646             this.resizeChild = Ext.get(this.el.dom.firstChild, true);\r
21647         }else{\r
21648             this.resizeChild = Ext.get(this.resizeChild, true);\r
21649         }\r
21650     }\r
21651     \r
21652     if(this.adjustments == "auto"){\r
21653         var rc = this.resizeChild;\r
21654         var hw = this.west, he = this.east, hn = this.north, hs = this.south;\r
21655         if(rc && (hw || hn)){\r
21656             rc.position("relative");\r
21657             rc.setLeft(hw ? hw.el.getWidth() : 0);\r
21658             rc.setTop(hn ? hn.el.getHeight() : 0);\r
21659         }\r
21660         this.adjustments = [\r
21661             (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),\r
21662             (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 \r
21663         ];\r
21664     }\r
21665     \r
21666     if(this.draggable){\r
21667         this.dd = this.dynamic ? \r
21668             this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});\r
21669         this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\r
21670     }\r
21671     \r
21672     // public events\r
21673     this.addEvents(\r
21674         "beforeresize",\r
21675         "resize"\r
21676     );\r
21677     \r
21678     if(this.width !== null && this.height !== null){\r
21679         this.resizeTo(this.width, this.height);\r
21680     }else{\r
21681         this.updateChildSize();\r
21682     }\r
21683     if(Ext.isIE){\r
21684         this.el.dom.style.zoom = 1;\r
21685     }\r
21686     Ext.Resizable.superclass.constructor.call(this);\r
21687 };\r
21688 \r
21689 Ext.extend(Ext.Resizable, Ext.util.Observable, {\r
21690         resizeChild : false,\r
21691         adjustments : [0, 0],\r
21692         minWidth : 5,\r
21693         minHeight : 5,\r
21694         maxWidth : 10000,\r
21695         maxHeight : 10000,\r
21696         enabled : true,\r
21697         animate : false,\r
21698         duration : .35,\r
21699         dynamic : false,\r
21700         handles : false,\r
21701         multiDirectional : false,\r
21702         disableTrackOver : false,\r
21703         easing : 'easeOutStrong',\r
21704         widthIncrement : 0,\r
21705         heightIncrement : 0,\r
21706         pinned : false,\r
21707         width : null,\r
21708         height : null,\r
21709         preserveRatio : false,\r
21710         transparent: false,\r
21711         minX: 0,\r
21712         minY: 0,\r
21713         draggable: false,\r
21714 \r
21715         \r
21716         \r
21717 \r
21718         \r
21719         \r
21720     \r
21721     \r
21722     resizeTo : function(width, height){\r
21723         this.el.setSize(width, height);\r
21724         this.updateChildSize();\r
21725         this.fireEvent("resize", this, width, height, null);\r
21726     },\r
21727 \r
21728     // private\r
21729     startSizing : function(e, handle){\r
21730         this.fireEvent("beforeresize", this, e);\r
21731         if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler\r
21732 \r
21733             if(!this.overlay){\r
21734                 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: "&#160;"}, Ext.getBody());\r
21735                 this.overlay.unselectable();\r
21736                 this.overlay.enableDisplayMode("block");\r
21737                 this.overlay.on("mousemove", this.onMouseMove, this);\r
21738                 this.overlay.on("mouseup", this.onMouseUp, this);\r
21739             }\r
21740             this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));\r
21741 \r
21742             this.resizing = true;\r
21743             this.startBox = this.el.getBox();\r
21744             this.startPoint = e.getXY();\r
21745             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],\r
21746                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];\r
21747 \r
21748             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
21749             this.overlay.show();\r
21750 \r
21751             if(this.constrainTo) {\r
21752                 var ct = Ext.get(this.constrainTo);\r
21753                 this.resizeRegion = ct.getRegion().adjust(\r
21754                     ct.getFrameWidth('t'),\r
21755                     ct.getFrameWidth('l'),\r
21756                     -ct.getFrameWidth('b'),\r
21757                     -ct.getFrameWidth('r')\r
21758                 );\r
21759             }\r
21760 \r
21761             this.proxy.setStyle('visibility', 'hidden'); // workaround display none\r
21762             this.proxy.show();\r
21763             this.proxy.setBox(this.startBox);\r
21764             if(!this.dynamic){\r
21765                 this.proxy.setStyle('visibility', 'visible');\r
21766             }\r
21767         }\r
21768     },\r
21769 \r
21770     // private\r
21771     onMouseDown : function(handle, e){\r
21772         if(this.enabled){\r
21773             e.stopEvent();\r
21774             this.activeHandle = handle;\r
21775             this.startSizing(e, handle);\r
21776         }          \r
21777     },\r
21778 \r
21779     // private\r
21780     onMouseUp : function(e){\r
21781         var size = this.resizeElement();\r
21782         this.resizing = false;\r
21783         this.handleOut();\r
21784         this.overlay.hide();\r
21785         this.proxy.hide();\r
21786         this.fireEvent("resize", this, size.width, size.height, e);\r
21787     },\r
21788 \r
21789     // private\r
21790     updateChildSize : function(){\r
21791         if(this.resizeChild){\r
21792             var el = this.el;\r
21793             var child = this.resizeChild;\r
21794             var adj = this.adjustments;\r
21795             if(el.dom.offsetWidth){\r
21796                 var b = el.getSize(true);\r
21797                 child.setSize(b.width+adj[0], b.height+adj[1]);\r
21798             }\r
21799             // Second call here for IE\r
21800             // The first call enables instant resizing and\r
21801             // the second call corrects scroll bars if they\r
21802             // exist\r
21803             if(Ext.isIE){\r
21804                 setTimeout(function(){\r
21805                     if(el.dom.offsetWidth){\r
21806                         var b = el.getSize(true);\r
21807                         child.setSize(b.width+adj[0], b.height+adj[1]);\r
21808                     }\r
21809                 }, 10);\r
21810             }\r
21811         }\r
21812     },\r
21813 \r
21814     // private\r
21815     snap : function(value, inc, min){\r
21816         if(!inc || !value) return value;\r
21817         var newValue = value;\r
21818         var m = value % inc;\r
21819         if(m > 0){\r
21820             if(m > (inc/2)){\r
21821                 newValue = value + (inc-m);\r
21822             }else{\r
21823                 newValue = value - m;\r
21824             }\r
21825         }\r
21826         return Math.max(min, newValue);\r
21827     },\r
21828 \r
21829     \r
21830     resizeElement : function(){\r
21831         var box = this.proxy.getBox();\r
21832         if(this.updateBox){\r
21833             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);\r
21834         }else{\r
21835             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);\r
21836         }\r
21837         this.updateChildSize();\r
21838         if(!this.dynamic){\r
21839             this.proxy.hide();\r
21840         }\r
21841         return box;\r
21842     },\r
21843 \r
21844     // private\r
21845     constrain : function(v, diff, m, mx){\r
21846         if(v - diff < m){\r
21847             diff = v - m;    \r
21848         }else if(v - diff > mx){\r
21849             diff = mx - v; \r
21850         }\r
21851         return diff;                \r
21852     },\r
21853 \r
21854     // private\r
21855     onMouseMove : function(e){\r
21856         if(this.enabled){\r
21857             try{// try catch so if something goes wrong the user doesn't get hung\r
21858 \r
21859             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {\r
21860                 return;\r
21861             }\r
21862 \r
21863             //var curXY = this.startPoint;\r
21864             var curSize = this.curSize || this.startBox;\r
21865             var x = this.startBox.x, y = this.startBox.y;\r
21866             var ox = x, oy = y;\r
21867             var w = curSize.width, h = curSize.height;\r
21868             var ow = w, oh = h;\r
21869             var mw = this.minWidth, mh = this.minHeight;\r
21870             var mxw = this.maxWidth, mxh = this.maxHeight;\r
21871             var wi = this.widthIncrement;\r
21872             var hi = this.heightIncrement;\r
21873             \r
21874             var eventXY = e.getXY();\r
21875             var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));\r
21876             var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));\r
21877             \r
21878             var pos = this.activeHandle.position;\r
21879             \r
21880             switch(pos){\r
21881                 case "east":\r
21882                     w += diffX; \r
21883                     w = Math.min(Math.max(mw, w), mxw);\r
21884                     break;\r
21885                 case "south":\r
21886                     h += diffY;\r
21887                     h = Math.min(Math.max(mh, h), mxh);\r
21888                     break;\r
21889                 case "southeast":\r
21890                     w += diffX; \r
21891                     h += diffY;\r
21892                     w = Math.min(Math.max(mw, w), mxw);\r
21893                     h = Math.min(Math.max(mh, h), mxh);\r
21894                     break;\r
21895                 case "north":\r
21896                     diffY = this.constrain(h, diffY, mh, mxh);\r
21897                     y += diffY;\r
21898                     h -= diffY;\r
21899                     break;\r
21900                 case "west":\r
21901                     diffX = this.constrain(w, diffX, mw, mxw);\r
21902                     x += diffX;\r
21903                     w -= diffX;\r
21904                     break;\r
21905                 case "northeast":\r
21906                     w += diffX; \r
21907                     w = Math.min(Math.max(mw, w), mxw);\r
21908                     diffY = this.constrain(h, diffY, mh, mxh);\r
21909                     y += diffY;\r
21910                     h -= diffY;\r
21911                     break;\r
21912                 case "northwest":\r
21913                     diffX = this.constrain(w, diffX, mw, mxw);\r
21914                     diffY = this.constrain(h, diffY, mh, mxh);\r
21915                     y += diffY;\r
21916                     h -= diffY;\r
21917                     x += diffX;\r
21918                     w -= diffX;\r
21919                     break;\r
21920                case "southwest":\r
21921                     diffX = this.constrain(w, diffX, mw, mxw);\r
21922                     h += diffY;\r
21923                     h = Math.min(Math.max(mh, h), mxh);\r
21924                     x += diffX;\r
21925                     w -= diffX;\r
21926                     break;\r
21927             }\r
21928             \r
21929             var sw = this.snap(w, wi, mw);\r
21930             var sh = this.snap(h, hi, mh);\r
21931             if(sw != w || sh != h){\r
21932                 switch(pos){\r
21933                     case "northeast":\r
21934                         y -= sh - h;\r
21935                     break;\r
21936                     case "north":\r
21937                         y -= sh - h;\r
21938                         break;\r
21939                     case "southwest":\r
21940                         x -= sw - w;\r
21941                     break;\r
21942                     case "west":\r
21943                         x -= sw - w;\r
21944                         break;\r
21945                     case "northwest":\r
21946                         x -= sw - w;\r
21947                         y -= sh - h;\r
21948                     break;\r
21949                 }\r
21950                 w = sw;\r
21951                 h = sh;\r
21952             }\r
21953             \r
21954             if(this.preserveRatio){\r
21955                 switch(pos){\r
21956                     case "southeast":\r
21957                     case "east":\r
21958                         h = oh * (w/ow);\r
21959                         h = Math.min(Math.max(mh, h), mxh);\r
21960                         w = ow * (h/oh);\r
21961                        break;\r
21962                     case "south":\r
21963                         w = ow * (h/oh);\r
21964                         w = Math.min(Math.max(mw, w), mxw);\r
21965                         h = oh * (w/ow);\r
21966                         break;\r
21967                     case "northeast":\r
21968                         w = ow * (h/oh);\r
21969                         w = Math.min(Math.max(mw, w), mxw);\r
21970                         h = oh * (w/ow);\r
21971                     break;\r
21972                     case "north":\r
21973                         var tw = w;\r
21974                         w = ow * (h/oh);\r
21975                         w = Math.min(Math.max(mw, w), mxw);\r
21976                         h = oh * (w/ow);\r
21977                         x += (tw - w) / 2;\r
21978                         break;\r
21979                     case "southwest":\r
21980                         h = oh * (w/ow);\r
21981                         h = Math.min(Math.max(mh, h), mxh);\r
21982                         var tw = w;\r
21983                         w = ow * (h/oh);\r
21984                         x += tw - w;\r
21985                         break;\r
21986                     case "west":\r
21987                         var th = h;\r
21988                         h = oh * (w/ow);\r
21989                         h = Math.min(Math.max(mh, h), mxh);\r
21990                         y += (th - h) / 2;\r
21991                         var tw = w;\r
21992                         w = ow * (h/oh);\r
21993                         x += tw - w;\r
21994                        break;\r
21995                     case "northwest":\r
21996                         var tw = w;\r
21997                         var th = h;\r
21998                         h = oh * (w/ow);\r
21999                         h = Math.min(Math.max(mh, h), mxh);\r
22000                         w = ow * (h/oh);\r
22001                         y += th - h;\r
22002                          x += tw - w;\r
22003                        break;\r
22004                         \r
22005                 }\r
22006             }\r
22007             this.proxy.setBounds(x, y, w, h);\r
22008             if(this.dynamic){\r
22009                 this.resizeElement();\r
22010             }\r
22011             }catch(e){}\r
22012         }\r
22013     },\r
22014 \r
22015     // private\r
22016     handleOver : function(){\r
22017         if(this.enabled){\r
22018             this.el.addClass("x-resizable-over");\r
22019         }\r
22020     },\r
22021 \r
22022     // private\r
22023     handleOut : function(){\r
22024         if(!this.resizing){\r
22025             this.el.removeClass("x-resizable-over");\r
22026         }\r
22027     },\r
22028     \r
22029     \r
22030     getEl : function(){\r
22031         return this.el;\r
22032     },\r
22033     \r
22034     \r
22035     getResizeChild : function(){\r
22036         return this.resizeChild;\r
22037     },\r
22038     \r
22039     \r
22040     destroy : function(removeEl){\r
22041         if(this.dd){\r
22042             this.dd.destroy();\r
22043         }\r
22044         if(this.overlay){\r
22045             Ext.destroy(this.overlay);\r
22046             this.overlay = null;\r
22047         }\r
22048         Ext.destroy(this.proxy);\r
22049         this.proxy = null;\r
22050         \r
22051         var ps = Ext.Resizable.positions;\r
22052         for(var k in ps){\r
22053             if(typeof ps[k] != "function" && this[ps[k]]){\r
22054                 this[ps[k]].destroy();\r
22055             }\r
22056         }\r
22057         if(removeEl){\r
22058             this.el.update("");\r
22059             Ext.destroy(this.el);\r
22060             this.el = null;\r
22061         }\r
22062     },\r
22063 \r
22064     syncHandleHeight : function(){\r
22065         var h = this.el.getHeight(true);\r
22066         if(this.west){\r
22067             this.west.el.setHeight(h);\r
22068         }\r
22069         if(this.east){\r
22070             this.east.el.setHeight(h);\r
22071         }\r
22072     }\r
22073 });\r
22074 \r
22075 // private\r
22076 // hash to map config positions to true positions\r
22077 Ext.Resizable.positions = {\r
22078     n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"\r
22079 };\r
22080 \r
22081 // private\r
22082 Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){\r
22083     if(!this.tpl){\r
22084         // only initialize the template if resizable is used\r
22085         var tpl = Ext.DomHelper.createTemplate(\r
22086             {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}\r
22087         );\r
22088         tpl.compile();\r
22089         Ext.Resizable.Handle.prototype.tpl = tpl;\r
22090     }\r
22091     this.position = pos;\r
22092     this.rz = rz;\r
22093     this.el = this.tpl.append(rz.el.dom, [this.position], true);\r
22094     this.el.unselectable();\r
22095     if(transparent){\r
22096         this.el.setOpacity(0);\r
22097     }\r
22098     this.el.on("mousedown", this.onMouseDown, this);\r
22099     if(!disableTrackOver){\r
22100         this.el.on("mouseover", this.onMouseOver, this);\r
22101         this.el.on("mouseout", this.onMouseOut, this);\r
22102     }\r
22103 };\r
22104 \r
22105 // private\r
22106 Ext.Resizable.Handle.prototype = {\r
22107     // private\r
22108     afterResize : function(rz){\r
22109         // do nothing    \r
22110     },\r
22111     // private\r
22112     onMouseDown : function(e){\r
22113         this.rz.onMouseDown(this, e);\r
22114     },\r
22115     // private\r
22116     onMouseOver : function(e){\r
22117         this.rz.handleOver(this, e);\r
22118     },\r
22119     // private\r
22120     onMouseOut : function(e){\r
22121         this.rz.handleOut(this, e);\r
22122     },\r
22123     // private\r
22124     destroy : function(){\r
22125         Ext.destroy(this.el);\r
22126         this.el = null;\r
22127     }\r
22128 };\r
22129 \r
22130 \r
22131 \r
22132 \r
22133 \r
22134 Ext.Editor = function(field, config){\r
22135     this.field = field;\r
22136     Ext.Editor.superclass.constructor.call(this, config);\r
22137 };\r
22138 \r
22139 Ext.extend(Ext.Editor, Ext.Component, {\r
22140     \r
22141     \r
22142     \r
22143     \r
22144     \r
22145     value : "",\r
22146     \r
22147     alignment: "c-c?",\r
22148     \r
22149     shadow : "frame",\r
22150     \r
22151     constrain : false,\r
22152     \r
22153     swallowKeys : true,\r
22154     \r
22155     completeOnEnter : false,\r
22156     \r
22157     cancelOnEsc : false,\r
22158     \r
22159     updateEl : false,\r
22160 \r
22161     initComponent : function(){\r
22162         Ext.Editor.superclass.initComponent.call(this);\r
22163         this.addEvents(\r
22164             \r
22165             "beforestartedit",\r
22166             \r
22167             "startedit",\r
22168             \r
22169             "beforecomplete",\r
22170             \r
22171             "complete",\r
22172             \r
22173             "canceledit",\r
22174             \r
22175             "specialkey"\r
22176         );\r
22177     },\r
22178 \r
22179     // private\r
22180     onRender : function(ct, position){\r
22181         this.el = new Ext.Layer({\r
22182             shadow: this.shadow,\r
22183             cls: "x-editor",\r
22184             parentEl : ct,\r
22185             shim : this.shim,\r
22186             shadowOffset:4,\r
22187             id: this.id,\r
22188             constrain: this.constrain\r
22189         });\r
22190         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");\r
22191         if(this.field.msgTarget != 'title'){\r
22192             this.field.msgTarget = 'qtip';\r
22193         }\r
22194         this.field.inEditor = true;\r
22195         this.field.render(this.el);\r
22196         if(Ext.isGecko){\r
22197             this.field.el.dom.setAttribute('autocomplete', 'off');\r
22198         }\r
22199         this.field.on("specialkey", this.onSpecialKey, this);\r
22200         if(this.swallowKeys){\r
22201             this.field.el.swallowEvent(['keydown','keypress']);\r
22202         }\r
22203         this.field.show();\r
22204         this.field.on("blur", this.onBlur, this);\r
22205         if(this.field.grow){\r
22206             this.field.on("autosize", this.el.sync,  this.el, {delay:1});\r
22207         }\r
22208     },\r
22209 \r
22210     // private\r
22211     onSpecialKey : function(field, e){\r
22212         var key = e.getKey();\r
22213         if(this.completeOnEnter && key == e.ENTER){\r
22214             e.stopEvent();\r
22215             this.completeEdit();\r
22216         }else if(this.cancelOnEsc && key == e.ESC){\r
22217             this.cancelEdit();\r
22218         }else{\r
22219             this.fireEvent('specialkey', field, e);\r
22220         }\r
22221         if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){\r
22222             this.field.triggerBlur();\r
22223         }\r
22224     },\r
22225 \r
22226     \r
22227     startEdit : function(el, value){\r
22228         if(this.editing){\r
22229             this.completeEdit();\r
22230         }\r
22231         this.boundEl = Ext.get(el);\r
22232         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;\r
22233         if(!this.rendered){\r
22234             this.render(this.parentEl || document.body);\r
22235         }\r
22236         if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){\r
22237             return;\r
22238         }\r
22239         this.startValue = v;\r
22240         this.field.setValue(v);\r
22241         this.doAutoSize();\r
22242         this.el.alignTo(this.boundEl, this.alignment);\r
22243         this.editing = true;\r
22244         this.show();\r
22245     },\r
22246 \r
22247     // private\r
22248     doAutoSize : function(){\r
22249         if(this.autoSize){\r
22250             var sz = this.boundEl.getSize();\r
22251             switch(this.autoSize){\r
22252                 case "width":\r
22253                     this.setSize(sz.width,  "");\r
22254                 break;\r
22255                 case "height":\r
22256                     this.setSize("",  sz.height);\r
22257                 break;\r
22258                 default:\r
22259                     this.setSize(sz.width,  sz.height);\r
22260             }\r
22261         }\r
22262     },\r
22263 \r
22264     \r
22265     setSize : function(w, h){\r
22266         delete this.field.lastSize;\r
22267         this.field.setSize(w, h);\r
22268         if(this.el){\r
22269                 if(Ext.isGecko2 || Ext.isOpera){\r
22270                     // prevent layer scrollbars\r
22271                     this.el.setSize(w, h);\r
22272                 }\r
22273             this.el.sync();\r
22274         }\r
22275     },\r
22276 \r
22277     \r
22278     realign : function(){\r
22279         this.el.alignTo(this.boundEl, this.alignment);\r
22280     },\r
22281 \r
22282     \r
22283     completeEdit : function(remainVisible){\r
22284         if(!this.editing){\r
22285             return;\r
22286         }\r
22287         var v = this.getValue();\r
22288         if(this.revertInvalid !== false && !this.field.isValid()){\r
22289             v = this.startValue;\r
22290             this.cancelEdit(true);\r
22291         }\r
22292         if(String(v) === String(this.startValue) && this.ignoreNoChange){\r
22293             this.editing = false;\r
22294             this.hide();\r
22295             return;\r
22296         }\r
22297         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){\r
22298             this.editing = false;\r
22299             if(this.updateEl && this.boundEl){\r
22300                 this.boundEl.update(v);\r
22301             }\r
22302             if(remainVisible !== true){\r
22303                 this.hide();\r
22304             }\r
22305             this.fireEvent("complete", this, v, this.startValue);\r
22306         }\r
22307     },\r
22308 \r
22309     // private\r
22310     onShow : function(){\r
22311         this.el.show();\r
22312         if(this.hideEl !== false){\r
22313             this.boundEl.hide();\r
22314         }\r
22315         this.field.show();\r
22316         if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time\r
22317             this.fixIEFocus = true;\r
22318             this.deferredFocus.defer(50, this);\r
22319         }else{\r
22320             this.field.focus();\r
22321         }\r
22322         this.fireEvent("startedit", this.boundEl, this.startValue);\r
22323     },\r
22324 \r
22325     deferredFocus : function(){\r
22326         if(this.editing){\r
22327             this.field.focus();\r
22328         }\r
22329     },\r
22330 \r
22331     \r
22332     cancelEdit : function(remainVisible){\r
22333         if(this.editing){\r
22334             var v = this.getValue();\r
22335             this.setValue(this.startValue);\r
22336             if(remainVisible !== true){\r
22337                 this.hide();\r
22338             }\r
22339             this.fireEvent("canceledit", this, v, this.startValue);\r
22340         }\r
22341     },\r
22342 \r
22343     // private\r
22344     onBlur : function(){\r
22345         if(this.allowBlur !== true && this.editing){\r
22346             this.completeEdit();\r
22347         }\r
22348     },\r
22349 \r
22350     // private\r
22351     onHide : function(){\r
22352         if(this.editing){\r
22353             this.completeEdit();\r
22354             return;\r
22355         }\r
22356         this.field.blur();\r
22357         if(this.field.collapse){\r
22358             this.field.collapse();\r
22359         }\r
22360         this.el.hide();\r
22361         if(this.hideEl !== false){\r
22362             this.boundEl.show();\r
22363         }\r
22364     },\r
22365 \r
22366     \r
22367     setValue : function(v){\r
22368         this.field.setValue(v);\r
22369     },\r
22370 \r
22371     \r
22372     getValue : function(){\r
22373         return this.field.getValue();\r
22374     },\r
22375 \r
22376     beforeDestroy : function(){\r
22377         Ext.destroy(this.field);\r
22378         this.field = null;\r
22379     }\r
22380 });\r
22381 Ext.reg('editor', Ext.Editor);\r
22382 \r
22383 Ext.MessageBox = function(){\r
22384     var dlg, opt, mask, waitTimer;\r
22385     var bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl;\r
22386     var buttons, activeTextEl, bwidth, iconCls = '';\r
22387 \r
22388     // private\r
22389     var handleButton = function(button){\r
22390         if(dlg.isVisible()){\r
22391             dlg.hide();\r
22392             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);\r
22393         }\r
22394     };\r
22395 \r
22396     // private\r
22397     var handleHide = function(){\r
22398         if(opt && opt.cls){\r
22399             dlg.el.removeClass(opt.cls);\r
22400         }\r
22401         progressBar.reset();\r
22402     };\r
22403 \r
22404     // private\r
22405     var handleEsc = function(d, k, e){\r
22406         if(opt && opt.closable !== false){\r
22407             dlg.hide();\r
22408         }\r
22409         if(e){\r
22410             e.stopEvent();\r
22411         }\r
22412     };\r
22413 \r
22414     // private\r
22415     var updateButtons = function(b){\r
22416         var width = 0;\r
22417         if(!b){\r
22418             buttons["ok"].hide();\r
22419             buttons["cancel"].hide();\r
22420             buttons["yes"].hide();\r
22421             buttons["no"].hide();\r
22422             return width;\r
22423         }\r
22424         dlg.footer.dom.style.display = '';\r
22425         for(var k in buttons){\r
22426             if(typeof buttons[k] != "function"){\r
22427                 if(b[k]){\r
22428                     buttons[k].show();\r
22429                     buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox.buttonText[k]);\r
22430                     width += buttons[k].el.getWidth()+15;\r
22431                 }else{\r
22432                     buttons[k].hide();\r
22433                 }\r
22434             }\r
22435         }\r
22436         return width;\r
22437     };\r
22438 \r
22439     return {\r
22440         \r
22441         getDialog : function(titleText){\r
22442            if(!dlg){\r
22443                 dlg = new Ext.Window({\r
22444                     autoCreate : true,\r
22445                     title:titleText,\r
22446                     resizable:false,\r
22447                     constrain:true,\r
22448                     constrainHeader:true,\r
22449                     minimizable : false,\r
22450                     maximizable : false,\r
22451                     stateful: false,\r
22452                     modal: true,\r
22453                     shim:true,\r
22454                     buttonAlign:"center",\r
22455                     width:400,\r
22456                     height:100,\r
22457                     minHeight: 80,\r
22458                     plain:true,\r
22459                     footer:true,\r
22460                     closable:true,\r
22461                     close : function(){\r
22462                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){\r
22463                             handleButton("no");\r
22464                         }else{\r
22465                             handleButton("cancel");\r
22466                         }\r
22467                     }\r
22468                 });\r
22469                 buttons = {};\r
22470                 var bt = this.buttonText;\r
22471                 //TODO: refactor this block into a buttons config to pass into the Window constructor\r
22472                 buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));\r
22473                 buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));\r
22474                 buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));\r
22475                 buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));\r
22476                 buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';\r
22477                 dlg.render(document.body);\r
22478                 dlg.getEl().addClass('x-window-dlg');\r
22479                 mask = dlg.mask;\r
22480                 bodyEl = dlg.body.createChild({\r
22481                     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>'\r
22482                 });\r
22483                 iconEl = Ext.get(bodyEl.dom.firstChild);\r
22484                 var contentEl = bodyEl.dom.childNodes[1];\r
22485                 msgEl = Ext.get(contentEl.firstChild);\r
22486                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);\r
22487                 textboxEl.enableDisplayMode();\r
22488                 textboxEl.addKeyListener([10,13], function(){\r
22489                     if(dlg.isVisible() && opt && opt.buttons){\r
22490                         if(opt.buttons.ok){\r
22491                             handleButton("ok");\r
22492                         }else if(opt.buttons.yes){\r
22493                             handleButton("yes");\r
22494                         }\r
22495                     }\r
22496                 });\r
22497                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);\r
22498                 textareaEl.enableDisplayMode();\r
22499                 progressBar = new Ext.ProgressBar({\r
22500                     renderTo:bodyEl\r
22501                 });\r
22502                bodyEl.createChild({cls:'x-clear'});\r
22503             }\r
22504             return dlg;\r
22505         },\r
22506 \r
22507         \r
22508         updateText : function(text){\r
22509             if(!dlg.isVisible() && !opt.width){\r
22510                 dlg.setSize(this.maxWidth, 100); // resize first so content is never clipped from previous shows\r
22511             }\r
22512             msgEl.update(text || '&#160;');\r
22513 \r
22514             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;\r
22515             var mw = msgEl.getWidth() + msgEl.getMargins('lr');\r
22516             var fw = dlg.getFrameWidth('lr');\r
22517             var bw = dlg.body.getFrameWidth('lr');\r
22518             if (Ext.isIE && iw > 0){\r
22519                 //3 pixels get subtracted in the icon CSS for an IE margin issue,\r
22520                 //so we have to add it back here for the overall width to be consistent\r
22521                 iw += 3;\r
22522             }\r
22523             var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),\r
22524                         Math.max(opt.minWidth || this.minWidth, bwidth || 0));\r
22525 \r
22526             if(opt.prompt === true){\r
22527                 activeTextEl.setWidth(w-iw-fw-bw);\r
22528             }\r
22529             if(opt.progress === true || opt.wait === true){\r
22530                 progressBar.setSize(w-iw-fw-bw);\r
22531             }\r
22532             if(Ext.isIE && w == bwidth){\r
22533                 w += 4; //Add offset when the content width is smaller than the buttons.    \r
22534             }\r
22535             dlg.setSize(w, 'auto').center();\r
22536             return this;\r
22537         },\r
22538 \r
22539         \r
22540         updateProgress : function(value, progressText, msg){\r
22541             progressBar.updateProgress(value, progressText);\r
22542             if(msg){\r
22543                 this.updateText(msg);\r
22544             }\r
22545             return this;\r
22546         },\r
22547 \r
22548         \r
22549         isVisible : function(){\r
22550             return dlg && dlg.isVisible();\r
22551         },\r
22552 \r
22553         \r
22554         hide : function(){\r
22555             var proxy = dlg.activeGhost;\r
22556             if(this.isVisible() || proxy) {\r
22557                 dlg.hide();\r
22558                 handleHide();\r
22559                 if (proxy) {\r
22560                     proxy.hide();\r
22561                 } \r
22562             }\r
22563             return this;\r
22564         },\r
22565 \r
22566         \r
22567         show : function(options){\r
22568             if(this.isVisible()){\r
22569                 this.hide();\r
22570             }\r
22571             opt = options;\r
22572             var d = this.getDialog(opt.title || "&#160;");\r
22573 \r
22574             d.setTitle(opt.title || "&#160;");\r
22575             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);\r
22576             d.tools.close.setDisplayed(allowClose);\r
22577             activeTextEl = textboxEl;\r
22578             opt.prompt = opt.prompt || (opt.multiline ? true : false);\r
22579             if(opt.prompt){\r
22580                 if(opt.multiline){\r
22581                     textboxEl.hide();\r
22582                     textareaEl.show();\r
22583                     textareaEl.setHeight(typeof opt.multiline == "number" ?\r
22584                         opt.multiline : this.defaultTextHeight);\r
22585                     activeTextEl = textareaEl;\r
22586                 }else{\r
22587                     textboxEl.show();\r
22588                     textareaEl.hide();\r
22589                 }\r
22590             }else{\r
22591                 textboxEl.hide();\r
22592                 textareaEl.hide();\r
22593             }\r
22594             activeTextEl.dom.value = opt.value || "";\r
22595             if(opt.prompt){\r
22596                 d.focusEl = activeTextEl;\r
22597             }else{\r
22598                 var bs = opt.buttons;\r
22599                 var db = null;\r
22600                 if(bs && bs.ok){\r
22601                     db = buttons["ok"];\r
22602                 }else if(bs && bs.yes){\r
22603                     db = buttons["yes"];\r
22604                 }\r
22605                 if (db){\r
22606                     d.focusEl = db;\r
22607                 }\r
22608             }\r
22609             if(opt.iconCls){\r
22610               d.setIconClass(opt.iconCls);\r
22611             }\r
22612             this.setIcon(opt.icon);\r
22613             bwidth = updateButtons(opt.buttons);\r
22614             progressBar.setVisible(opt.progress === true || opt.wait === true);\r
22615             this.updateProgress(0, opt.progressText);\r
22616             this.updateText(opt.msg);\r
22617             if(opt.cls){\r
22618                 d.el.addClass(opt.cls);\r
22619             }\r
22620             d.proxyDrag = opt.proxyDrag === true;\r
22621             d.modal = opt.modal !== false;\r
22622             d.mask = opt.modal !== false ? mask : false;\r
22623             if(!d.isVisible()){\r
22624                 // force it to the end of the z-index stack so it gets a cursor in FF\r
22625                 document.body.appendChild(dlg.el.dom);\r
22626                 d.setAnimateTarget(opt.animEl);\r
22627                 d.show(opt.animEl);\r
22628             }\r
22629 \r
22630             //workaround for window internally enabling keymap in afterShow\r
22631             d.on('show', function(){\r
22632                 if(allowClose === true){\r
22633                     d.keyMap.enable();\r
22634                 }else{\r
22635                     d.keyMap.disable();\r
22636                 }\r
22637             }, this, {single:true});\r
22638 \r
22639             if(opt.wait === true){\r
22640                 progressBar.wait(opt.waitConfig);\r
22641             }\r
22642             return this;\r
22643         },\r
22644 \r
22645         \r
22646         setIcon : function(icon){\r
22647             if(icon && icon != ''){\r
22648                 iconEl.removeClass('x-hidden');\r
22649                 iconEl.replaceClass(iconCls, icon);\r
22650                 iconCls = icon;\r
22651             }else{\r
22652                 iconEl.replaceClass(iconCls, 'x-hidden');\r
22653                 iconCls = '';\r
22654             }\r
22655             return this;\r
22656         },\r
22657 \r
22658         \r
22659         progress : function(title, msg, progressText){\r
22660             this.show({\r
22661                 title : title,\r
22662                 msg : msg,\r
22663                 buttons: false,\r
22664                 progress:true,\r
22665                 closable:false,\r
22666                 minWidth: this.minProgressWidth,\r
22667                 progressText: progressText\r
22668             });\r
22669             return this;\r
22670         },\r
22671 \r
22672         \r
22673         wait : function(msg, title, config){\r
22674             this.show({\r
22675                 title : title,\r
22676                 msg : msg,\r
22677                 buttons: false,\r
22678                 closable:false,\r
22679                 wait:true,\r
22680                 modal:true,\r
22681                 minWidth: this.minProgressWidth,\r
22682                 waitConfig: config\r
22683             });\r
22684             return this;\r
22685         },\r
22686 \r
22687         \r
22688         alert : function(title, msg, fn, scope){\r
22689             this.show({\r
22690                 title : title,\r
22691                 msg : msg,\r
22692                 buttons: this.OK,\r
22693                 fn: fn,\r
22694                 scope : scope\r
22695             });\r
22696             return this;\r
22697         },\r
22698 \r
22699         \r
22700         confirm : function(title, msg, fn, scope){\r
22701             this.show({\r
22702                 title : title,\r
22703                 msg : msg,\r
22704                 buttons: this.YESNO,\r
22705                 fn: fn,\r
22706                 scope : scope,\r
22707                 icon: this.QUESTION\r
22708             });\r
22709             return this;\r
22710         },\r
22711 \r
22712         \r
22713         prompt : function(title, msg, fn, scope, multiline, value){\r
22714             this.show({\r
22715                 title : title,\r
22716                 msg : msg,\r
22717                 buttons: this.OKCANCEL,\r
22718                 fn: fn,\r
22719                 minWidth:250,\r
22720                 scope : scope,\r
22721                 prompt:true,\r
22722                 multiline: multiline,\r
22723                 value: value\r
22724             });\r
22725             return this;\r
22726         },\r
22727 \r
22728         \r
22729         OK : {ok:true},\r
22730         \r
22731         CANCEL : {cancel:true},\r
22732         \r
22733         OKCANCEL : {ok:true, cancel:true},\r
22734         \r
22735         YESNO : {yes:true, no:true},\r
22736         \r
22737         YESNOCANCEL : {yes:true, no:true, cancel:true},\r
22738         \r
22739         INFO : 'ext-mb-info',\r
22740         \r
22741         WARNING : 'ext-mb-warning',\r
22742         \r
22743         QUESTION : 'ext-mb-question',\r
22744         \r
22745         ERROR : 'ext-mb-error',\r
22746 \r
22747         \r
22748         defaultTextHeight : 75,\r
22749         \r
22750         maxWidth : 600,\r
22751         \r
22752         minWidth : 100,\r
22753         \r
22754         minProgressWidth : 250,\r
22755         \r
22756         buttonText : {\r
22757             ok : "OK",\r
22758             cancel : "Cancel",\r
22759             yes : "Yes",\r
22760             no : "No"\r
22761         }\r
22762     };\r
22763 }();\r
22764 \r
22765 \r
22766 Ext.Msg = Ext.MessageBox;\r
22767 \r
22768 Ext.Tip = Ext.extend(Ext.Panel, {\r
22769     \r
22770     \r
22771     \r
22772     minWidth : 40,\r
22773     \r
22774     maxWidth : 300,\r
22775     \r
22776     shadow : "sides",\r
22777     \r
22778     defaultAlign : "tl-bl?",\r
22779     autoRender: true,\r
22780     quickShowInterval : 250,\r
22781 \r
22782     // private panel overrides\r
22783     frame:true,\r
22784     hidden:true,\r
22785     baseCls: 'x-tip',\r
22786     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},\r
22787     autoHeight:true,\r
22788 \r
22789     // private\r
22790     initComponent : function(){\r
22791         Ext.Tip.superclass.initComponent.call(this);\r
22792         if(this.closable && !this.title){\r
22793             this.elements += ',header';\r
22794         }\r
22795     },\r
22796 \r
22797     // private\r
22798     afterRender : function(){\r
22799         Ext.Tip.superclass.afterRender.call(this);\r
22800         if(this.closable){\r
22801             this.addTool({\r
22802                 id: 'close',\r
22803                 handler: this.hide,\r
22804                 scope: this\r
22805             });\r
22806         }\r
22807     },\r
22808 \r
22809     \r
22810     showAt : function(xy){\r
22811         Ext.Tip.superclass.show.call(this);\r
22812         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){\r
22813             this.doAutoWidth();\r
22814         }\r
22815         if(this.constrainPosition){\r
22816             xy = this.el.adjustForConstraints(xy);\r
22817         }\r
22818         this.setPagePosition(xy[0], xy[1]);\r
22819     },\r
22820 \r
22821     // protected\r
22822     doAutoWidth : function(){\r
22823         var bw = this.body.getTextWidth();\r
22824         if(this.title){\r
22825             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));\r
22826         }\r
22827         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");\r
22828         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));\r
22829         \r
22830         // IE7 repaint bug on initial show\r
22831         if(Ext.isIE7 && !this.repainted){\r
22832             this.el.repaint();\r
22833             this.repainted = true;\r
22834         }\r
22835     },\r
22836 \r
22837     \r
22838     showBy : function(el, pos){\r
22839         if(!this.rendered){\r
22840             this.render(Ext.getBody());\r
22841         }\r
22842         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));\r
22843     },\r
22844 \r
22845     initDraggable : function(){\r
22846         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);\r
22847         this.header.addClass('x-tip-draggable');\r
22848     }\r
22849 });\r
22850 \r
22851 // private - custom Tip DD implementation\r
22852 Ext.Tip.DD = function(tip, config){\r
22853     Ext.apply(this, config);\r
22854     this.tip = tip;\r
22855     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);\r
22856     this.setHandleElId(tip.header.id);\r
22857     this.scroll = false;\r
22858 };\r
22859 \r
22860 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {\r
22861     moveOnly:true,\r
22862     scroll:false,\r
22863     headerOffsets:[100, 25],\r
22864     startDrag : function(){\r
22865         this.tip.el.disableShadow();\r
22866     },\r
22867     endDrag : function(e){\r
22868         this.tip.el.enableShadow(true);\r
22869     }\r
22870 });\r
22871 \r
22872 Ext.ToolTip = Ext.extend(Ext.Tip, {\r
22873     \r
22874     \r
22875     \r
22876     showDelay: 500,\r
22877     \r
22878     hideDelay: 200,\r
22879     \r
22880     dismissDelay: 5000,\r
22881     \r
22882     mouseOffset: [15,18],\r
22883     \r
22884     trackMouse : false,\r
22885     constrainPosition: true,\r
22886 \r
22887     // private\r
22888     initComponent: function(){\r
22889         Ext.ToolTip.superclass.initComponent.call(this);\r
22890         this.lastActive = new Date();\r
22891         this.initTarget();\r
22892     },\r
22893 \r
22894     // private\r
22895     initTarget : function(){\r
22896         if(this.target){\r
22897             this.target = Ext.get(this.target);\r
22898             this.target.on('mouseover', this.onTargetOver, this);\r
22899             this.target.on('mouseout', this.onTargetOut, this);\r
22900             this.target.on('mousemove', this.onMouseMove, this);\r
22901         }\r
22902     },\r
22903 \r
22904     // private\r
22905     onMouseMove : function(e){\r
22906         this.targetXY = e.getXY();\r
22907         if(!this.hidden && this.trackMouse){\r
22908             this.setPagePosition(this.getTargetXY());\r
22909         }\r
22910     },\r
22911 \r
22912     // private\r
22913     getTargetXY : function(){\r
22914         return [this.targetXY[0]+this.mouseOffset[0], this.targetXY[1]+this.mouseOffset[1]];\r
22915     },\r
22916 \r
22917     // private\r
22918     onTargetOver : function(e){\r
22919         if(this.disabled || e.within(this.target.dom, true)){\r
22920             return;\r
22921         }\r
22922         this.clearTimer('hide');\r
22923         this.targetXY = e.getXY();\r
22924         this.delayShow();\r
22925     },\r
22926 \r
22927     // private\r
22928     delayShow : function(){\r
22929         if(this.hidden && !this.showTimer){\r
22930             if(this.lastActive.getElapsed() < this.quickShowInterval){\r
22931                 this.show();\r
22932             }else{\r
22933                 this.showTimer = this.show.defer(this.showDelay, this);\r
22934             }\r
22935         }else if(!this.hidden && this.autoHide !== false){\r
22936             this.show();\r
22937         }\r
22938     },\r
22939 \r
22940     // private\r
22941     onTargetOut : function(e){\r
22942         if(this.disabled || e.within(this.target.dom, true)){\r
22943             return;\r
22944         }\r
22945         this.clearTimer('show');\r
22946         if(this.autoHide !== false){\r
22947             this.delayHide();\r
22948         }\r
22949     },\r
22950 \r
22951     // private\r
22952     delayHide : function(){\r
22953         if(!this.hidden && !this.hideTimer){\r
22954             this.hideTimer = this.hide.defer(this.hideDelay, this);\r
22955         }\r
22956     },\r
22957 \r
22958     \r
22959     hide: function(){\r
22960         this.clearTimer('dismiss');\r
22961         this.lastActive = new Date();\r
22962         Ext.ToolTip.superclass.hide.call(this);\r
22963     },\r
22964 \r
22965     \r
22966     show : function(){\r
22967         this.showAt(this.getTargetXY());\r
22968     },\r
22969 \r
22970     // inherit docs\r
22971     showAt : function(xy){\r
22972         this.lastActive = new Date();\r
22973         this.clearTimers();\r
22974         Ext.ToolTip.superclass.showAt.call(this, xy);\r
22975         if(this.dismissDelay && this.autoHide !== false){\r
22976             this.dismissTimer = this.hide.defer(this.dismissDelay, this);\r
22977         }\r
22978     },\r
22979 \r
22980     // private\r
22981     clearTimer : function(name){\r
22982         name = name + 'Timer';\r
22983         clearTimeout(this[name]);\r
22984         delete this[name];\r
22985     },\r
22986 \r
22987     // private\r
22988     clearTimers : function(){\r
22989         this.clearTimer('show');\r
22990         this.clearTimer('dismiss');\r
22991         this.clearTimer('hide');\r
22992     },\r
22993 \r
22994     // private\r
22995     onShow : function(){\r
22996         Ext.ToolTip.superclass.onShow.call(this);\r
22997         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);\r
22998     },\r
22999 \r
23000     // private\r
23001     onHide : function(){\r
23002         Ext.ToolTip.superclass.onHide.call(this);\r
23003         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);\r
23004     },\r
23005 \r
23006     // private\r
23007     onDocMouseDown : function(e){\r
23008         if(this.autoHide !== false && !e.within(this.el.dom)){\r
23009             this.disable();\r
23010             this.enable.defer(100, this);\r
23011         }\r
23012     },\r
23013 \r
23014     // private\r
23015     onDisable : function(){\r
23016         this.clearTimers();\r
23017         this.hide();\r
23018     },\r
23019 \r
23020     // private\r
23021     adjustPosition : function(x, y){\r
23022         // keep the position from being under the mouse\r
23023         var ay = this.targetXY[1], h = this.getSize().height;\r
23024         if(this.constrainPosition && y <= ay && (y+h) >= ay){\r
23025             y = ay-h-5;\r
23026         }\r
23027         return {x : x, y: y};\r
23028     },\r
23029 \r
23030     // private\r
23031     onDestroy : function(){\r
23032         Ext.ToolTip.superclass.onDestroy.call(this);\r
23033         if(this.target){\r
23034             this.target.un('mouseover', this.onTargetOver, this);\r
23035             this.target.un('mouseout', this.onTargetOut, this);\r
23036             this.target.un('mousemove', this.onMouseMove, this);\r
23037         }\r
23038     }\r
23039 });\r
23040 \r
23041 Ext.QuickTip = Ext.extend(Ext.ToolTip, {\r
23042     \r
23043     \r
23044     interceptTitles : false,\r
23045 \r
23046     // private\r
23047     tagConfig : {\r
23048         namespace : "ext",\r
23049         attribute : "qtip",\r
23050         width : "qwidth",\r
23051         target : "target",\r
23052         title : "qtitle",\r
23053         hide : "hide",\r
23054         cls : "qclass",\r
23055         align : "qalign"\r
23056     },\r
23057 \r
23058     // private\r
23059     initComponent : function(){\r
23060         this.target = this.target || Ext.getDoc();\r
23061         this.targets = this.targets || {};\r
23062         Ext.QuickTip.superclass.initComponent.call(this);\r
23063     },\r
23064 \r
23065     \r
23066     register : function(config){\r
23067         var cs = Ext.isArray(config) ? config : arguments;\r
23068         for(var i = 0, len = cs.length; i < len; i++){\r
23069             var c = cs[i];\r
23070             var target = c.target;\r
23071             if(target){\r
23072                 if(Ext.isArray(target)){\r
23073                     for(var j = 0, jlen = target.length; j < jlen; j++){\r
23074                         this.targets[Ext.id(target[j])] = c;\r
23075                     }\r
23076                 } else{\r
23077                     this.targets[Ext.id(target)] = c;\r
23078                 }\r
23079             }\r
23080         }\r
23081     },\r
23082 \r
23083     \r
23084     unregister : function(el){\r
23085         delete this.targets[Ext.id(el)];\r
23086     },\r
23087 \r
23088     // private\r
23089     onTargetOver : function(e){\r
23090         if(this.disabled){\r
23091             return;\r
23092         }\r
23093         this.targetXY = e.getXY();\r
23094         var t = e.getTarget();\r
23095         if(!t || t.nodeType !== 1 || t == document || t == document.body){\r
23096             return;\r
23097         }\r
23098         if(this.activeTarget && t == this.activeTarget.el){\r
23099             this.clearTimer('hide');\r
23100             this.show();\r
23101             return;\r
23102         }\r
23103         if(t && this.targets[t.id]){\r
23104             this.activeTarget = this.targets[t.id];\r
23105             this.activeTarget.el = t;\r
23106             this.delayShow();\r
23107             return;\r
23108         }\r
23109         var ttp, et = Ext.fly(t), cfg = this.tagConfig;\r
23110         var ns = cfg.namespace;\r
23111         if(this.interceptTitles && t.title){\r
23112             ttp = t.title;\r
23113             t.qtip = ttp;\r
23114             t.removeAttribute("title");\r
23115             e.preventDefault();\r
23116         } else{\r
23117             ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);\r
23118         }\r
23119         if(ttp){\r
23120             var autoHide = et.getAttributeNS(ns, cfg.hide);\r
23121             this.activeTarget = {\r
23122                 el: t,\r
23123                 text: ttp,\r
23124                 width: et.getAttributeNS(ns, cfg.width),\r
23125                 autoHide: autoHide != "user" && autoHide !== 'false',\r
23126                 title: et.getAttributeNS(ns, cfg.title),\r
23127                 cls: et.getAttributeNS(ns, cfg.cls),\r
23128                 align: et.getAttributeNS(ns, cfg.align)\r
23129             };\r
23130             this.delayShow();\r
23131         }\r
23132     },\r
23133 \r
23134     // private\r
23135     onTargetOut : function(e){\r
23136         this.clearTimer('show');\r
23137         if(this.autoHide !== false){\r
23138             this.delayHide();\r
23139         }\r
23140     },\r
23141 \r
23142     // inherit docs\r
23143     showAt : function(xy){\r
23144         var t = this.activeTarget;\r
23145         if(t){\r
23146             if(!this.rendered){\r
23147                 this.render(Ext.getBody());\r
23148                 this.activeTarget = t;\r
23149             }\r
23150             if(t.width){\r
23151                 this.setWidth(t.width);\r
23152                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));\r
23153                 this.measureWidth = false;\r
23154             } else{\r
23155                 this.measureWidth = true;\r
23156             }\r
23157             this.setTitle(t.title || '');\r
23158             this.body.update(t.text);\r
23159             this.autoHide = t.autoHide;\r
23160             this.dismissDelay = t.dismissDelay || this.dismissDelay;\r
23161             if(this.lastCls){\r
23162                 this.el.removeClass(this.lastCls);\r
23163                 delete this.lastCls;\r
23164             }\r
23165             if(t.cls){\r
23166                 this.el.addClass(t.cls);\r
23167                 this.lastCls = t.cls;\r
23168             }\r
23169             if(t.align){ // TODO: this doesn't seem to work consistently\r
23170                 xy = this.el.getAlignToXY(t.el, t.align);\r
23171                 this.constrainPosition = false;\r
23172             } else{\r
23173                 this.constrainPosition = true;\r
23174             }\r
23175         }\r
23176         Ext.QuickTip.superclass.showAt.call(this, xy);\r
23177     },\r
23178 \r
23179     // inherit docs\r
23180     hide: function(){\r
23181         delete this.activeTarget;\r
23182         Ext.QuickTip.superclass.hide.call(this);\r
23183     }\r
23184 });\r
23185 \r
23186 Ext.QuickTips = function(){\r
23187     var tip, locks = [];\r
23188     return {\r
23189         \r
23190         init : function(autoRender){\r
23191                     if(!tip){\r
23192                         if(!Ext.isReady){\r
23193                             Ext.onReady(function(){\r
23194                                 Ext.QuickTips.init(autoRender);\r
23195                             });\r
23196                             return;\r
23197                         }\r
23198                         tip = new Ext.QuickTip({elements:'header,body'});\r
23199                         if(autoRender !== false){\r
23200                             tip.render(Ext.getBody());\r
23201                         }\r
23202                     }\r
23203         },\r
23204 \r
23205         \r
23206         enable : function(){\r
23207             if(tip){\r
23208                 locks.pop();\r
23209                 if(locks.length < 1){\r
23210                     tip.enable();\r
23211                 }\r
23212             }\r
23213         },\r
23214 \r
23215         \r
23216         disable : function(){\r
23217             if(tip){\r
23218                 tip.disable();\r
23219             }\r
23220             locks.push(1);\r
23221         },\r
23222 \r
23223         \r
23224         isEnabled : function(){\r
23225             return tip !== undefined && !tip.disabled;\r
23226         },\r
23227 \r
23228         \r
23229         getQuickTip : function(){\r
23230             return tip;\r
23231         },\r
23232 \r
23233         \r
23234         register : function(){\r
23235             tip.register.apply(tip, arguments);\r
23236         },\r
23237 \r
23238         \r
23239         unregister : function(){\r
23240             tip.unregister.apply(tip, arguments);\r
23241         },\r
23242 \r
23243         \r
23244         tips :function(){\r
23245             tip.register.apply(tip, arguments);\r
23246         }\r
23247     }\r
23248 }();\r
23249 \r
23250 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {\r
23251     rootVisible : true,\r
23252     animate: Ext.enableFx,\r
23253     lines : true,\r
23254     enableDD : false,\r
23255     hlDrop : Ext.enableFx,\r
23256     pathSeparator: "/",\r
23257 \r
23258     initComponent : function(){\r
23259         Ext.tree.TreePanel.superclass.initComponent.call(this);\r
23260 \r
23261         if(!this.eventModel){\r
23262             this.eventModel = new Ext.tree.TreeEventModel(this);\r
23263         }\r
23264         \r
23265         // initialize the loader\r
23266         var l = this.loader;\r
23267         if(!l){\r
23268             l = new Ext.tree.TreeLoader({\r
23269                 dataUrl: this.dataUrl\r
23270             });\r
23271         }else if(typeof l == 'object' && !l.load){\r
23272             l = new Ext.tree.TreeLoader(l);\r
23273         }\r
23274         this.loader = l;\r
23275         \r
23276         this.nodeHash = {};\r
23277 \r
23278         \r
23279         if(this.root){\r
23280            this.setRootNode(this.root);\r
23281         }\r
23282 \r
23283         this.addEvents(\r
23284 \r
23285             \r
23286            "append",\r
23287            \r
23288            "remove",\r
23289            \r
23290            "movenode",\r
23291            \r
23292            "insert",\r
23293            \r
23294            "beforeappend",\r
23295            \r
23296            "beforeremove",\r
23297            \r
23298            "beforemovenode",\r
23299            \r
23300             "beforeinsert",\r
23301 \r
23302             \r
23303             "beforeload",\r
23304             \r
23305             "load",\r
23306             \r
23307             "textchange",\r
23308             \r
23309             "beforeexpandnode",\r
23310             \r
23311             "beforecollapsenode",\r
23312             \r
23313             "expandnode",\r
23314             \r
23315             "disabledchange",\r
23316             \r
23317             "collapsenode",\r
23318             \r
23319             "beforeclick",\r
23320             \r
23321             "click",\r
23322             \r
23323             "checkchange",\r
23324             \r
23325             "dblclick",\r
23326             \r
23327             "contextmenu",\r
23328             \r
23329             "beforechildrenrendered",\r
23330            \r
23331             "startdrag",\r
23332             \r
23333             "enddrag",\r
23334             \r
23335             "dragdrop",\r
23336             \r
23337             "beforenodedrop",\r
23338             \r
23339             "nodedrop",\r
23340              \r
23341             "nodedragover"\r
23342         );\r
23343         if(this.singleExpand){\r
23344             this.on("beforeexpandnode", this.restrictExpand, this);\r
23345         }\r
23346     },\r
23347 \r
23348     // private\r
23349     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){\r
23350         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){\r
23351             ename = ename+'node';\r
23352         }\r
23353         // args inline for performance while bubbling events\r
23354         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);\r
23355     },\r
23356 \r
23357 \r
23358     \r
23359     getRootNode : function(){\r
23360         return this.root;\r
23361     },\r
23362 \r
23363     \r
23364     setRootNode : function(node){\r
23365         if(!node.render){ // attributes passed\r
23366             node = this.loader.createNode(node);\r
23367         }\r
23368         this.root = node;\r
23369         node.ownerTree = this;\r
23370         node.isRoot = true;\r
23371         this.registerNode(node);\r
23372         if(!this.rootVisible){\r
23373                 var uiP = node.attributes.uiProvider;\r
23374                 node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node); \r
23375         }\r
23376         return node;\r
23377     },\r
23378 \r
23379     \r
23380     getNodeById : function(id){\r
23381         return this.nodeHash[id];\r
23382     },\r
23383 \r
23384     // private\r
23385     registerNode : function(node){\r
23386         this.nodeHash[node.id] = node;\r
23387     },\r
23388 \r
23389     // private\r
23390     unregisterNode : function(node){\r
23391         delete this.nodeHash[node.id];\r
23392     },\r
23393 \r
23394     // private\r
23395     toString : function(){\r
23396         return "[Tree"+(this.id?" "+this.id:"")+"]";\r
23397     },\r
23398 \r
23399     // private\r
23400     restrictExpand : function(node){\r
23401         var p = node.parentNode;\r
23402         if(p){\r
23403             if(p.expandedChild && p.expandedChild.parentNode == p){\r
23404                 p.expandedChild.collapse();\r
23405             }\r
23406             p.expandedChild = node;\r
23407         }\r
23408     },\r
23409 \r
23410     \r
23411     getChecked : function(a, startNode){\r
23412         startNode = startNode || this.root;\r
23413         var r = [];\r
23414         var f = function(){\r
23415             if(this.attributes.checked){\r
23416                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));\r
23417             }\r
23418         }\r
23419         startNode.cascade(f);\r
23420         return r;\r
23421     },\r
23422 \r
23423     \r
23424     getEl : function(){\r
23425         return this.el;\r
23426     },\r
23427 \r
23428     \r
23429     getLoader : function(){\r
23430         return this.loader;\r
23431     },\r
23432 \r
23433     \r
23434     expandAll : function(){\r
23435         this.root.expand(true);\r
23436     },\r
23437 \r
23438     \r
23439     collapseAll : function(){\r
23440         this.root.collapse(true);\r
23441     },\r
23442 \r
23443     \r
23444     getSelectionModel : function(){\r
23445         if(!this.selModel){\r
23446             this.selModel = new Ext.tree.DefaultSelectionModel();\r
23447         }\r
23448         return this.selModel;\r
23449     },\r
23450 \r
23451     \r
23452     expandPath : function(path, attr, callback){\r
23453         attr = attr || "id";\r
23454         var keys = path.split(this.pathSeparator);\r
23455         var curNode = this.root;\r
23456         if(curNode.attributes[attr] != keys[1]){ // invalid root\r
23457             if(callback){\r
23458                 callback(false, null);\r
23459             }\r
23460             return;\r
23461         }\r
23462         var index = 1;\r
23463         var f = function(){\r
23464             if(++index == keys.length){\r
23465                 if(callback){\r
23466                     callback(true, curNode);\r
23467                 }\r
23468                 return;\r
23469             }\r
23470             var c = curNode.findChild(attr, keys[index]);\r
23471             if(!c){\r
23472                 if(callback){\r
23473                     callback(false, curNode);\r
23474                 }\r
23475                 return;\r
23476             }\r
23477             curNode = c;\r
23478             c.expand(false, false, f);\r
23479         };\r
23480         curNode.expand(false, false, f);\r
23481     },\r
23482 \r
23483     \r
23484     selectPath : function(path, attr, callback){\r
23485         attr = attr || "id";\r
23486         var keys = path.split(this.pathSeparator);\r
23487         var v = keys.pop();\r
23488         if(keys.length > 0){\r
23489             var f = function(success, node){\r
23490                 if(success && node){\r
23491                     var n = node.findChild(attr, v);\r
23492                     if(n){\r
23493                         n.select();\r
23494                         if(callback){\r
23495                             callback(true, n);\r
23496                         }\r
23497                     }else if(callback){\r
23498                         callback(false, n);\r
23499                     }\r
23500                 }else{\r
23501                     if(callback){\r
23502                         callback(false, n);\r
23503                     }\r
23504                 }\r
23505             };\r
23506             this.expandPath(keys.join(this.pathSeparator), attr, f);\r
23507         }else{\r
23508             this.root.select();\r
23509             if(callback){\r
23510                 callback(true, this.root);\r
23511             }\r
23512         }\r
23513     },\r
23514 \r
23515     \r
23516     getTreeEl : function(){\r
23517         return this.body;\r
23518     },\r
23519 \r
23520     // private\r
23521     onRender : function(ct, position){\r
23522         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);\r
23523         this.el.addClass('x-tree');\r
23524         this.innerCt = this.body.createChild({tag:"ul",\r
23525                cls:"x-tree-root-ct " +\r
23526                (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});\r
23527     },\r
23528 \r
23529     // private\r
23530     initEvents : function(){\r
23531         Ext.tree.TreePanel.superclass.initEvents.call(this);\r
23532 \r
23533         if(this.containerScroll){\r
23534             Ext.dd.ScrollManager.register(this.body);\r
23535         }\r
23536         if((this.enableDD || this.enableDrop) && !this.dropZone){\r
23537            \r
23538              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {\r
23539                ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true\r
23540            });\r
23541         }\r
23542         if((this.enableDD || this.enableDrag) && !this.dragZone){\r
23543            \r
23544             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {\r
23545                ddGroup: this.ddGroup || "TreeDD",\r
23546                scroll: this.ddScroll\r
23547            });\r
23548         }\r
23549         this.getSelectionModel().init(this);\r
23550     },\r
23551 \r
23552     // private\r
23553     afterRender : function(){\r
23554         Ext.tree.TreePanel.superclass.afterRender.call(this);\r
23555         this.root.render();\r
23556         if(!this.rootVisible){\r
23557             this.root.renderChildren();\r
23558         }\r
23559     },\r
23560 \r
23561     onDestroy : function(){\r
23562         if(this.rendered){\r
23563             this.body.removeAllListeners();\r
23564             Ext.dd.ScrollManager.unregister(this.body);\r
23565             if(this.dropZone){\r
23566                 this.dropZone.unreg();\r
23567             }\r
23568             if(this.dragZone){\r
23569                this.dragZone.unreg();\r
23570             }\r
23571         }\r
23572         this.root.destroy();\r
23573         this.nodeHash = null;\r
23574         Ext.tree.TreePanel.superclass.onDestroy.call(this);\r
23575     }\r
23576     \r
23577     \r
23578     \r
23579     \r
23580     \r
23581     \r
23582     \r
23583     \r
23584     \r
23585     \r
23586     \r
23587     \r
23588     \r
23589     \r
23590     \r
23591     \r
23592     \r
23593     \r
23594     \r
23595     \r
23596     \r
23597     \r
23598     \r
23599     \r
23600     \r
23601     \r
23602     \r
23603     \r
23604     \r
23605     \r
23606     \r
23607     \r
23608 \r
23609 \r
23610 \r
23611     \r
23612     \r
23613     \r
23614     \r
23615     \r
23616     \r
23617     \r
23618     \r
23619     \r
23620     \r
23621     \r
23622     \r
23623 });\r
23624 \r
23625 Ext.tree.TreePanel.nodeTypes = {};\r
23626 \r
23627 Ext.reg('treepanel', Ext.tree.TreePanel);\r
23628 Ext.tree.TreeEventModel = function(tree){\r
23629     this.tree = tree;\r
23630     this.tree.on('render', this.initEvents, this);\r
23631 }\r
23632 \r
23633 Ext.tree.TreeEventModel.prototype = {\r
23634     initEvents : function(){\r
23635         var el = this.tree.getTreeEl();\r
23636         el.on('click', this.delegateClick, this);\r
23637         if(this.tree.trackMouseOver !== false){\r
23638             el.on('mouseover', this.delegateOver, this);\r
23639             el.on('mouseout', this.delegateOut, this);\r
23640         }\r
23641         el.on('dblclick', this.delegateDblClick, this);\r
23642         el.on('contextmenu', this.delegateContextMenu, this);\r
23643     },\r
23644 \r
23645     getNode : function(e){\r
23646         var t;\r
23647         if(t = e.getTarget('.x-tree-node-el', 10)){\r
23648             var id = Ext.fly(t, '_treeEvents').getAttributeNS('ext', 'tree-node-id');\r
23649             if(id){\r
23650                 return this.tree.getNodeById(id);\r
23651             }\r
23652         }\r
23653         return null;\r
23654     },\r
23655 \r
23656     getNodeTarget : function(e){\r
23657         var t = e.getTarget('.x-tree-node-icon', 1);\r
23658         if(!t){\r
23659             t = e.getTarget('.x-tree-node-el', 6);\r
23660         }\r
23661         return t;\r
23662     },\r
23663 \r
23664     delegateOut : function(e, t){\r
23665         if(!this.beforeEvent(e)){\r
23666             return;\r
23667         }\r
23668         if(e.getTarget('.x-tree-ec-icon', 1)){\r
23669             var n = this.getNode(e);\r
23670             this.onIconOut(e, n);\r
23671             if(n == this.lastEcOver){\r
23672                 delete this.lastEcOver;\r
23673             }\r
23674         }\r
23675         if((t = this.getNodeTarget(e)) && !e.within(t, true)){\r
23676             this.onNodeOut(e, this.getNode(e));\r
23677         }\r
23678     },\r
23679 \r
23680     delegateOver : function(e, t){\r
23681         if(!this.beforeEvent(e)){\r
23682             return;\r
23683         }\r
23684         if(this.lastEcOver){ // prevent hung highlight\r
23685             this.onIconOut(e, this.lastEcOver);\r
23686             delete this.lastEcOver;\r
23687         }\r
23688         if(e.getTarget('.x-tree-ec-icon', 1)){\r
23689             this.lastEcOver = this.getNode(e);\r
23690             this.onIconOver(e, this.lastEcOver);\r
23691         }\r
23692         if(t = this.getNodeTarget(e)){\r
23693             this.onNodeOver(e, this.getNode(e));\r
23694         }\r
23695     },\r
23696 \r
23697     delegateClick : function(e, t){\r
23698         if(!this.beforeEvent(e)){\r
23699             return;\r
23700         }\r
23701 \r
23702         if(e.getTarget('input[type=checkbox]', 1)){\r
23703             this.onCheckboxClick(e, this.getNode(e));\r
23704         }\r
23705         else if(e.getTarget('.x-tree-ec-icon', 1)){\r
23706             this.onIconClick(e, this.getNode(e));\r
23707         }\r
23708         else if(this.getNodeTarget(e)){\r
23709             this.onNodeClick(e, this.getNode(e));\r
23710         }\r
23711     },\r
23712 \r
23713     delegateDblClick : function(e, t){\r
23714         if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
23715             this.onNodeDblClick(e, this.getNode(e));\r
23716         }\r
23717     },\r
23718 \r
23719     delegateContextMenu : function(e, t){\r
23720         if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
23721             this.onNodeContextMenu(e, this.getNode(e));\r
23722         }\r
23723     },\r
23724 \r
23725     onNodeClick : function(e, node){\r
23726         node.ui.onClick(e);\r
23727     },\r
23728 \r
23729     onNodeOver : function(e, node){\r
23730         node.ui.onOver(e);\r
23731     },\r
23732 \r
23733     onNodeOut : function(e, node){\r
23734         node.ui.onOut(e);\r
23735     },\r
23736 \r
23737     onIconOver : function(e, node){\r
23738         node.ui.addClass('x-tree-ec-over');\r
23739     },\r
23740 \r
23741     onIconOut : function(e, node){\r
23742         node.ui.removeClass('x-tree-ec-over');\r
23743     },\r
23744 \r
23745     onIconClick : function(e, node){\r
23746         node.ui.ecClick(e);\r
23747     },\r
23748 \r
23749     onCheckboxClick : function(e, node){\r
23750         node.ui.onCheckChange(e);\r
23751     },\r
23752 \r
23753     onNodeDblClick : function(e, node){\r
23754         node.ui.onDblClick(e);\r
23755     },\r
23756 \r
23757     onNodeContextMenu : function(e, node){\r
23758         node.ui.onContextMenu(e);\r
23759     },\r
23760 \r
23761     beforeEvent : function(e){\r
23762         if(this.disabled){\r
23763             e.stopEvent();\r
23764             return false;\r
23765         }\r
23766         return true;\r
23767     },\r
23768 \r
23769     disable: function(){\r
23770         this.disabled = true;\r
23771     },\r
23772 \r
23773     enable: function(){\r
23774         this.disabled = false;\r
23775     }\r
23776 };\r
23777 \r
23778 Ext.tree.DefaultSelectionModel = function(config){\r
23779    this.selNode = null;\r
23780    \r
23781    this.addEvents(\r
23782        \r
23783        "selectionchange",\r
23784 \r
23785        \r
23786        "beforeselect"\r
23787    );\r
23788 \r
23789     Ext.apply(this, config);\r
23790     Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);\r
23791 };\r
23792 \r
23793 Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {\r
23794     init : function(tree){\r
23795         this.tree = tree;\r
23796         tree.getTreeEl().on("keydown", this.onKeyDown, this);\r
23797         tree.on("click", this.onNodeClick, this);\r
23798     },\r
23799     \r
23800     onNodeClick : function(node, e){\r
23801         this.select(node);\r
23802     },\r
23803     \r
23804     \r
23805     select : function(node){\r
23806         var last = this.selNode;\r
23807         if(last != node && this.fireEvent('beforeselect', this, node, last) !== false){\r
23808             if(last){\r
23809                 last.ui.onSelectedChange(false);\r
23810             }\r
23811             this.selNode = node;\r
23812             node.ui.onSelectedChange(true);\r
23813             this.fireEvent("selectionchange", this, node, last);\r
23814         }\r
23815         return node;\r
23816     },\r
23817     \r
23818     \r
23819     unselect : function(node){\r
23820         if(this.selNode == node){\r
23821             this.clearSelections();\r
23822         }    \r
23823     },\r
23824     \r
23825     \r
23826     clearSelections : function(){\r
23827         var n = this.selNode;\r
23828         if(n){\r
23829             n.ui.onSelectedChange(false);\r
23830             this.selNode = null;\r
23831             this.fireEvent("selectionchange", this, null);\r
23832         }\r
23833         return n;\r
23834     },\r
23835     \r
23836     \r
23837     getSelectedNode : function(){\r
23838         return this.selNode;    \r
23839     },\r
23840     \r
23841     \r
23842     isSelected : function(node){\r
23843         return this.selNode == node;  \r
23844     },\r
23845 \r
23846     \r
23847     selectPrevious : function(){\r
23848         var s = this.selNode || this.lastSelNode;\r
23849         if(!s){\r
23850             return null;\r
23851         }\r
23852         var ps = s.previousSibling;\r
23853         if(ps){\r
23854             if(!ps.isExpanded() || ps.childNodes.length < 1){\r
23855                 return this.select(ps);\r
23856             } else{\r
23857                 var lc = ps.lastChild;\r
23858                 while(lc && lc.isExpanded() && lc.childNodes.length > 0){\r
23859                     lc = lc.lastChild;\r
23860                 }\r
23861                 return this.select(lc);\r
23862             }\r
23863         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){\r
23864             return this.select(s.parentNode);\r
23865         }\r
23866         return null;\r
23867     },\r
23868 \r
23869     \r
23870     selectNext : function(){\r
23871         var s = this.selNode || this.lastSelNode;\r
23872         if(!s){\r
23873             return null;\r
23874         }\r
23875         if(s.firstChild && s.isExpanded()){\r
23876              return this.select(s.firstChild);\r
23877          }else if(s.nextSibling){\r
23878              return this.select(s.nextSibling);\r
23879          }else if(s.parentNode){\r
23880             var newS = null;\r
23881             s.parentNode.bubble(function(){\r
23882                 if(this.nextSibling){\r
23883                     newS = this.getOwnerTree().selModel.select(this.nextSibling);\r
23884                     return false;\r
23885                 }\r
23886             });\r
23887             return newS;\r
23888          }\r
23889         return null;\r
23890     },\r
23891 \r
23892     onKeyDown : function(e){\r
23893         var s = this.selNode || this.lastSelNode;\r
23894         // undesirable, but required\r
23895         var sm = this;\r
23896         if(!s){\r
23897             return;\r
23898         }\r
23899         var k = e.getKey();\r
23900         switch(k){\r
23901              case e.DOWN:\r
23902                  e.stopEvent();\r
23903                  this.selectNext();\r
23904              break;\r
23905              case e.UP:\r
23906                  e.stopEvent();\r
23907                  this.selectPrevious();\r
23908              break;\r
23909              case e.RIGHT:\r
23910                  e.preventDefault();\r
23911                  if(s.hasChildNodes()){\r
23912                      if(!s.isExpanded()){\r
23913                          s.expand();\r
23914                      }else if(s.firstChild){\r
23915                          this.select(s.firstChild, e);\r
23916                      }\r
23917                  }\r
23918              break;\r
23919              case e.LEFT:\r
23920                  e.preventDefault();\r
23921                  if(s.hasChildNodes() && s.isExpanded()){\r
23922                      s.collapse();\r
23923                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){\r
23924                      this.select(s.parentNode, e);\r
23925                  }\r
23926              break;\r
23927         };\r
23928     }\r
23929 });\r
23930 \r
23931 \r
23932 Ext.tree.MultiSelectionModel = function(config){\r
23933    this.selNodes = [];\r
23934    this.selMap = {};\r
23935    this.addEvents(\r
23936        \r
23937        "selectionchange"\r
23938    );\r
23939     Ext.apply(this, config);\r
23940     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);\r
23941 };\r
23942 \r
23943 Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {\r
23944     init : function(tree){\r
23945         this.tree = tree;\r
23946         tree.getTreeEl().on("keydown", this.onKeyDown, this);\r
23947         tree.on("click", this.onNodeClick, this);\r
23948     },\r
23949     \r
23950     onNodeClick : function(node, e){\r
23951         this.select(node, e, e.ctrlKey);\r
23952     },\r
23953     \r
23954     \r
23955     select : function(node, e, keepExisting){\r
23956         if(keepExisting !== true){\r
23957             this.clearSelections(true);\r
23958         }\r
23959         if(this.isSelected(node)){\r
23960             this.lastSelNode = node;\r
23961             return node;\r
23962         }\r
23963         this.selNodes.push(node);\r
23964         this.selMap[node.id] = node;\r
23965         this.lastSelNode = node;\r
23966         node.ui.onSelectedChange(true);\r
23967         this.fireEvent("selectionchange", this, this.selNodes);\r
23968         return node;\r
23969     },\r
23970     \r
23971     \r
23972     unselect : function(node){\r
23973         if(this.selMap[node.id]){\r
23974             node.ui.onSelectedChange(false);\r
23975             var sn = this.selNodes;\r
23976             var index = sn.indexOf(node);\r
23977             if(index != -1){\r
23978                 this.selNodes.splice(index, 1);\r
23979             }\r
23980             delete this.selMap[node.id];\r
23981             this.fireEvent("selectionchange", this, this.selNodes);\r
23982         }\r
23983     },\r
23984     \r
23985     \r
23986     clearSelections : function(suppressEvent){\r
23987         var sn = this.selNodes;\r
23988         if(sn.length > 0){\r
23989             for(var i = 0, len = sn.length; i < len; i++){\r
23990                 sn[i].ui.onSelectedChange(false);\r
23991             }\r
23992             this.selNodes = [];\r
23993             this.selMap = {};\r
23994             if(suppressEvent !== true){\r
23995                 this.fireEvent("selectionchange", this, this.selNodes);\r
23996             }\r
23997         }\r
23998     },\r
23999     \r
24000     \r
24001     isSelected : function(node){\r
24002         return this.selMap[node.id] ? true : false;  \r
24003     },\r
24004     \r
24005     \r
24006     getSelectedNodes : function(){\r
24007         return this.selNodes;    \r
24008     },\r
24009 \r
24010     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,\r
24011 \r
24012     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,\r
24013 \r
24014     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious\r
24015 });\r
24016 \r
24017 Ext.tree.TreeNode = function(attributes){\r
24018     attributes = attributes || {};\r
24019     if(typeof attributes == "string"){\r
24020         attributes = {text: attributes};\r
24021     }\r
24022     this.childrenRendered = false;\r
24023     this.rendered = false;\r
24024     Ext.tree.TreeNode.superclass.constructor.call(this, attributes);\r
24025     this.expanded = attributes.expanded === true;\r
24026     this.isTarget = attributes.isTarget !== false;\r
24027     this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;\r
24028     this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;\r
24029 \r
24030     \r
24031     this.text = attributes.text;\r
24032     \r
24033     this.disabled = attributes.disabled === true;\r
24034 \r
24035     this.addEvents(\r
24036         \r
24037         "textchange",\r
24038         \r
24039         "beforeexpand",\r
24040         \r
24041         "beforecollapse",\r
24042         \r
24043         "expand",\r
24044         \r
24045         "disabledchange",\r
24046         \r
24047         "collapse",\r
24048         \r
24049         "beforeclick",\r
24050         \r
24051         "click",\r
24052         \r
24053         "checkchange",\r
24054         \r
24055         "dblclick",\r
24056         \r
24057         "contextmenu",\r
24058         \r
24059         "beforechildrenrendered"\r
24060     );\r
24061 \r
24062     var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;\r
24063 \r
24064     \r
24065     this.ui = new uiClass(this);\r
24066 };\r
24067 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {\r
24068     preventHScroll: true,\r
24069     \r
24070     isExpanded : function(){\r
24071         return this.expanded;\r
24072     },\r
24073 \r
24074 \r
24075     getUI : function(){\r
24076         return this.ui;\r
24077     },\r
24078 \r
24079     getLoader : function(){\r
24080         var owner;\r
24081         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());\r
24082     },\r
24083 \r
24084     // private override\r
24085     setFirstChild : function(node){\r
24086         var of = this.firstChild;\r
24087         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);\r
24088         if(this.childrenRendered && of && node != of){\r
24089             of.renderIndent(true, true);\r
24090         }\r
24091         if(this.rendered){\r
24092             this.renderIndent(true, true);\r
24093         }\r
24094     },\r
24095 \r
24096     // private override\r
24097     setLastChild : function(node){\r
24098         var ol = this.lastChild;\r
24099         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);\r
24100         if(this.childrenRendered && ol && node != ol){\r
24101             ol.renderIndent(true, true);\r
24102         }\r
24103         if(this.rendered){\r
24104             this.renderIndent(true, true);\r
24105         }\r
24106     },\r
24107 \r
24108     // these methods are overridden to provide lazy rendering support\r
24109     // private override\r
24110     appendChild : function(n){\r
24111         if(!n.render && !Ext.isArray(n)){\r
24112             n = this.getLoader().createNode(n);\r
24113         }\r
24114         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);\r
24115         if(node && this.childrenRendered){\r
24116             node.render();\r
24117         }\r
24118         this.ui.updateExpandIcon();\r
24119         return node;\r
24120     },\r
24121 \r
24122     // private override\r
24123     removeChild : function(node){\r
24124         this.ownerTree.getSelectionModel().unselect(node);\r
24125         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);\r
24126         // if it's been rendered remove dom node\r
24127         if(this.childrenRendered){\r
24128             node.ui.remove();\r
24129         }\r
24130         if(this.childNodes.length < 1){\r
24131             this.collapse(false, false);\r
24132         }else{\r
24133             this.ui.updateExpandIcon();\r
24134         }\r
24135         if(!this.firstChild && !this.isHiddenRoot()) {\r
24136             this.childrenRendered = false;\r
24137         }\r
24138         return node;\r
24139     },\r
24140 \r
24141     // private override\r
24142     insertBefore : function(node, refNode){\r
24143         if(!node.render){ \r
24144             node = this.getLoader().createNode(node);\r
24145         }\r
24146         var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);\r
24147         if(newNode && refNode && this.childrenRendered){\r
24148             node.render();\r
24149         }\r
24150         this.ui.updateExpandIcon();\r
24151         return newNode;\r
24152     },\r
24153 \r
24154     \r
24155     setText : function(text){\r
24156         var oldText = this.text;\r
24157         this.text = text;\r
24158         this.attributes.text = text;\r
24159         if(this.rendered){ // event without subscribing\r
24160             this.ui.onTextChange(this, text, oldText);\r
24161         }\r
24162         this.fireEvent("textchange", this, text, oldText);\r
24163     },\r
24164 \r
24165     \r
24166     select : function(){\r
24167         this.getOwnerTree().getSelectionModel().select(this);\r
24168     },\r
24169 \r
24170     \r
24171     unselect : function(){\r
24172         this.getOwnerTree().getSelectionModel().unselect(this);\r
24173     },\r
24174 \r
24175     \r
24176     isSelected : function(){\r
24177         return this.getOwnerTree().getSelectionModel().isSelected(this);\r
24178     },\r
24179 \r
24180     \r
24181     expand : function(deep, anim, callback){\r
24182         if(!this.expanded){\r
24183             if(this.fireEvent("beforeexpand", this, deep, anim) === false){\r
24184                 return;\r
24185             }\r
24186             if(!this.childrenRendered){\r
24187                 this.renderChildren();\r
24188             }\r
24189             this.expanded = true;\r
24190             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){\r
24191                 this.ui.animExpand(function(){\r
24192                     this.fireEvent("expand", this);\r
24193                     if(typeof callback == "function"){\r
24194                         callback(this);\r
24195                     }\r
24196                     if(deep === true){\r
24197                         this.expandChildNodes(true);\r
24198                     }\r
24199                 }.createDelegate(this));\r
24200                 return;\r
24201             }else{\r
24202                 this.ui.expand();\r
24203                 this.fireEvent("expand", this);\r
24204                 if(typeof callback == "function"){\r
24205                     callback(this);\r
24206                 }\r
24207             }\r
24208         }else{\r
24209            if(typeof callback == "function"){\r
24210                callback(this);\r
24211            }\r
24212         }\r
24213         if(deep === true){\r
24214             this.expandChildNodes(true);\r
24215         }\r
24216     },\r
24217 \r
24218     isHiddenRoot : function(){\r
24219         return this.isRoot && !this.getOwnerTree().rootVisible;\r
24220     },\r
24221 \r
24222     \r
24223     collapse : function(deep, anim){\r
24224         if(this.expanded && !this.isHiddenRoot()){\r
24225             if(this.fireEvent("beforecollapse", this, deep, anim) === false){\r
24226                 return;\r
24227             }\r
24228             this.expanded = false;\r
24229             if((this.getOwnerTree().animate && anim !== false) || anim){\r
24230                 this.ui.animCollapse(function(){\r
24231                     this.fireEvent("collapse", this);\r
24232                     if(deep === true){\r
24233                         this.collapseChildNodes(true);\r
24234                     }\r
24235                 }.createDelegate(this));\r
24236                 return;\r
24237             }else{\r
24238                 this.ui.collapse();\r
24239                 this.fireEvent("collapse", this);\r
24240             }\r
24241         }\r
24242         if(deep === true){\r
24243             var cs = this.childNodes;\r
24244             for(var i = 0, len = cs.length; i < len; i++) {\r
24245                 cs[i].collapse(true, false);\r
24246             }\r
24247         }\r
24248     },\r
24249 \r
24250     // private\r
24251     delayedExpand : function(delay){\r
24252         if(!this.expandProcId){\r
24253             this.expandProcId = this.expand.defer(delay, this);\r
24254         }\r
24255     },\r
24256 \r
24257     // private\r
24258     cancelExpand : function(){\r
24259         if(this.expandProcId){\r
24260             clearTimeout(this.expandProcId);\r
24261         }\r
24262         this.expandProcId = false;\r
24263     },\r
24264 \r
24265     \r
24266     toggle : function(){\r
24267         if(this.expanded){\r
24268             this.collapse();\r
24269         }else{\r
24270             this.expand();\r
24271         }\r
24272     },\r
24273 \r
24274     \r
24275     ensureVisible : function(callback){\r
24276         var tree = this.getOwnerTree();\r
24277         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){\r
24278             var node = tree.getNodeById(this.id);  // Somehow if we don't do this, we lose changes that happened to node in the meantime\r
24279             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);\r
24280             Ext.callback(callback);\r
24281         }.createDelegate(this));\r
24282     },\r
24283 \r
24284     \r
24285     expandChildNodes : function(deep){\r
24286         var cs = this.childNodes;\r
24287         for(var i = 0, len = cs.length; i < len; i++) {\r
24288                 cs[i].expand(deep);\r
24289         }\r
24290     },\r
24291 \r
24292     \r
24293     collapseChildNodes : function(deep){\r
24294         var cs = this.childNodes;\r
24295         for(var i = 0, len = cs.length; i < len; i++) {\r
24296                 cs[i].collapse(deep);\r
24297         }\r
24298     },\r
24299 \r
24300     \r
24301     disable : function(){\r
24302         this.disabled = true;\r
24303         this.unselect();\r
24304         if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
24305             this.ui.onDisableChange(this, true);\r
24306         }\r
24307         this.fireEvent("disabledchange", this, true);\r
24308     },\r
24309 \r
24310     \r
24311     enable : function(){\r
24312         this.disabled = false;\r
24313         if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
24314             this.ui.onDisableChange(this, false);\r
24315         }\r
24316         this.fireEvent("disabledchange", this, false);\r
24317     },\r
24318 \r
24319     // private\r
24320     renderChildren : function(suppressEvent){\r
24321         if(suppressEvent !== false){\r
24322             this.fireEvent("beforechildrenrendered", this);\r
24323         }\r
24324         var cs = this.childNodes;\r
24325         for(var i = 0, len = cs.length; i < len; i++){\r
24326             cs[i].render(true);\r
24327         }\r
24328         this.childrenRendered = true;\r
24329     },\r
24330 \r
24331     // private\r
24332     sort : function(fn, scope){\r
24333         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);\r
24334         if(this.childrenRendered){\r
24335             var cs = this.childNodes;\r
24336             for(var i = 0, len = cs.length; i < len; i++){\r
24337                 cs[i].render(true);\r
24338             }\r
24339         }\r
24340     },\r
24341 \r
24342     // private\r
24343     render : function(bulkRender){\r
24344         this.ui.render(bulkRender);\r
24345         if(!this.rendered){\r
24346             // make sure it is registered\r
24347             this.getOwnerTree().registerNode(this);\r
24348             this.rendered = true;\r
24349             if(this.expanded){\r
24350                 this.expanded = false;\r
24351                 this.expand(false, false);\r
24352             }\r
24353         }\r
24354     },\r
24355 \r
24356     // private\r
24357     renderIndent : function(deep, refresh){\r
24358         if(refresh){\r
24359             this.ui.childIndent = null;\r
24360         }\r
24361         this.ui.renderIndent();\r
24362         if(deep === true && this.childrenRendered){\r
24363             var cs = this.childNodes;\r
24364             for(var i = 0, len = cs.length; i < len; i++){\r
24365                 cs[i].renderIndent(true, refresh);\r
24366             }\r
24367         }\r
24368     },\r
24369 \r
24370     beginUpdate : function(){\r
24371         this.childrenRendered = false;\r
24372     },\r
24373 \r
24374     endUpdate : function(){\r
24375         if(this.expanded && this.rendered){\r
24376             this.renderChildren();\r
24377         }\r
24378     },\r
24379 \r
24380     destroy : function(){\r
24381         if(this.childNodes){\r
24382                 for(var i = 0,l = this.childNodes.length; i < l; i++){\r
24383                     this.childNodes[i].destroy();\r
24384                 }\r
24385             this.childNodes = null;\r
24386         }\r
24387         if(this.ui.destroy){\r
24388             this.ui.destroy();\r
24389         }\r
24390     }\r
24391 });\r
24392 \r
24393 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;\r
24394 \r
24395  Ext.tree.AsyncTreeNode = function(config){\r
24396     this.loaded = config && config.loaded === true;\r
24397     this.loading = false;\r
24398     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);\r
24399     \r
24400     this.addEvents('beforeload', 'load');\r
24401     \r
24402     \r
24403 };\r
24404 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {\r
24405     expand : function(deep, anim, callback){\r
24406         if(this.loading){ // if an async load is already running, waiting til it's done\r
24407             var timer;\r
24408             var f = function(){\r
24409                 if(!this.loading){ // done loading\r
24410                     clearInterval(timer);\r
24411                     this.expand(deep, anim, callback);\r
24412                 }\r
24413             }.createDelegate(this);\r
24414             timer = setInterval(f, 200);\r
24415             return;\r
24416         }\r
24417         if(!this.loaded){\r
24418             if(this.fireEvent("beforeload", this) === false){\r
24419                 return;\r
24420             }\r
24421             this.loading = true;\r
24422             this.ui.beforeLoad(this);\r
24423             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();\r
24424             if(loader){\r
24425                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));\r
24426                 return;\r
24427             }\r
24428         }\r
24429         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);\r
24430     },\r
24431     \r
24432     \r
24433     isLoading : function(){\r
24434         return this.loading;  \r
24435     },\r
24436     \r
24437     loadComplete : function(deep, anim, callback){\r
24438         this.loading = false;\r
24439         this.loaded = true;\r
24440         this.ui.afterLoad(this);\r
24441         this.fireEvent("load", this);\r
24442         this.expand(deep, anim, callback);\r
24443     },\r
24444     \r
24445     \r
24446     isLoaded : function(){\r
24447         return this.loaded;\r
24448     },\r
24449     \r
24450     hasChildNodes : function(){\r
24451         if(!this.isLeaf() && !this.loaded){\r
24452             return true;\r
24453         }else{\r
24454             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);\r
24455         }\r
24456     },\r
24457 \r
24458     \r
24459     reload : function(callback){\r
24460         this.collapse(false, false);\r
24461         while(this.firstChild){\r
24462             this.removeChild(this.firstChild).destroy();\r
24463         }\r
24464         this.childrenRendered = false;\r
24465         this.loaded = false;\r
24466         if(this.isHiddenRoot()){\r
24467             this.expanded = false;\r
24468         }\r
24469         this.expand(false, false, callback);\r
24470     }\r
24471 });\r
24472 \r
24473 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;\r
24474 \r
24475 Ext.tree.TreeNodeUI = function(node){\r
24476     this.node = node;\r
24477     this.rendered = false;\r
24478     this.animating = false;\r
24479     this.wasLeaf = true;\r
24480     this.ecc = 'x-tree-ec-icon x-tree-elbow';\r
24481     this.emptyIcon = Ext.BLANK_IMAGE_URL;\r
24482 };\r
24483 \r
24484 Ext.tree.TreeNodeUI.prototype = {\r
24485     // private\r
24486     removeChild : function(node){\r
24487         if(this.rendered){\r
24488             this.ctNode.removeChild(node.ui.getEl());\r
24489         } \r
24490     },\r
24491 \r
24492     // private\r
24493     beforeLoad : function(){\r
24494          this.addClass("x-tree-node-loading");\r
24495     },\r
24496 \r
24497     // private\r
24498     afterLoad : function(){\r
24499          this.removeClass("x-tree-node-loading");\r
24500     },\r
24501 \r
24502     // private\r
24503     onTextChange : function(node, text, oldText){\r
24504         if(this.rendered){\r
24505             this.textNode.innerHTML = text;\r
24506         }\r
24507     },\r
24508 \r
24509     // private\r
24510     onDisableChange : function(node, state){\r
24511         this.disabled = state;\r
24512                 if (this.checkbox) {\r
24513                         this.checkbox.disabled = state;\r
24514                 }        \r
24515         if(state){\r
24516             this.addClass("x-tree-node-disabled");\r
24517         }else{\r
24518             this.removeClass("x-tree-node-disabled");\r
24519         } \r
24520     },\r
24521 \r
24522     // private\r
24523     onSelectedChange : function(state){\r
24524         if(state){\r
24525             this.focus();\r
24526             this.addClass("x-tree-selected");\r
24527         }else{\r
24528             //this.blur();\r
24529             this.removeClass("x-tree-selected");\r
24530         }\r
24531     },\r
24532 \r
24533     // private\r
24534     onMove : function(tree, node, oldParent, newParent, index, refNode){\r
24535         this.childIndent = null;\r
24536         if(this.rendered){\r
24537             var targetNode = newParent.ui.getContainer();\r
24538             if(!targetNode){//target not rendered\r
24539                 this.holder = document.createElement("div");\r
24540                 this.holder.appendChild(this.wrap);\r
24541                 return;\r
24542             }\r
24543             var insertBefore = refNode ? refNode.ui.getEl() : null;\r
24544             if(insertBefore){\r
24545                 targetNode.insertBefore(this.wrap, insertBefore);\r
24546             }else{\r
24547                 targetNode.appendChild(this.wrap);\r
24548             }\r
24549             this.node.renderIndent(true);\r
24550         }\r
24551     },\r
24552 \r
24553 \r
24554     addClass : function(cls){\r
24555         if(this.elNode){\r
24556             Ext.fly(this.elNode).addClass(cls);\r
24557         }\r
24558     },\r
24559 \r
24560 \r
24561     removeClass : function(cls){\r
24562         if(this.elNode){\r
24563             Ext.fly(this.elNode).removeClass(cls);  \r
24564         }\r
24565     },\r
24566 \r
24567     // private\r
24568     remove : function(){\r
24569         if(this.rendered){\r
24570             this.holder = document.createElement("div");\r
24571             this.holder.appendChild(this.wrap);\r
24572         }  \r
24573     },\r
24574 \r
24575     // private\r
24576     fireEvent : function(){\r
24577         return this.node.fireEvent.apply(this.node, arguments);  \r
24578     },\r
24579 \r
24580     // private\r
24581     initEvents : function(){\r
24582         this.node.on("move", this.onMove, this);\r
24583 \r
24584         if(this.node.disabled){\r
24585             this.addClass("x-tree-node-disabled");\r
24586                         if (this.checkbox) {\r
24587                                 this.checkbox.disabled = true;\r
24588                         }            \r
24589         }\r
24590         if(this.node.hidden){\r
24591             this.hide();\r
24592         }\r
24593         var ot = this.node.getOwnerTree();\r
24594         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;\r
24595         if(dd && (!this.node.isRoot || ot.rootVisible)){\r
24596             Ext.dd.Registry.register(this.elNode, {\r
24597                 node: this.node,\r
24598                 handles: this.getDDHandles(),\r
24599                 isHandle: false\r
24600             });\r
24601         }\r
24602     },\r
24603 \r
24604     // private\r
24605     getDDHandles : function(){\r
24606         return [this.iconNode, this.textNode, this.elNode];\r
24607     },\r
24608 \r
24609 \r
24610     hide : function(){\r
24611         this.node.hidden = true;\r
24612         if(this.wrap){\r
24613             this.wrap.style.display = "none";\r
24614         }\r
24615     },\r
24616 \r
24617 \r
24618     show : function(){\r
24619         this.node.hidden = false;\r
24620         if(this.wrap){\r
24621             this.wrap.style.display = "";\r
24622         } \r
24623     },\r
24624 \r
24625     // private\r
24626     onContextMenu : function(e){\r
24627         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {\r
24628             e.preventDefault();\r
24629             this.focus();\r
24630             this.fireEvent("contextmenu", this.node, e);\r
24631         }\r
24632     },\r
24633 \r
24634     // private\r
24635     onClick : function(e){\r
24636         if(this.dropping){\r
24637             e.stopEvent();\r
24638             return;\r
24639         }\r
24640         if(this.fireEvent("beforeclick", this.node, e) !== false){\r
24641             var a = e.getTarget('a');\r
24642             if(!this.disabled && this.node.attributes.href && a){\r
24643                 this.fireEvent("click", this.node, e);\r
24644                 return;\r
24645             }else if(a && e.ctrlKey){\r
24646                 e.stopEvent();\r
24647             }\r
24648             e.preventDefault();\r
24649             if(this.disabled){\r
24650                 return;\r
24651             }\r
24652 \r
24653             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){\r
24654                 this.node.toggle();\r
24655             }\r
24656 \r
24657             this.fireEvent("click", this.node, e);\r
24658         }else{\r
24659             e.stopEvent();\r
24660         }\r
24661     },\r
24662 \r
24663     // private\r
24664     onDblClick : function(e){\r
24665         e.preventDefault();\r
24666         if(this.disabled){\r
24667             return;\r
24668         }\r
24669         if(this.checkbox){\r
24670             this.toggleCheck();\r
24671         }\r
24672         if(!this.animating && this.node.isExpandable()){\r
24673             this.node.toggle();\r
24674         }\r
24675         this.fireEvent("dblclick", this.node, e);\r
24676     },\r
24677 \r
24678     onOver : function(e){\r
24679         this.addClass('x-tree-node-over');\r
24680     },\r
24681 \r
24682     onOut : function(e){\r
24683         this.removeClass('x-tree-node-over');\r
24684     },\r
24685 \r
24686     // private\r
24687     onCheckChange : function(){\r
24688         var checked = this.checkbox.checked;\r
24689                 // fix for IE6\r
24690                 this.checkbox.defaultChecked = checked;\r
24691         this.node.attributes.checked = checked;\r
24692         this.fireEvent('checkchange', this.node, checked);\r
24693     },\r
24694 \r
24695     // private\r
24696     ecClick : function(e){\r
24697         if(!this.animating && this.node.isExpandable()){\r
24698             this.node.toggle();\r
24699         }\r
24700     },\r
24701 \r
24702     // private\r
24703     startDrop : function(){\r
24704         this.dropping = true;\r
24705     },\r
24706     \r
24707     // delayed drop so the click event doesn't get fired on a drop\r
24708     endDrop : function(){ \r
24709        setTimeout(function(){\r
24710            this.dropping = false;\r
24711        }.createDelegate(this), 50); \r
24712     },\r
24713 \r
24714     // private\r
24715     expand : function(){\r
24716         this.updateExpandIcon();\r
24717         this.ctNode.style.display = "";\r
24718     },\r
24719 \r
24720     // private\r
24721     focus : function(){\r
24722         if(!this.node.preventHScroll){\r
24723             try{this.anchor.focus();\r
24724             }catch(e){}\r
24725         }else{\r
24726             try{\r
24727                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;\r
24728                 var l = noscroll.scrollLeft;\r
24729                 this.anchor.focus();\r
24730                 noscroll.scrollLeft = l;\r
24731             }catch(e){}\r
24732         }\r
24733     },\r
24734 \r
24735 \r
24736     toggleCheck : function(value){\r
24737         var cb = this.checkbox;\r
24738         if(cb){\r
24739             cb.checked = (value === undefined ? !cb.checked : value);\r
24740             this.onCheckChange();\r
24741         }\r
24742     },\r
24743 \r
24744     // private\r
24745     blur : function(){\r
24746         try{\r
24747             this.anchor.blur();\r
24748         }catch(e){} \r
24749     },\r
24750 \r
24751     // private\r
24752     animExpand : function(callback){\r
24753         var ct = Ext.get(this.ctNode);\r
24754         ct.stopFx();\r
24755         if(!this.node.isExpandable()){\r
24756             this.updateExpandIcon();\r
24757             this.ctNode.style.display = "";\r
24758             Ext.callback(callback);\r
24759             return;\r
24760         }\r
24761         this.animating = true;\r
24762         this.updateExpandIcon();\r
24763         \r
24764         ct.slideIn('t', {\r
24765            callback : function(){\r
24766                this.animating = false;\r
24767                Ext.callback(callback);\r
24768             },\r
24769             scope: this,\r
24770             duration: this.node.ownerTree.duration || .25\r
24771         });\r
24772     },\r
24773 \r
24774     // private\r
24775     highlight : function(){\r
24776         var tree = this.node.getOwnerTree();\r
24777         Ext.fly(this.wrap).highlight(\r
24778             tree.hlColor || "C3DAF9",\r
24779             {endColor: tree.hlBaseColor}\r
24780         );\r
24781     },\r
24782 \r
24783     // private\r
24784     collapse : function(){\r
24785         this.updateExpandIcon();\r
24786         this.ctNode.style.display = "none";\r
24787     },\r
24788 \r
24789     // private\r
24790     animCollapse : function(callback){\r
24791         var ct = Ext.get(this.ctNode);\r
24792         ct.enableDisplayMode('block');\r
24793         ct.stopFx();\r
24794 \r
24795         this.animating = true;\r
24796         this.updateExpandIcon();\r
24797 \r
24798         ct.slideOut('t', {\r
24799             callback : function(){\r
24800                this.animating = false;\r
24801                Ext.callback(callback);\r
24802             },\r
24803             scope: this,\r
24804             duration: this.node.ownerTree.duration || .25\r
24805         });\r
24806     },\r
24807 \r
24808     // private\r
24809     getContainer : function(){\r
24810         return this.ctNode;  \r
24811     },\r
24812 \r
24813     // private\r
24814     getEl : function(){\r
24815         return this.wrap;  \r
24816     },\r
24817 \r
24818     // private\r
24819     appendDDGhost : function(ghostNode){\r
24820         ghostNode.appendChild(this.elNode.cloneNode(true));\r
24821     },\r
24822 \r
24823     // private\r
24824     getDDRepairXY : function(){\r
24825         return Ext.lib.Dom.getXY(this.iconNode);\r
24826     },\r
24827 \r
24828     // private\r
24829     onRender : function(){\r
24830         this.render();    \r
24831     },\r
24832 \r
24833     // private\r
24834     render : function(bulkRender){\r
24835         var n = this.node, a = n.attributes;\r
24836         var targetNode = n.parentNode ? \r
24837               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;\r
24838         \r
24839         if(!this.rendered){\r
24840             this.rendered = true;\r
24841 \r
24842             this.renderElements(n, a, targetNode, bulkRender);\r
24843 \r
24844             if(a.qtip){\r
24845                if(this.textNode.setAttributeNS){\r
24846                    this.textNode.setAttributeNS("ext", "qtip", a.qtip);\r
24847                    if(a.qtipTitle){\r
24848                        this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);\r
24849                    }\r
24850                }else{\r
24851                    this.textNode.setAttribute("ext:qtip", a.qtip);\r
24852                    if(a.qtipTitle){\r
24853                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);\r
24854                    }\r
24855                } \r
24856             }else if(a.qtipCfg){\r
24857                 a.qtipCfg.target = Ext.id(this.textNode);\r
24858                 Ext.QuickTips.register(a.qtipCfg);\r
24859             }\r
24860             this.initEvents();\r
24861             if(!this.node.expanded){\r
24862                 this.updateExpandIcon(true);\r
24863             }\r
24864         }else{\r
24865             if(bulkRender === true) {\r
24866                 targetNode.appendChild(this.wrap);\r
24867             }\r
24868         }\r
24869     },\r
24870 \r
24871     // private\r
24872     renderElements : function(n, a, targetNode, bulkRender){\r
24873         // add some indent caching, this helps performance when rendering a large tree\r
24874         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';\r
24875 \r
24876         var cb = typeof a.checked == 'boolean';\r
24877 \r
24878         var href = a.href ? a.href : Ext.isGecko ? "" : "#";\r
24879         var 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">',\r
24880             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",\r
24881             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',\r
24882             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',\r
24883             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',\r
24884             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',\r
24885              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",\r
24886             '<ul class="x-tree-node-ct" style="display:none;"></ul>',\r
24887             "</li>"].join('');\r
24888 \r
24889         var nel;\r
24890         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){\r
24891             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);\r
24892         }else{\r
24893             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);\r
24894         }\r
24895         \r
24896         this.elNode = this.wrap.childNodes[0];\r
24897         this.ctNode = this.wrap.childNodes[1];\r
24898         var cs = this.elNode.childNodes;\r
24899         this.indentNode = cs[0];\r
24900         this.ecNode = cs[1];\r
24901         this.iconNode = cs[2];\r
24902         var index = 3;\r
24903         if(cb){\r
24904             this.checkbox = cs[3];\r
24905                         // fix for IE6\r
24906                         this.checkbox.defaultChecked = this.checkbox.checked;                   \r
24907             index++;\r
24908         }\r
24909         this.anchor = cs[index];\r
24910         this.textNode = cs[index].firstChild;\r
24911     },\r
24912 \r
24913 \r
24914     getAnchor : function(){\r
24915         return this.anchor;\r
24916     },\r
24917     \r
24918 \r
24919     getTextEl : function(){\r
24920         return this.textNode;\r
24921     },\r
24922     \r
24923 \r
24924     getIconEl : function(){\r
24925         return this.iconNode;\r
24926     },\r
24927 \r
24928 \r
24929     isChecked : function(){\r
24930         return this.checkbox ? this.checkbox.checked : false; \r
24931     },\r
24932 \r
24933     // private\r
24934     updateExpandIcon : function(){\r
24935         if(this.rendered){\r
24936             var n = this.node, c1, c2;\r
24937             var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";\r
24938             if(n.isExpandable()){\r
24939                 if(n.expanded){\r
24940                     cls += "-minus";\r
24941                     c1 = "x-tree-node-collapsed";\r
24942                     c2 = "x-tree-node-expanded";\r
24943                 }else{\r
24944                     cls += "-plus";\r
24945                     c1 = "x-tree-node-expanded";\r
24946                     c2 = "x-tree-node-collapsed";\r
24947                 }\r
24948                 if(this.wasLeaf){\r
24949                     this.removeClass("x-tree-node-leaf");\r
24950                     this.wasLeaf = false;\r
24951                 }\r
24952                 if(this.c1 != c1 || this.c2 != c2){\r
24953                     Ext.fly(this.elNode).replaceClass(c1, c2);\r
24954                     this.c1 = c1; this.c2 = c2;\r
24955                 }\r
24956             }else{\r
24957                 if(!this.wasLeaf){\r
24958                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");\r
24959                     delete this.c1;\r
24960                     delete this.c2;\r
24961                     this.wasLeaf = true;\r
24962                 }\r
24963             }\r
24964             var ecc = "x-tree-ec-icon "+cls;\r
24965             if(this.ecc != ecc){\r
24966                 this.ecNode.className = ecc;\r
24967                 this.ecc = ecc;\r
24968             }\r
24969         }\r
24970     },\r
24971 \r
24972     // private\r
24973     getChildIndent : function(){\r
24974         if(!this.childIndent){\r
24975             var buf = [];\r
24976             var p = this.node;\r
24977             while(p){\r
24978                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){\r
24979                     if(!p.isLast()) {\r
24980                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');\r
24981                     } else {\r
24982                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');\r
24983                     }\r
24984                 }\r
24985                 p = p.parentNode;\r
24986             }\r
24987             this.childIndent = buf.join("");\r
24988         }\r
24989         return this.childIndent;\r
24990     },\r
24991 \r
24992     // private\r
24993     renderIndent : function(){\r
24994         if(this.rendered){\r
24995             var indent = "";\r
24996             var p = this.node.parentNode;\r
24997             if(p){\r
24998                 indent = p.ui.getChildIndent();\r
24999             }\r
25000             if(this.indentMarkup != indent){ // don't rerender if not required\r
25001                 this.indentNode.innerHTML = indent;\r
25002                 this.indentMarkup = indent;\r
25003             }\r
25004             this.updateExpandIcon();\r
25005         }\r
25006     },\r
25007 \r
25008     destroy : function(){\r
25009         if(this.elNode){\r
25010             Ext.dd.Registry.unregister(this.elNode.id);\r
25011         }\r
25012         delete this.elNode;\r
25013         delete this.ctNode;\r
25014         delete this.indentNode;\r
25015         delete this.ecNode;\r
25016         delete this.iconNode;\r
25017         delete this.checkbox;\r
25018         delete this.anchor;\r
25019         delete this.textNode;\r
25020         \r
25021         if (this.holder){\r
25022              delete this.wrap;\r
25023              Ext.removeNode(this.holder);\r
25024              delete this.holder;\r
25025         }else{\r
25026             Ext.removeNode(this.wrap);\r
25027             delete this.wrap;\r
25028         }\r
25029     }\r
25030 };\r
25031 \r
25032 \r
25033 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {\r
25034     // private\r
25035     render : function(){\r
25036         if(!this.rendered){\r
25037             var targetNode = this.node.ownerTree.innerCt.dom;\r
25038             this.node.expanded = true;\r
25039             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';\r
25040             this.wrap = this.ctNode = targetNode.firstChild;\r
25041         }\r
25042     },\r
25043     collapse : Ext.emptyFn,\r
25044     expand : Ext.emptyFn\r
25045 });\r
25046 \r
25047 Ext.tree.TreeLoader = function(config){\r
25048     this.baseParams = {};\r
25049     Ext.apply(this, config);\r
25050 \r
25051     this.addEvents(\r
25052         \r
25053         "beforeload",\r
25054         \r
25055         "load",\r
25056         \r
25057         "loadexception"\r
25058     );\r
25059 \r
25060     Ext.tree.TreeLoader.superclass.constructor.call(this);\r
25061 };\r
25062 \r
25063 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {\r
25064     \r
25065     \r
25066     \r
25067     \r
25068     \r
25069     \r
25070     \r
25071     uiProviders : {},\r
25072 \r
25073     \r
25074     clearOnLoad : true,\r
25075 \r
25076     \r
25077     load : function(node, callback){\r
25078         if(this.clearOnLoad){\r
25079             while(node.firstChild){\r
25080                 node.removeChild(node.firstChild);\r
25081             }\r
25082         }\r
25083         if(this.doPreload(node)){ // preloaded json children\r
25084             if(typeof callback == "function"){\r
25085                 callback();\r
25086             }\r
25087         }else if(this.dataUrl||this.url){\r
25088             this.requestData(node, callback);\r
25089         }\r
25090     },\r
25091 \r
25092     doPreload : function(node){\r
25093         if(node.attributes.children){\r
25094             if(node.childNodes.length < 1){ // preloaded?\r
25095                 var cs = node.attributes.children;\r
25096                 node.beginUpdate();\r
25097                 for(var i = 0, len = cs.length; i < len; i++){\r
25098                     var cn = node.appendChild(this.createNode(cs[i]));\r
25099                     if(this.preloadChildren){\r
25100                         this.doPreload(cn);\r
25101                     }\r
25102                 }\r
25103                 node.endUpdate();\r
25104             }\r
25105             return true;\r
25106         }else {\r
25107             return false;\r
25108         }\r
25109     },\r
25110 \r
25111     getParams: function(node){\r
25112         var buf = [], bp = this.baseParams;\r
25113         for(var key in bp){\r
25114             if(typeof bp[key] != "function"){\r
25115                 buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");\r
25116             }\r
25117         }\r
25118         buf.push("node=", encodeURIComponent(node.id));\r
25119         return buf.join("");\r
25120     },\r
25121 \r
25122     requestData : function(node, callback){\r
25123         if(this.fireEvent("beforeload", this, node, callback) !== false){\r
25124             this.transId = Ext.Ajax.request({\r
25125                 method:this.requestMethod,\r
25126                 url: this.dataUrl||this.url,\r
25127                 success: this.handleResponse,\r
25128                 failure: this.handleFailure,\r
25129                 scope: this,\r
25130                 argument: {callback: callback, node: node},\r
25131                 params: this.getParams(node)\r
25132             });\r
25133         }else{\r
25134             // if the load is cancelled, make sure we notify\r
25135             // the node that we are done\r
25136             if(typeof callback == "function"){\r
25137                 callback();\r
25138             }\r
25139         }\r
25140     },\r
25141 \r
25142     isLoading : function(){\r
25143         return !!this.transId;\r
25144     },\r
25145 \r
25146     abort : function(){\r
25147         if(this.isLoading()){\r
25148             Ext.Ajax.abort(this.transId);\r
25149         }\r
25150     },\r
25151 \r
25152     \r
25153     createNode : function(attr){\r
25154         // apply baseAttrs, nice idea Corey!\r
25155         if(this.baseAttrs){\r
25156             Ext.applyIf(attr, this.baseAttrs);\r
25157         }\r
25158         if(this.applyLoader !== false){\r
25159             attr.loader = this;\r
25160         }\r
25161         if(typeof attr.uiProvider == 'string'){\r
25162            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);\r
25163         }\r
25164         if(attr.nodeType){\r
25165             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);\r
25166         }else{\r
25167             return attr.leaf ?\r
25168                         new Ext.tree.TreeNode(attr) :\r
25169                         new Ext.tree.AsyncTreeNode(attr);\r
25170         }\r
25171     },\r
25172 \r
25173     processResponse : function(response, node, callback){\r
25174         var json = response.responseText;\r
25175         try {\r
25176             var o = eval("("+json+")");\r
25177             node.beginUpdate();\r
25178             for(var i = 0, len = o.length; i < len; i++){\r
25179                 var n = this.createNode(o[i]);\r
25180                 if(n){\r
25181                     node.appendChild(n);\r
25182                 }\r
25183             }\r
25184             node.endUpdate();\r
25185             if(typeof callback == "function"){\r
25186                 callback(this, node);\r
25187             }\r
25188         }catch(e){\r
25189             this.handleFailure(response);\r
25190         }\r
25191     },\r
25192 \r
25193     handleResponse : function(response){\r
25194         this.transId = false;\r
25195         var a = response.argument;\r
25196         this.processResponse(response, a.node, a.callback);\r
25197         this.fireEvent("load", this, a.node, response);\r
25198     },\r
25199 \r
25200     handleFailure : function(response){\r
25201         this.transId = false;\r
25202         var a = response.argument;\r
25203         this.fireEvent("loadexception", this, a.node, response);\r
25204         if(typeof a.callback == "function"){\r
25205             a.callback(this, a.node);\r
25206         }\r
25207     }\r
25208 });\r
25209 \r
25210 Ext.tree.TreeFilter = function(tree, config){\r
25211     this.tree = tree;\r
25212     this.filtered = {};\r
25213     Ext.apply(this, config);\r
25214 };\r
25215 \r
25216 Ext.tree.TreeFilter.prototype = {\r
25217     clearBlank:false,\r
25218     reverse:false,\r
25219     autoClear:false,\r
25220     remove:false,\r
25221 \r
25222      \r
25223     filter : function(value, attr, startNode){\r
25224         attr = attr || "text";\r
25225         var f;\r
25226         if(typeof value == "string"){\r
25227             var vlen = value.length;\r
25228             // auto clear empty filter\r
25229             if(vlen == 0 && this.clearBlank){\r
25230                 this.clear();\r
25231                 return;\r
25232             }\r
25233             value = value.toLowerCase();\r
25234             f = function(n){\r
25235                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;\r
25236             };\r
25237         }else if(value.exec){ // regex?\r
25238             f = function(n){\r
25239                 return value.test(n.attributes[attr]);\r
25240             };\r
25241         }else{\r
25242             throw 'Illegal filter type, must be string or regex';\r
25243         }\r
25244         this.filterBy(f, null, startNode);\r
25245         },\r
25246     \r
25247     \r
25248     filterBy : function(fn, scope, startNode){\r
25249         startNode = startNode || this.tree.root;\r
25250         if(this.autoClear){\r
25251             this.clear();\r
25252         }\r
25253         var af = this.filtered, rv = this.reverse;\r
25254         var f = function(n){\r
25255             if(n == startNode){\r
25256                 return true;\r
25257             }\r
25258             if(af[n.id]){\r
25259                 return false;\r
25260             }\r
25261             var m = fn.call(scope || n, n);\r
25262             if(!m || rv){\r
25263                 af[n.id] = n;\r
25264                 n.ui.hide();\r
25265                 return false;\r
25266             }\r
25267             return true;\r
25268         };\r
25269         startNode.cascade(f);\r
25270         if(this.remove){\r
25271            for(var id in af){\r
25272                if(typeof id != "function"){\r
25273                    var n = af[id];\r
25274                    if(n && n.parentNode){\r
25275                        n.parentNode.removeChild(n);\r
25276                    }\r
25277                }\r
25278            } \r
25279         }\r
25280     },\r
25281     \r
25282     \r
25283     clear : function(){\r
25284         var t = this.tree;\r
25285         var af = this.filtered;\r
25286         for(var id in af){\r
25287             if(typeof id != "function"){\r
25288                 var n = af[id];\r
25289                 if(n){\r
25290                     n.ui.show();\r
25291                 }\r
25292             }\r
25293         }\r
25294         this.filtered = {}; \r
25295     }\r
25296 };\r
25297 \r
25298 \r
25299 Ext.tree.TreeSorter = function(tree, config){\r
25300     \r
25301         \r
25302     \r
25303     \r
25304     \r
25305     \r
25306     \r
25307     Ext.apply(this, config);\r
25308     tree.on("beforechildrenrendered", this.doSort, this);\r
25309     tree.on("append", this.updateSort, this);\r
25310     tree.on("insert", this.updateSort, this);\r
25311     tree.on("textchange", this.updateSortParent, this);\r
25312     \r
25313     var dsc = this.dir && this.dir.toLowerCase() == "desc";\r
25314     var p = this.property || "text";\r
25315     var sortType = this.sortType;\r
25316     var fs = this.folderSort;\r
25317     var cs = this.caseSensitive === true;\r
25318     var leafAttr = this.leafAttr || 'leaf';\r
25319 \r
25320     this.sortFn = function(n1, n2){\r
25321         if(fs){\r
25322             if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){\r
25323                 return 1;\r
25324             }\r
25325             if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){\r
25326                 return -1;\r
25327             }\r
25328         }\r
25329         var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());\r
25330         var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());\r
25331         if(v1 < v2){\r
25332                         return dsc ? +1 : -1;\r
25333                 }else if(v1 > v2){\r
25334                         return dsc ? -1 : +1;\r
25335         }else{\r
25336                 return 0;\r
25337         }\r
25338     };\r
25339 };\r
25340 \r
25341 Ext.tree.TreeSorter.prototype = {\r
25342     doSort : function(node){\r
25343         node.sort(this.sortFn);\r
25344     },\r
25345     \r
25346     compareNodes : function(n1, n2){\r
25347         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);\r
25348     },\r
25349     \r
25350     updateSort : function(tree, node){\r
25351         if(node.childrenRendered){\r
25352             this.doSort.defer(1, this, [node]);\r
25353         }\r
25354     },\r
25355     \r
25356     updateSortParent : function(node){\r
25357                 var p = node.parentNode;\r
25358                 if(p && p.childrenRendered){\r
25359             this.doSort.defer(1, this, [p]);\r
25360         }\r
25361     }\r
25362 };\r
25363 \r
25364 if(Ext.dd.DropZone){\r
25365     \r
25366 Ext.tree.TreeDropZone = function(tree, config){\r
25367     \r
25368     this.allowParentInsert = false;\r
25369     \r
25370     this.allowContainerDrop = false;\r
25371     \r
25372     this.appendOnly = false;\r
25373     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);\r
25374     \r
25375     this.tree = tree;\r
25376     \r
25377     this.dragOverData = {};\r
25378     // private\r
25379     this.lastInsertClass = "x-tree-no-status";\r
25380 };\r
25381 \r
25382 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {\r
25383     \r
25384     ddGroup : "TreeDD",\r
25385 \r
25386     \r
25387     expandDelay : 1000,\r
25388 \r
25389     // private\r
25390     expandNode : function(node){\r
25391         if(node.hasChildNodes() && !node.isExpanded()){\r
25392             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));\r
25393         }\r
25394     },\r
25395 \r
25396     // private\r
25397     queueExpand : function(node){\r
25398         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);\r
25399     },\r
25400 \r
25401     // private\r
25402     cancelExpand : function(){\r
25403         if(this.expandProcId){\r
25404             clearTimeout(this.expandProcId);\r
25405             this.expandProcId = false;\r
25406         }\r
25407     },\r
25408 \r
25409     // private\r
25410     isValidDropPoint : function(n, pt, dd, e, data){\r
25411         if(!n || !data){ return false; }\r
25412         var targetNode = n.node;\r
25413         var dropNode = data.node;\r
25414         // default drop rules\r
25415         if(!(targetNode && targetNode.isTarget && pt)){\r
25416             return false;\r
25417         }\r
25418         if(pt == "append" && targetNode.allowChildren === false){\r
25419             return false;\r
25420         }\r
25421         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){\r
25422             return false;\r
25423         }\r
25424         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){\r
25425             return false;\r
25426         }\r
25427         // reuse the object\r
25428         var overEvent = this.dragOverData;\r
25429         overEvent.tree = this.tree;\r
25430         overEvent.target = targetNode;\r
25431         overEvent.data = data;\r
25432         overEvent.point = pt;\r
25433         overEvent.source = dd;\r
25434         overEvent.rawEvent = e;\r
25435         overEvent.dropNode = dropNode;\r
25436         overEvent.cancel = false;  \r
25437         var result = this.tree.fireEvent("nodedragover", overEvent);\r
25438         return overEvent.cancel === false && result !== false;\r
25439     },\r
25440 \r
25441     // private\r
25442     getDropPoint : function(e, n, dd){\r
25443         var tn = n.node;\r
25444         if(tn.isRoot){\r
25445             return tn.allowChildren !== false ? "append" : false; // always append for root\r
25446         }\r
25447         var dragEl = n.ddel;\r
25448         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;\r
25449         var y = Ext.lib.Event.getPageY(e);\r
25450         var noAppend = tn.allowChildren === false || tn.isLeaf();\r
25451         if(this.appendOnly || tn.parentNode.allowChildren === false){\r
25452             return noAppend ? false : "append";\r
25453         }\r
25454         var noBelow = false;\r
25455         if(!this.allowParentInsert){\r
25456             noBelow = tn.hasChildNodes() && tn.isExpanded();\r
25457         }\r
25458         var q = (b - t) / (noAppend ? 2 : 3);\r
25459         if(y >= t && y < (t + q)){\r
25460             return "above";\r
25461         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){\r
25462             return "below";\r
25463         }else{\r
25464             return "append";\r
25465         }\r
25466     },\r
25467 \r
25468     // private\r
25469     onNodeEnter : function(n, dd, e, data){\r
25470         this.cancelExpand();\r
25471     },\r
25472 \r
25473     // private\r
25474     onNodeOver : function(n, dd, e, data){\r
25475         var pt = this.getDropPoint(e, n, dd);\r
25476         var node = n.node;\r
25477         \r
25478         // auto node expand check\r
25479         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){\r
25480             this.queueExpand(node);\r
25481         }else if(pt != "append"){\r
25482             this.cancelExpand();\r
25483         }\r
25484         \r
25485         // set the insert point style on the target node\r
25486         var returnCls = this.dropNotAllowed;\r
25487         if(this.isValidDropPoint(n, pt, dd, e, data)){\r
25488            if(pt){\r
25489                var el = n.ddel;\r
25490                var cls;\r
25491                if(pt == "above"){\r
25492                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";\r
25493                    cls = "x-tree-drag-insert-above";\r
25494                }else if(pt == "below"){\r
25495                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";\r
25496                    cls = "x-tree-drag-insert-below";\r
25497                }else{\r
25498                    returnCls = "x-tree-drop-ok-append";\r
25499                    cls = "x-tree-drag-append";\r
25500                }\r
25501                if(this.lastInsertClass != cls){\r
25502                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);\r
25503                    this.lastInsertClass = cls;\r
25504                }\r
25505            }\r
25506        }\r
25507        return returnCls;\r
25508     },\r
25509 \r
25510     // private\r
25511     onNodeOut : function(n, dd, e, data){\r
25512         this.cancelExpand();\r
25513         this.removeDropIndicators(n);\r
25514     },\r
25515 \r
25516     // private\r
25517     onNodeDrop : function(n, dd, e, data){\r
25518         var point = this.getDropPoint(e, n, dd);\r
25519         var targetNode = n.node;\r
25520         targetNode.ui.startDrop();\r
25521         if(!this.isValidDropPoint(n, point, dd, e, data)){\r
25522             targetNode.ui.endDrop();\r
25523             return false;\r
25524         }\r
25525         // first try to find the drop node\r
25526         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);\r
25527         var dropEvent = {\r
25528             tree : this.tree,\r
25529             target: targetNode,\r
25530             data: data,\r
25531             point: point,\r
25532             source: dd,\r
25533             rawEvent: e,\r
25534             dropNode: dropNode,\r
25535             cancel: !dropNode,\r
25536             dropStatus: false\r
25537         };\r
25538         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);\r
25539         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){\r
25540             targetNode.ui.endDrop();\r
25541             return dropEvent.dropStatus;\r
25542         }\r
25543         // allow target changing\r
25544         targetNode = dropEvent.target;\r
25545         if(point == "append" && !targetNode.isExpanded()){\r
25546             targetNode.expand(false, null, function(){\r
25547                 this.completeDrop(dropEvent);\r
25548             }.createDelegate(this));\r
25549         }else{\r
25550             this.completeDrop(dropEvent);\r
25551         }\r
25552         return true;\r
25553     },\r
25554 \r
25555     // private\r
25556     completeDrop : function(de){\r
25557         var ns = de.dropNode, p = de.point, t = de.target;\r
25558         if(!Ext.isArray(ns)){\r
25559             ns = [ns];\r
25560         }\r
25561         var n;\r
25562         for(var i = 0, len = ns.length; i < len; i++){\r
25563             n = ns[i];\r
25564             if(p == "above"){\r
25565                 t.parentNode.insertBefore(n, t);\r
25566             }else if(p == "below"){\r
25567                 t.parentNode.insertBefore(n, t.nextSibling);\r
25568             }else{\r
25569                 t.appendChild(n);\r
25570             }\r
25571         }\r
25572         n.ui.focus();\r
25573         if(Ext.enableFx && this.tree.hlDrop){\r
25574             n.ui.highlight();\r
25575         }\r
25576         t.ui.endDrop();\r
25577         this.tree.fireEvent("nodedrop", de);\r
25578     },\r
25579 \r
25580     // private\r
25581     afterNodeMoved : function(dd, data, e, targetNode, dropNode){\r
25582         if(Ext.enableFx && this.tree.hlDrop){\r
25583             dropNode.ui.focus();\r
25584             dropNode.ui.highlight();\r
25585         }\r
25586         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);\r
25587     },\r
25588 \r
25589     // private\r
25590     getTree : function(){\r
25591         return this.tree;\r
25592     },\r
25593 \r
25594     // private\r
25595     removeDropIndicators : function(n){\r
25596         if(n && n.ddel){\r
25597             var el = n.ddel;\r
25598             Ext.fly(el).removeClass([\r
25599                     "x-tree-drag-insert-above",\r
25600                     "x-tree-drag-insert-below",\r
25601                     "x-tree-drag-append"]);\r
25602             this.lastInsertClass = "_noclass";\r
25603         }\r
25604     },\r
25605 \r
25606     // private\r
25607     beforeDragDrop : function(target, e, id){\r
25608         this.cancelExpand();\r
25609         return true;\r
25610     },\r
25611 \r
25612     // private\r
25613     afterRepair : function(data){\r
25614         if(data && Ext.enableFx){\r
25615             data.node.ui.highlight();\r
25616         }\r
25617         this.hideProxy();\r
25618     }    \r
25619 });\r
25620 \r
25621 }\r
25622 \r
25623 if(Ext.dd.DragZone){\r
25624 Ext.tree.TreeDragZone = function(tree, config){\r
25625     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getTreeEl(), config);\r
25626     \r
25627     this.tree = tree;\r
25628 };\r
25629 \r
25630 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {\r
25631     \r
25632     ddGroup : "TreeDD",\r
25633 \r
25634     // private\r
25635     onBeforeDrag : function(data, e){\r
25636         var n = data.node;\r
25637         return n && n.draggable && !n.disabled;\r
25638     },\r
25639 \r
25640     // private\r
25641     onInitDrag : function(e){\r
25642         var data = this.dragData;\r
25643         this.tree.getSelectionModel().select(data.node);\r
25644         this.tree.eventModel.disable();\r
25645         this.proxy.update("");\r
25646         data.node.ui.appendDDGhost(this.proxy.ghost.dom);\r
25647         this.tree.fireEvent("startdrag", this.tree, data.node, e);\r
25648     },\r
25649 \r
25650     // private\r
25651     getRepairXY : function(e, data){\r
25652         return data.node.ui.getDDRepairXY();\r
25653     },\r
25654 \r
25655     // private\r
25656     onEndDrag : function(data, e){\r
25657         this.tree.eventModel.enable.defer(100, this.tree.eventModel);\r
25658         this.tree.fireEvent("enddrag", this.tree, data.node, e);\r
25659     },\r
25660 \r
25661     // private\r
25662     onValidDrop : function(dd, e, id){\r
25663         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);\r
25664         this.hideProxy();\r
25665     },\r
25666 \r
25667     // private\r
25668     beforeInvalidDrop : function(e, id){\r
25669         // this scrolls the original position back into view\r
25670         var sm = this.tree.getSelectionModel();\r
25671         sm.clearSelections();\r
25672         sm.select(this.dragData.node);\r
25673     },\r
25674     \r
25675     // private\r
25676     afterRepair : function(){\r
25677         if (Ext.enableFx && this.tree.hlDrop) {\r
25678             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");\r
25679         }\r
25680         this.dragging = false;\r
25681     }\r
25682 });\r
25683 }\r
25684 \r
25685 Ext.tree.TreeEditor = function(tree, fc, config){\r
25686     fc = fc || {};\r
25687     var field = fc.events ? fc : new Ext.form.TextField(fc);\r
25688     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);\r
25689 \r
25690     this.tree = tree;\r
25691 \r
25692     if(!tree.rendered){\r
25693         tree.on('render', this.initEditor, this);\r
25694     }else{\r
25695         this.initEditor(tree);\r
25696     }\r
25697 };\r
25698 \r
25699 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {\r
25700     \r
25701     alignment: "l-l",\r
25702     // inherit\r
25703     autoSize: false,\r
25704     \r
25705     hideEl : false,\r
25706     \r
25707     cls: "x-small-editor x-tree-editor",\r
25708     \r
25709     shim:false,\r
25710     // inherit\r
25711     shadow:"frame",\r
25712     \r
25713     maxWidth: 250,\r
25714     \r
25715     editDelay : 350,\r
25716 \r
25717     initEditor : function(tree){\r
25718         tree.on('beforeclick', this.beforeNodeClick, this);\r
25719         tree.on('dblclick', this.onNodeDblClick, this);\r
25720         this.on('complete', this.updateNode, this);\r
25721         this.on('beforestartedit', this.fitToTree, this);\r
25722         this.on('startedit', this.bindScroll, this, {delay:10});\r
25723         this.on('specialkey', this.onSpecialKey, this);\r
25724     },\r
25725 \r
25726     // private\r
25727     fitToTree : function(ed, el){\r
25728         var td = this.tree.getTreeEl().dom, nd = el.dom;\r
25729         if(td.scrollLeft >  nd.offsetLeft){ // ensure the node left point is visible\r
25730             td.scrollLeft = nd.offsetLeft;\r
25731         }\r
25732         var w = Math.min(\r
25733                 this.maxWidth,\r
25734                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);\r
25735         this.setSize(w, '');\r
25736     },\r
25737 \r
25738     // private\r
25739     triggerEdit : function(node, defer){\r
25740         this.completeEdit();\r
25741                 if(node.attributes.editable !== false){\r
25742                \r
25743                         this.editNode = node;\r
25744             if(this.tree.autoScroll){\r
25745                 node.ui.getEl().scrollIntoView(this.tree.body);\r
25746             }\r
25747             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);\r
25748             return false;\r
25749         }\r
25750     },\r
25751 \r
25752     // private\r
25753     bindScroll : function(){\r
25754         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);\r
25755     },\r
25756 \r
25757     // private\r
25758     beforeNodeClick : function(node, e){\r
25759         clearTimeout(this.autoEditTimer);\r
25760         if(this.tree.getSelectionModel().isSelected(node)){\r
25761             e.stopEvent();\r
25762             return this.triggerEdit(node);\r
25763         }\r
25764     },\r
25765 \r
25766     onNodeDblClick : function(node, e){\r
25767         clearTimeout(this.autoEditTimer);\r
25768     },\r
25769 \r
25770     // private\r
25771     updateNode : function(ed, value){\r
25772         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);\r
25773         this.editNode.setText(value);\r
25774     },\r
25775 \r
25776     // private\r
25777     onHide : function(){\r
25778         Ext.tree.TreeEditor.superclass.onHide.call(this);\r
25779         if(this.editNode){\r
25780             this.editNode.ui.focus.defer(50, this.editNode.ui);\r
25781         }\r
25782     },\r
25783 \r
25784     // private\r
25785     onSpecialKey : function(field, e){\r
25786         var k = e.getKey();\r
25787         if(k == e.ESC){\r
25788             e.stopEvent();\r
25789             this.cancelEdit();\r
25790         }else if(k == e.ENTER && !e.hasModifier()){\r
25791             e.stopEvent();\r
25792             this.completeEdit();\r
25793         }\r
25794     }\r
25795 });\r
25796 \r
25797 Ext.menu.Menu = function(config){\r
25798     if(Ext.isArray(config)){\r
25799         config = {items:config};\r
25800     }\r
25801     Ext.apply(this, config);\r
25802     this.id = this.id || Ext.id();\r
25803     this.addEvents(\r
25804         \r
25805         'beforeshow',\r
25806         \r
25807         'beforehide',\r
25808         \r
25809         'show',\r
25810         \r
25811         'hide',\r
25812         \r
25813         'click',\r
25814         \r
25815         'mouseover',\r
25816         \r
25817         'mouseout',\r
25818         \r
25819         'itemclick'\r
25820     );\r
25821     Ext.menu.MenuMgr.register(this);\r
25822     Ext.menu.Menu.superclass.constructor.call(this);\r
25823     var mis = this.items;\r
25824     \r
25825 \r
25826     this.items = new Ext.util.MixedCollection();\r
25827     if(mis){\r
25828         this.add.apply(this, mis);\r
25829     }\r
25830 };\r
25831 \r
25832 Ext.extend(Ext.menu.Menu, Ext.util.Observable, {\r
25833     \r
25834     \r
25835     \r
25836     minWidth : 120,\r
25837     \r
25838     shadow : "sides",\r
25839     \r
25840     subMenuAlign : "tl-tr?",\r
25841     \r
25842     defaultAlign : "tl-bl?",\r
25843     \r
25844     allowOtherMenus : false,\r
25845     \r
25846     ignoreParentClicks : false,\r
25847 \r
25848     // private\r
25849     hidden:true,\r
25850 \r
25851     // private\r
25852     createEl : function(){\r
25853         return new Ext.Layer({\r
25854             cls: "x-menu",\r
25855             shadow:this.shadow,\r
25856             constrain: false,\r
25857             parentEl: this.parentEl || document.body,\r
25858             zindex:15000\r
25859         });\r
25860     },\r
25861 \r
25862     // private\r
25863     render : function(){\r
25864         if(this.el){\r
25865             return;\r
25866         }\r
25867         var el = this.el = this.createEl();\r
25868 \r
25869         if(!this.keyNav){\r
25870             this.keyNav = new Ext.menu.MenuNav(this);\r
25871         }\r
25872         if(this.plain){\r
25873             el.addClass("x-menu-plain");\r
25874         }\r
25875         if(this.cls){\r
25876             el.addClass(this.cls);\r
25877         }\r
25878         // generic focus element\r
25879         this.focusEl = el.createChild({\r
25880             tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"\r
25881         });\r
25882         var ul = el.createChild({tag: "ul", cls: "x-menu-list"});\r
25883         ul.on("click", this.onClick, this);\r
25884         ul.on("mouseover", this.onMouseOver, this);\r
25885         ul.on("mouseout", this.onMouseOut, this);\r
25886         this.items.each(function(item){\r
25887             var li = document.createElement("li");\r
25888             li.className = "x-menu-list-item";\r
25889             ul.dom.appendChild(li);\r
25890             item.render(li, this);\r
25891         }, this);\r
25892         this.ul = ul;\r
25893         this.autoWidth();\r
25894     },\r
25895 \r
25896     // private\r
25897     autoWidth : function(){\r
25898         var el = this.el, ul = this.ul;\r
25899         if(!el){\r
25900             return;\r
25901         }\r
25902         var w = this.width;\r
25903         if(w){\r
25904             el.setWidth(w);\r
25905         }else if(Ext.isIE){\r
25906             el.setWidth(this.minWidth);\r
25907             var t = el.dom.offsetWidth; // force recalc\r
25908             el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));\r
25909         }\r
25910     },\r
25911 \r
25912     // private\r
25913     delayAutoWidth : function(){\r
25914         if(this.el){\r
25915             if(!this.awTask){\r
25916                 this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);\r
25917             }\r
25918             this.awTask.delay(20);\r
25919         }\r
25920     },\r
25921 \r
25922     // private\r
25923     findTargetItem : function(e){\r
25924         var t = e.getTarget(".x-menu-list-item", this.ul,  true);\r
25925         if(t && t.menuItemId){\r
25926             return this.items.get(t.menuItemId);\r
25927         }\r
25928     },\r
25929 \r
25930     // private\r
25931     onClick : function(e){\r
25932         var t;\r
25933         if(t = this.findTargetItem(e)){\r
25934             if(t.menu && this.ignoreParentClicks){\r
25935                 t.expandMenu();\r
25936             }else{\r
25937                 t.onClick(e);\r
25938                 this.fireEvent("click", this, t, e);\r
25939             }\r
25940         }\r
25941     },\r
25942 \r
25943     // private\r
25944     setActiveItem : function(item, autoExpand){\r
25945         if(item != this.activeItem){\r
25946             if(this.activeItem){\r
25947                 this.activeItem.deactivate();\r
25948             }\r
25949             this.activeItem = item;\r
25950             item.activate(autoExpand);\r
25951         }else if(autoExpand){\r
25952             item.expandMenu();\r
25953         }\r
25954     },\r
25955 \r
25956     // private\r
25957     tryActivate : function(start, step){\r
25958         var items = this.items;\r
25959         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){\r
25960             var item = items.get(i);\r
25961             if(!item.disabled && item.canActivate){\r
25962                 this.setActiveItem(item, false);\r
25963                 return item;\r
25964             }\r
25965         }\r
25966         return false;\r
25967     },\r
25968 \r
25969     // private\r
25970     onMouseOver : function(e){\r
25971         var t;\r
25972         if(t = this.findTargetItem(e)){\r
25973             if(t.canActivate && !t.disabled){\r
25974                 this.setActiveItem(t, true);\r
25975             }\r
25976         }\r
25977         this.over = true;\r
25978         this.fireEvent("mouseover", this, e, t);\r
25979     },\r
25980 \r
25981     // private\r
25982     onMouseOut : function(e){\r
25983         var t;\r
25984         if(t = this.findTargetItem(e)){\r
25985             if(t == this.activeItem && t.shouldDeactivate(e)){\r
25986                 this.activeItem.deactivate();\r
25987                 delete this.activeItem;\r
25988             }\r
25989         }\r
25990         this.over = false;\r
25991         this.fireEvent("mouseout", this, e, t);\r
25992     },\r
25993 \r
25994     \r
25995     isVisible : function(){\r
25996         return this.el && !this.hidden;\r
25997     },\r
25998 \r
25999     \r
26000     show : function(el, pos, parentMenu){\r
26001         this.parentMenu = parentMenu;\r
26002         if(!this.el){\r
26003             this.render();\r
26004         }\r
26005         this.fireEvent("beforeshow", this);\r
26006         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);\r
26007     },\r
26008 \r
26009     \r
26010     showAt : function(xy, parentMenu, _e){\r
26011         this.parentMenu = parentMenu;\r
26012         if(!this.el){\r
26013             this.render();\r
26014         }\r
26015         if(_e !== false){\r
26016             this.fireEvent("beforeshow", this);\r
26017             xy = this.el.adjustForConstraints(xy);\r
26018         }\r
26019         this.el.setXY(xy);\r
26020         this.el.show();\r
26021         this.hidden = false;\r
26022         this.focus();\r
26023         this.fireEvent("show", this);\r
26024     },\r
26025 \r
26026 \r
26027 \r
26028     focus : function(){\r
26029         if(!this.hidden){\r
26030             this.doFocus.defer(50, this);\r
26031         }\r
26032     },\r
26033 \r
26034     doFocus : function(){\r
26035         if(!this.hidden){\r
26036             this.focusEl.focus();\r
26037         }\r
26038     },\r
26039 \r
26040     \r
26041     hide : function(deep){\r
26042         if(this.el && this.isVisible()){\r
26043             this.fireEvent("beforehide", this);\r
26044             if(this.activeItem){\r
26045                 this.activeItem.deactivate();\r
26046                 this.activeItem = null;\r
26047             }\r
26048             this.el.hide();\r
26049             this.hidden = true;\r
26050             this.fireEvent("hide", this);\r
26051         }\r
26052         if(deep === true && this.parentMenu){\r
26053             this.parentMenu.hide(true);\r
26054         }\r
26055     },\r
26056 \r
26057     \r
26058     add : function(){\r
26059         var a = arguments, l = a.length, item;\r
26060         for(var i = 0; i < l; i++){\r
26061             var el = a[i];\r
26062             if(el.render){ // some kind of Item\r
26063                 item = this.addItem(el);\r
26064             }else if(typeof el == "string"){ // string\r
26065                 if(el == "separator" || el == "-"){\r
26066                     item = this.addSeparator();\r
26067                 }else{\r
26068                     item = this.addText(el);\r
26069                 }\r
26070             }else if(el.tagName || el.el){ // element\r
26071                 item = this.addElement(el);\r
26072             }else if(typeof el == "object"){ // must be menu item config?\r
26073                 Ext.applyIf(el, this.defaults);\r
26074                 item = this.addMenuItem(el);\r
26075             }\r
26076         }\r
26077         return item;\r
26078     },\r
26079 \r
26080     \r
26081     getEl : function(){\r
26082         if(!this.el){\r
26083             this.render();\r
26084         }\r
26085         return this.el;\r
26086     },\r
26087 \r
26088     \r
26089     addSeparator : function(){\r
26090         return this.addItem(new Ext.menu.Separator());\r
26091     },\r
26092 \r
26093     \r
26094     addElement : function(el){\r
26095         return this.addItem(new Ext.menu.BaseItem(el));\r
26096     },\r
26097 \r
26098     \r
26099     addItem : function(item){\r
26100         this.items.add(item);\r
26101         if(this.ul){\r
26102             var li = document.createElement("li");\r
26103             li.className = "x-menu-list-item";\r
26104             this.ul.dom.appendChild(li);\r
26105             item.render(li, this);\r
26106             this.delayAutoWidth();\r
26107         }\r
26108         return item;\r
26109     },\r
26110 \r
26111     \r
26112     addMenuItem : function(config){\r
26113         if(!(config instanceof Ext.menu.Item)){\r
26114             if(typeof config.checked == "boolean"){ // must be check menu item config?\r
26115                 config = new Ext.menu.CheckItem(config);\r
26116             }else{\r
26117                 config = new Ext.menu.Item(config);\r
26118             }\r
26119         }\r
26120         return this.addItem(config);\r
26121     },\r
26122 \r
26123     \r
26124     addText : function(text){\r
26125         return this.addItem(new Ext.menu.TextItem(text));\r
26126     },\r
26127 \r
26128     \r
26129     insert : function(index, item){\r
26130         this.items.insert(index, item);\r
26131         if(this.ul){\r
26132             var li = document.createElement("li");\r
26133             li.className = "x-menu-list-item";\r
26134             this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);\r
26135             item.render(li, this);\r
26136             this.delayAutoWidth();\r
26137         }\r
26138         return item;\r
26139     },\r
26140 \r
26141     \r
26142     remove : function(item){\r
26143         this.items.removeKey(item.id);\r
26144         item.destroy();\r
26145     },\r
26146 \r
26147     \r
26148     removeAll : function(){\r
26149         if(this.items){\r
26150                 var f;\r
26151                 while(f = this.items.first()){\r
26152                     this.remove(f);\r
26153                 }\r
26154         }\r
26155     },\r
26156 \r
26157     \r
26158     destroy : function(){\r
26159         this.beforeDestroy();\r
26160         Ext.menu.MenuMgr.unregister(this);\r
26161         if (this.keyNav) {\r
26162                 this.keyNav.disable();\r
26163         }\r
26164         this.removeAll();\r
26165         if (this.ul) {\r
26166                 this.ul.removeAllListeners();\r
26167         }\r
26168         if (this.el) {\r
26169                 this.el.destroy();\r
26170         }\r
26171     },\r
26172 \r
26173         // private\r
26174     beforeDestroy : Ext.emptyFn\r
26175 \r
26176 });\r
26177 \r
26178 // MenuNav is a private utility class used internally by the Menu\r
26179 Ext.menu.MenuNav = function(menu){\r
26180     Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);\r
26181     this.scope = this.menu = menu;\r
26182 };\r
26183 \r
26184 Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {\r
26185     doRelay : function(e, h){\r
26186         var k = e.getKey();\r
26187         if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){\r
26188             this.menu.tryActivate(0, 1);\r
26189             return false;\r
26190         }\r
26191         return h.call(this.scope || this, e, this.menu);\r
26192     },\r
26193 \r
26194     up : function(e, m){\r
26195         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){\r
26196             m.tryActivate(m.items.length-1, -1);\r
26197         }\r
26198     },\r
26199 \r
26200     down : function(e, m){\r
26201         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){\r
26202             m.tryActivate(0, 1);\r
26203         }\r
26204     },\r
26205 \r
26206     right : function(e, m){\r
26207         if(m.activeItem){\r
26208             m.activeItem.expandMenu(true);\r
26209         }\r
26210     },\r
26211 \r
26212     left : function(e, m){\r
26213         m.hide();\r
26214         if(m.parentMenu && m.parentMenu.activeItem){\r
26215             m.parentMenu.activeItem.activate();\r
26216         }\r
26217     },\r
26218 \r
26219     enter : function(e, m){\r
26220         if(m.activeItem){\r
26221             e.stopPropagation();\r
26222             m.activeItem.onClick(e);\r
26223             m.fireEvent("click", this, m.activeItem);\r
26224             return true;\r
26225         }\r
26226     }\r
26227 });\r
26228 \r
26229 Ext.menu.MenuMgr = function(){\r
26230    var menus, active, groups = {}, attached = false, lastShow = new Date();\r
26231 \r
26232    // private - called when first menu is created\r
26233    function init(){\r
26234        menus = {};\r
26235        active = new Ext.util.MixedCollection();\r
26236        Ext.getDoc().addKeyListener(27, function(){\r
26237            if(active.length > 0){\r
26238                hideAll();\r
26239            }\r
26240        });\r
26241    }\r
26242 \r
26243    // private\r
26244    function hideAll(){\r
26245        if(active && active.length > 0){\r
26246            var c = active.clone();\r
26247            c.each(function(m){\r
26248                m.hide();\r
26249            });\r
26250        }\r
26251    }\r
26252 \r
26253    // private\r
26254    function onHide(m){\r
26255        active.remove(m);\r
26256        if(active.length < 1){\r
26257            Ext.getDoc().un("mousedown", onMouseDown);\r
26258            attached = false;\r
26259        }\r
26260    }\r
26261 \r
26262    // private\r
26263    function onShow(m){\r
26264        var last = active.last();\r
26265        lastShow = new Date();\r
26266        active.add(m);\r
26267        if(!attached){\r
26268            Ext.getDoc().on("mousedown", onMouseDown);\r
26269            attached = true;\r
26270        }\r
26271        if(m.parentMenu){\r
26272           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);\r
26273           m.parentMenu.activeChild = m;\r
26274        }else if(last && last.isVisible()){\r
26275           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);\r
26276        }\r
26277    }\r
26278 \r
26279    // private\r
26280    function onBeforeHide(m){\r
26281        if(m.activeChild){\r
26282            m.activeChild.hide();\r
26283        }\r
26284        if(m.autoHideTimer){\r
26285            clearTimeout(m.autoHideTimer);\r
26286            delete m.autoHideTimer;\r
26287        }\r
26288    }\r
26289 \r
26290    // private\r
26291    function onBeforeShow(m){\r
26292        var pm = m.parentMenu;\r
26293        if(!pm && !m.allowOtherMenus){\r
26294            hideAll();\r
26295        }else if(pm && pm.activeChild){\r
26296            pm.activeChild.hide();\r
26297        }\r
26298    }\r
26299 \r
26300    // private\r
26301    function onMouseDown(e){\r
26302        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){\r
26303            hideAll();\r
26304        }\r
26305    }\r
26306 \r
26307    // private\r
26308    function onBeforeCheck(mi, state){\r
26309        if(state){\r
26310            var g = groups[mi.group];\r
26311            for(var i = 0, l = g.length; i < l; i++){\r
26312                if(g[i] != mi){\r
26313                    g[i].setChecked(false);\r
26314                }\r
26315            }\r
26316        }\r
26317    }\r
26318 \r
26319    return {\r
26320 \r
26321        \r
26322        hideAll : function(){\r
26323             hideAll();  \r
26324        },\r
26325 \r
26326        // private\r
26327        register : function(menu){\r
26328            if(!menus){\r
26329                init();\r
26330            }\r
26331            menus[menu.id] = menu;\r
26332            menu.on("beforehide", onBeforeHide);\r
26333            menu.on("hide", onHide);\r
26334            menu.on("beforeshow", onBeforeShow);\r
26335            menu.on("show", onShow);\r
26336            var g = menu.group;\r
26337            if(g && menu.events["checkchange"]){\r
26338                if(!groups[g]){\r
26339                    groups[g] = [];\r
26340                }\r
26341                groups[g].push(menu);\r
26342                menu.on("checkchange", onCheck);\r
26343            }\r
26344        },\r
26345 \r
26346         \r
26347        get : function(menu){\r
26348            if(typeof menu == "string"){ // menu id\r
26349                if(!menus){  // not initialized, no menus to return\r
26350                    return null;\r
26351                }\r
26352                return menus[menu];\r
26353            }else if(menu.events){  // menu instance\r
26354                return menu;\r
26355            }else if(typeof menu.length == 'number'){ // array of menu items?\r
26356                return new Ext.menu.Menu({items:menu});\r
26357            }else{ // otherwise, must be a config\r
26358                return new Ext.menu.Menu(menu);\r
26359            }\r
26360        },\r
26361 \r
26362        // private\r
26363        unregister : function(menu){\r
26364            delete menus[menu.id];\r
26365            menu.un("beforehide", onBeforeHide);\r
26366            menu.un("hide", onHide);\r
26367            menu.un("beforeshow", onBeforeShow);\r
26368            menu.un("show", onShow);\r
26369            var g = menu.group;\r
26370            if(g && menu.events["checkchange"]){\r
26371                groups[g].remove(menu);\r
26372                menu.un("checkchange", onCheck);\r
26373            }\r
26374        },\r
26375 \r
26376        // private\r
26377        registerCheckable : function(menuItem){\r
26378            var g = menuItem.group;\r
26379            if(g){\r
26380                if(!groups[g]){\r
26381                    groups[g] = [];\r
26382                }\r
26383                groups[g].push(menuItem);\r
26384                menuItem.on("beforecheckchange", onBeforeCheck);\r
26385            }\r
26386        },\r
26387 \r
26388        // private\r
26389        unregisterCheckable : function(menuItem){\r
26390            var g = menuItem.group;\r
26391            if(g){\r
26392                groups[g].remove(menuItem);\r
26393                menuItem.un("beforecheckchange", onBeforeCheck);\r
26394            }\r
26395        },\r
26396 \r
26397        getCheckedItem : function(groupId){\r
26398            var g = groups[groupId];\r
26399            if(g){\r
26400                for(var i = 0, l = g.length; i < l; i++){\r
26401                    if(g[i].checked){\r
26402                        return g[i];\r
26403                    }\r
26404                }\r
26405            }\r
26406            return null;\r
26407        },\r
26408 \r
26409        setCheckedItem : function(groupId, itemId){\r
26410            var g = groups[groupId];\r
26411            if(g){\r
26412                for(var i = 0, l = g.length; i < l; i++){\r
26413                    if(g[i].id == itemId){\r
26414                        g[i].setChecked(true);\r
26415                    }\r
26416                }\r
26417            }\r
26418            return null;\r
26419        }\r
26420    };\r
26421 }();\r
26422 \r
26423 \r
26424 Ext.menu.BaseItem = function(config){\r
26425     Ext.menu.BaseItem.superclass.constructor.call(this, config);\r
26426 \r
26427     this.addEvents(\r
26428         \r
26429         'click',\r
26430         \r
26431         'activate',\r
26432         \r
26433         'deactivate'\r
26434     );\r
26435 \r
26436     if(this.handler){\r
26437         this.on("click", this.handler, this.scope);\r
26438     }\r
26439 };\r
26440 \r
26441 Ext.extend(Ext.menu.BaseItem, Ext.Component, {\r
26442     \r
26443     \r
26444     \r
26445     canActivate : false,\r
26446     \r
26447     activeClass : "x-menu-item-active",\r
26448     \r
26449     hideOnClick : true,\r
26450     \r
26451     hideDelay : 100,\r
26452 \r
26453     // private\r
26454     ctype: "Ext.menu.BaseItem",\r
26455 \r
26456     // private\r
26457     actionMode : "container",\r
26458 \r
26459     // private\r
26460     render : function(container, parentMenu){\r
26461         \r
26462         this.parentMenu = parentMenu;\r
26463         Ext.menu.BaseItem.superclass.render.call(this, container);\r
26464         this.container.menuItemId = this.id;\r
26465     },\r
26466 \r
26467     // private\r
26468     onRender : function(container, position){\r
26469         this.el = Ext.get(this.el);\r
26470         if(this.id){\r
26471             this.el.id = this.id;\r
26472         }\r
26473         container.dom.appendChild(this.el.dom);\r
26474     },\r
26475 \r
26476     \r
26477     setHandler : function(handler, scope){\r
26478         if(this.handler){\r
26479             this.un("click", this.handler, this.scope);\r
26480         }\r
26481         this.on("click", this.handler = handler, this.scope = scope);\r
26482     },\r
26483 \r
26484     // private\r
26485     onClick : function(e){\r
26486         if(!this.disabled && this.fireEvent("click", this, e) !== false\r
26487                 && this.parentMenu.fireEvent("itemclick", this, e) !== false){\r
26488             this.handleClick(e);\r
26489         }else{\r
26490             e.stopEvent();\r
26491         }\r
26492     },\r
26493 \r
26494     // private\r
26495     activate : function(){\r
26496         if(this.disabled){\r
26497             return false;\r
26498         }\r
26499         var li = this.container;\r
26500         li.addClass(this.activeClass);\r
26501         this.region = li.getRegion().adjust(2, 2, -2, -2);\r
26502         this.fireEvent("activate", this);\r
26503         return true;\r
26504     },\r
26505 \r
26506     // private\r
26507     deactivate : function(){\r
26508         this.container.removeClass(this.activeClass);\r
26509         this.fireEvent("deactivate", this);\r
26510     },\r
26511 \r
26512     // private\r
26513     shouldDeactivate : function(e){\r
26514         return !this.region || !this.region.contains(e.getPoint());\r
26515     },\r
26516 \r
26517     // private\r
26518     handleClick : function(e){\r
26519         if(this.hideOnClick){\r
26520             this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);\r
26521         }\r
26522     },\r
26523 \r
26524     // private\r
26525     expandMenu : function(autoActivate){\r
26526         // do nothing\r
26527     },\r
26528 \r
26529     // private\r
26530     hideMenu : function(){\r
26531         // do nothing\r
26532     }\r
26533 });\r
26534 \r
26535 Ext.menu.TextItem = function(cfg){\r
26536     if(typeof cfg == 'string'){\r
26537         cfg = {text: cfg}\r
26538     }\r
26539     Ext.menu.TextItem.superclass.constructor.call(this, cfg);\r
26540 };\r
26541 \r
26542 Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {\r
26543     \r
26544     \r
26545     hideOnClick : false,\r
26546     \r
26547     itemCls : "x-menu-text",\r
26548 \r
26549     // private\r
26550     onRender : function(){\r
26551         var s = document.createElement("span");\r
26552         s.className = this.itemCls;\r
26553         s.innerHTML = this.text;\r
26554         this.el = s;\r
26555         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);\r
26556     }\r
26557 });\r
26558 \r
26559 Ext.menu.Separator = function(config){\r
26560     Ext.menu.Separator.superclass.constructor.call(this, config);\r
26561 };\r
26562 \r
26563 Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {\r
26564     \r
26565     itemCls : "x-menu-sep",\r
26566     \r
26567     hideOnClick : false,\r
26568 \r
26569     // private\r
26570     onRender : function(li){\r
26571         var s = document.createElement("span");\r
26572         s.className = this.itemCls;\r
26573         s.innerHTML = "&#160;";\r
26574         this.el = s;\r
26575         li.addClass("x-menu-sep-li");\r
26576         Ext.menu.Separator.superclass.onRender.apply(this, arguments);\r
26577     }\r
26578 });\r
26579 \r
26580 Ext.menu.Item = function(config){\r
26581     Ext.menu.Item.superclass.constructor.call(this, config);\r
26582     if(this.menu){\r
26583         this.menu = Ext.menu.MenuMgr.get(this.menu);\r
26584     }\r
26585 };\r
26586 Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {\r
26587     \r
26588     \r
26589     \r
26590     \r
26591     \r
26592     \r
26593     \r
26594     itemCls : "x-menu-item",\r
26595     \r
26596     canActivate : true,\r
26597     \r
26598     showDelay: 200,\r
26599     // doc'd in BaseItem\r
26600     hideDelay: 200,\r
26601 \r
26602     // private\r
26603     ctype: "Ext.menu.Item",\r
26604 \r
26605     // private\r
26606     onRender : function(container, position){\r
26607         var el = document.createElement("a");\r
26608         el.hideFocus = true;\r
26609         el.unselectable = "on";\r
26610         el.href = this.href || "#";\r
26611         if(this.hrefTarget){\r
26612             el.target = this.hrefTarget;\r
26613         }\r
26614         el.className = this.itemCls + (this.menu ?  " x-menu-item-arrow" : "") + (this.cls ?  " " + this.cls : "");\r
26615         el.innerHTML = String.format(\r
26616                 '<img src="{0}" class="x-menu-item-icon {2}" />{1}',\r
26617                 this.icon || Ext.BLANK_IMAGE_URL, this.itemText||this.text, this.iconCls || '');\r
26618         this.el = el;\r
26619         Ext.menu.Item.superclass.onRender.call(this, container, position);\r
26620     },\r
26621 \r
26622     \r
26623     setText : function(text){\r
26624         this.text = text;\r
26625         if(this.rendered){\r
26626             this.el.update(String.format(\r
26627                 '<img src="{0}" class="x-menu-item-icon {2}">{1}',\r
26628                 this.icon || Ext.BLANK_IMAGE_URL, this.text, this.iconCls || ''));\r
26629             this.parentMenu.autoWidth();\r
26630         }\r
26631     },\r
26632 \r
26633     \r
26634     setIconClass : function(cls){\r
26635         var oldCls = this.iconCls;\r
26636         this.iconCls = cls;\r
26637         if(this.rendered){\r
26638             this.el.child('img.x-menu-item-icon').replaceClass(oldCls, this.iconCls);\r
26639         }\r
26640     },\r
26641     \r
26642     //private\r
26643     beforeDestroy: function(){\r
26644         if (this.menu){\r
26645             this.menu.destroy();\r
26646         }\r
26647         Ext.menu.Item.superclass.beforeDestroy.call(this);\r
26648     },\r
26649 \r
26650     // private\r
26651     handleClick : function(e){\r
26652         if(!this.href){ // if no link defined, stop the event automatically\r
26653             e.stopEvent();\r
26654         }\r
26655         Ext.menu.Item.superclass.handleClick.apply(this, arguments);\r
26656     },\r
26657 \r
26658     // private\r
26659     activate : function(autoExpand){\r
26660         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){\r
26661             this.focus();\r
26662             if(autoExpand){\r
26663                 this.expandMenu();\r
26664             }\r
26665         }\r
26666         return true;\r
26667     },\r
26668 \r
26669     // private\r
26670     shouldDeactivate : function(e){\r
26671         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){\r
26672             if(this.menu && this.menu.isVisible()){\r
26673                 return !this.menu.getEl().getRegion().contains(e.getPoint());\r
26674             }\r
26675             return true;\r
26676         }\r
26677         return false;\r
26678     },\r
26679 \r
26680     // private\r
26681     deactivate : function(){\r
26682         Ext.menu.Item.superclass.deactivate.apply(this, arguments);\r
26683         this.hideMenu();\r
26684     },\r
26685 \r
26686     // private\r
26687     expandMenu : function(autoActivate){\r
26688         if(!this.disabled && this.menu){\r
26689             clearTimeout(this.hideTimer);\r
26690             delete this.hideTimer;\r
26691             if(!this.menu.isVisible() && !this.showTimer){\r
26692                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);\r
26693             }else if (this.menu.isVisible() && autoActivate){\r
26694                 this.menu.tryActivate(0, 1);\r
26695             }\r
26696         }\r
26697     },\r
26698 \r
26699     // private\r
26700     deferExpand : function(autoActivate){\r
26701         delete this.showTimer;\r
26702         this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);\r
26703         if(autoActivate){\r
26704             this.menu.tryActivate(0, 1);\r
26705         }\r
26706     },\r
26707 \r
26708     // private\r
26709     hideMenu : function(){\r
26710         clearTimeout(this.showTimer);\r
26711         delete this.showTimer;\r
26712         if(!this.hideTimer && this.menu && this.menu.isVisible()){\r
26713             this.hideTimer = this.deferHide.defer(this.hideDelay, this);\r
26714         }\r
26715     },\r
26716 \r
26717     // private\r
26718     deferHide : function(){\r
26719         delete this.hideTimer;\r
26720         if(this.menu.over){\r
26721             this.parentMenu.setActiveItem(this, false);\r
26722         }else{\r
26723             this.menu.hide();\r
26724         }\r
26725     }\r
26726 });\r
26727 \r
26728 Ext.menu.CheckItem = function(config){\r
26729     Ext.menu.CheckItem.superclass.constructor.call(this, config);\r
26730     this.addEvents(\r
26731         \r
26732         "beforecheckchange" ,\r
26733         \r
26734         "checkchange"\r
26735     );\r
26736     \r
26737     if(this.checkHandler){\r
26738         this.on('checkchange', this.checkHandler, this.scope);\r
26739     }\r
26740     Ext.menu.MenuMgr.registerCheckable(this);\r
26741 };\r
26742 Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {\r
26743     \r
26744     \r
26745     itemCls : "x-menu-item x-menu-check-item",\r
26746     \r
26747     groupClass : "x-menu-group-item",\r
26748 \r
26749     \r
26750     checked: false,\r
26751 \r
26752     // private\r
26753     ctype: "Ext.menu.CheckItem",\r
26754 \r
26755     // private\r
26756     onRender : function(c){\r
26757         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);\r
26758         if(this.group){\r
26759             this.el.addClass(this.groupClass);\r
26760         }\r
26761         if(this.checked){\r
26762             this.checked = false;\r
26763             this.setChecked(true, true);\r
26764         }\r
26765     },\r
26766 \r
26767     // private\r
26768     destroy : function(){\r
26769         Ext.menu.MenuMgr.unregisterCheckable(this);\r
26770         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);\r
26771     },\r
26772 \r
26773     \r
26774     setChecked : function(state, suppressEvent){\r
26775         if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){\r
26776             if(this.container){\r
26777                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");\r
26778             }\r
26779             this.checked = state;\r
26780             if(suppressEvent !== true){\r
26781                 this.fireEvent("checkchange", this, state);\r
26782             }\r
26783         }\r
26784     },\r
26785 \r
26786     // private\r
26787     handleClick : function(e){\r
26788        if(!this.disabled && !(this.checked && this.group)){// disable unselect on radio item\r
26789            this.setChecked(!this.checked);\r
26790        }\r
26791        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);\r
26792     }\r
26793 });\r
26794 \r
26795 Ext.menu.Adapter = function(component, config){\r
26796     Ext.menu.Adapter.superclass.constructor.call(this, config);\r
26797     this.component = component;\r
26798 };\r
26799 Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {\r
26800     // private\r
26801     canActivate : true,\r
26802 \r
26803     // private\r
26804     onRender : function(container, position){\r
26805         this.component.render(container);\r
26806         this.el = this.component.getEl();\r
26807     },\r
26808 \r
26809     // private\r
26810     activate : function(){\r
26811         if(this.disabled){\r
26812             return false;\r
26813         }\r
26814         this.component.focus();\r
26815         this.fireEvent("activate", this);\r
26816         return true;\r
26817     },\r
26818 \r
26819     // private\r
26820     deactivate : function(){\r
26821         this.fireEvent("deactivate", this);\r
26822     },\r
26823 \r
26824     // private\r
26825     disable : function(){\r
26826         this.component.disable();\r
26827         Ext.menu.Adapter.superclass.disable.call(this);\r
26828     },\r
26829 \r
26830     // private\r
26831     enable : function(){\r
26832         this.component.enable();\r
26833         Ext.menu.Adapter.superclass.enable.call(this);\r
26834     }\r
26835 });\r
26836 \r
26837 Ext.menu.DateItem = function(config){\r
26838     Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);\r
26839     \r
26840     this.picker = this.component;\r
26841     this.addEvents('select');\r
26842     \r
26843     this.picker.on("render", function(picker){\r
26844         picker.getEl().swallowEvent("click");\r
26845         picker.container.addClass("x-menu-date-item");\r
26846     });\r
26847 \r
26848     this.picker.on("select", this.onSelect, this);\r
26849 };\r
26850 \r
26851 Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {\r
26852     // private\r
26853     onSelect : function(picker, date){\r
26854         this.fireEvent("select", this, date, picker);\r
26855         Ext.menu.DateItem.superclass.handleClick.call(this);\r
26856     }\r
26857 });\r
26858 \r
26859 Ext.menu.ColorItem = function(config){\r
26860     Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);\r
26861     \r
26862     this.palette = this.component;\r
26863     this.relayEvents(this.palette, ["select"]);\r
26864     if(this.selectHandler){\r
26865         this.on('select', this.selectHandler, this.scope);\r
26866     }\r
26867 };\r
26868 Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);\r
26869 \r
26870 Ext.menu.DateMenu = function(config){\r
26871     Ext.menu.DateMenu.superclass.constructor.call(this, config);\r
26872     this.plain = true;\r
26873     var di = new Ext.menu.DateItem(config);\r
26874     this.add(di);\r
26875     \r
26876     this.picker = di.picker;\r
26877     \r
26878     this.relayEvents(di, ["select"]);\r
26879 \r
26880     this.on('beforeshow', function(){\r
26881         if(this.picker){\r
26882             this.picker.hideMonthPicker(true);\r
26883         }\r
26884     }, this);\r
26885 };\r
26886 Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {\r
26887     cls:'x-date-menu',\r
26888 \r
26889     // private\r
26890     beforeDestroy : function() {\r
26891         this.picker.destroy();\r
26892     }\r
26893 });\r
26894 \r
26895 Ext.menu.ColorMenu = function(config){\r
26896     Ext.menu.ColorMenu.superclass.constructor.call(this, config);\r
26897     this.plain = true;\r
26898     var ci = new Ext.menu.ColorItem(config);\r
26899     this.add(ci);\r
26900     \r
26901     this.palette = ci.palette;\r
26902     \r
26903     this.relayEvents(ci, ["select"]);\r
26904 };\r
26905 Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu, {\r
26906     //private\r
26907     beforeDestroy: function(){\r
26908         this.palette.destroy();\r
26909     }\r
26910 });\r
26911 \r
26912 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {\r
26913     \r
26914     \r
26915     \r
26916     \r
26917     \r
26918     \r
26919     \r
26920     \r
26921     \r
26922     \r
26923     \r
26924 \r
26925     \r
26926     invalidClass : "x-form-invalid",\r
26927     \r
26928     invalidText : "The value in this field is invalid",\r
26929     \r
26930     focusClass : "x-form-focus",\r
26931     \r
26932     validationEvent : "keyup",\r
26933     \r
26934     validateOnBlur : true,\r
26935     \r
26936     validationDelay : 250,\r
26937     \r
26938     defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},\r
26939     \r
26940     fieldClass : "x-form-field",\r
26941     \r
26942     msgTarget : 'qtip',\r
26943     \r
26944     msgFx : 'normal',\r
26945     \r
26946     readOnly : false,\r
26947     \r
26948     disabled : false,\r
26949 \r
26950     // private\r
26951     isFormField : true,\r
26952 \r
26953     // private\r
26954     hasFocus : false,\r
26955 \r
26956         // private\r
26957         initComponent : function(){\r
26958         Ext.form.Field.superclass.initComponent.call(this);\r
26959         this.addEvents(\r
26960             \r
26961             'focus',\r
26962             \r
26963             'blur',\r
26964             \r
26965             'specialkey',\r
26966             \r
26967             'change',\r
26968             \r
26969             'invalid',\r
26970             \r
26971             'valid'\r
26972         );\r
26973     },\r
26974 \r
26975     \r
26976     getName: function(){\r
26977          return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');\r
26978     },\r
26979 \r
26980     // private\r
26981     onRender : function(ct, position){\r
26982         Ext.form.Field.superclass.onRender.call(this, ct, position);\r
26983         if(!this.el){\r
26984             var cfg = this.getAutoCreate();\r
26985             if(!cfg.name){\r
26986                 cfg.name = this.name || this.id;\r
26987             }\r
26988             if(this.inputType){\r
26989                 cfg.type = this.inputType;\r
26990             }\r
26991             this.el = ct.createChild(cfg, position);\r
26992         }\r
26993         var type = this.el.dom.type;\r
26994         if(type){\r
26995             if(type == 'password'){\r
26996                 type = 'text';\r
26997             }\r
26998             this.el.addClass('x-form-'+type);\r
26999         }\r
27000         if(this.readOnly){\r
27001             this.el.dom.readOnly = true;\r
27002         }\r
27003         if(this.tabIndex !== undefined){\r
27004             this.el.dom.setAttribute('tabIndex', this.tabIndex);\r
27005         }\r
27006 \r
27007         this.el.addClass([this.fieldClass, this.cls]);\r
27008     },\r
27009 \r
27010     // private\r
27011     initValue : function(){\r
27012         if(this.value !== undefined){\r
27013             this.setValue(this.value);\r
27014         }else if(this.el.dom.value.length > 0 && this.el.dom.value != this.emptyText){\r
27015             this.setValue(this.el.dom.value);\r
27016         }\r
27017         // reference to original value for reset\r
27018         this.originalValue = this.getValue();\r
27019     },\r
27020 \r
27021     \r
27022     isDirty : function() {\r
27023         if(this.disabled) {\r
27024             return false;\r
27025         }\r
27026         return String(this.getValue()) !== String(this.originalValue);\r
27027     },\r
27028 \r
27029     // private\r
27030     afterRender : function(){\r
27031         Ext.form.Field.superclass.afterRender.call(this);\r
27032         this.initEvents();\r
27033         this.initValue();\r
27034     },\r
27035 \r
27036     // private\r
27037     fireKey : function(e){\r
27038         if(e.isSpecialKey()){\r
27039             this.fireEvent("specialkey", this, e);\r
27040         }\r
27041     },\r
27042 \r
27043     \r
27044     reset : function(){\r
27045         this.setValue(this.originalValue);\r
27046         this.clearInvalid();\r
27047     },\r
27048 \r
27049     // private\r
27050     initEvents : function(){\r
27051         this.el.on(Ext.isIE || Ext.isSafari3 ? "keydown" : "keypress", this.fireKey,  this);\r
27052         this.el.on("focus", this.onFocus,  this);\r
27053 \r
27054         // fix weird FF/Win editor issue when changing OS window focus\r
27055         var o = this.inEditor && Ext.isWindows && Ext.isGecko ? {buffer:10} : null;\r
27056         this.el.on("blur", this.onBlur,  this, o);\r
27057     },\r
27058 \r
27059     // private\r
27060     onFocus : function(){\r
27061         if(this.focusClass){\r
27062             this.el.addClass(this.focusClass);\r
27063         }\r
27064         if(!this.hasFocus){\r
27065             this.hasFocus = true;\r
27066             this.startValue = this.getValue();\r
27067             this.fireEvent("focus", this);\r
27068         }\r
27069     },\r
27070 \r
27071     // private\r
27072     beforeBlur : Ext.emptyFn,\r
27073 \r
27074     // private\r
27075     onBlur : function(){\r
27076         this.beforeBlur();\r
27077         if(this.focusClass){\r
27078             this.el.removeClass(this.focusClass);\r
27079         }\r
27080         this.hasFocus = false;\r
27081         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){\r
27082             this.validate();\r
27083         }\r
27084         var v = this.getValue();\r
27085         if(String(v) !== String(this.startValue)){\r
27086             this.fireEvent('change', this, v, this.startValue);\r
27087         }\r
27088         this.fireEvent("blur", this);\r
27089     },\r
27090 \r
27091     \r
27092     isValid : function(preventMark){\r
27093         if(this.disabled){\r
27094             return true;\r
27095         }\r
27096         var restore = this.preventMark;\r
27097         this.preventMark = preventMark === true;\r
27098         var v = this.validateValue(this.processValue(this.getRawValue()));\r
27099         this.preventMark = restore;\r
27100         return v;\r
27101     },\r
27102 \r
27103     \r
27104     validate : function(){\r
27105         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){\r
27106             this.clearInvalid();\r
27107             return true;\r
27108         }\r
27109         return false;\r
27110     },\r
27111 \r
27112     // protected - should be overridden by subclasses if necessary to prepare raw values for validation\r
27113     processValue : function(value){\r
27114         return value;\r
27115     },\r
27116 \r
27117     // private\r
27118     // Subclasses should provide the validation implementation by overriding this\r
27119     validateValue : function(value){\r
27120         return true;\r
27121     },\r
27122 \r
27123     \r
27124     markInvalid : function(msg){\r
27125         if(!this.rendered || this.preventMark){ // not rendered\r
27126             return;\r
27127         }\r
27128         this.el.addClass(this.invalidClass);\r
27129         msg = msg || this.invalidText;\r
27130 \r
27131         switch(this.msgTarget){\r
27132             case 'qtip':\r
27133                 this.el.dom.qtip = msg;\r
27134                 this.el.dom.qclass = 'x-form-invalid-tip';\r
27135                 if(Ext.QuickTips){ // fix for floating editors interacting with DND\r
27136                     Ext.QuickTips.enable();\r
27137                 }\r
27138                 break;\r
27139             case 'title':\r
27140                 this.el.dom.title = msg;\r
27141                 break;\r
27142             case 'under':\r
27143                 if(!this.errorEl){\r
27144                     var elp = this.getErrorCt();\r
27145                     if(!elp){ // field has no container el\r
27146                         this.el.dom.title = msg;\r
27147                         break;\r
27148                     }\r
27149                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});\r
27150                     this.errorEl.setWidth(elp.getWidth(true)-20);\r
27151                 }\r
27152                 this.errorEl.update(msg);\r
27153                 Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);\r
27154                 break;\r
27155             case 'side':\r
27156                 if(!this.errorIcon){\r
27157                     var elp = this.getErrorCt();\r
27158                     if(!elp){ // field has no container el\r
27159                         this.el.dom.title = msg;\r
27160                         break;\r
27161                     }\r
27162                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});\r
27163                 }\r
27164                 this.alignErrorIcon();\r
27165                 this.errorIcon.dom.qtip = msg;\r
27166                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';\r
27167                 this.errorIcon.show();\r
27168                 this.on('resize', this.alignErrorIcon, this);\r
27169                 break;\r
27170             default:\r
27171                 var t = Ext.getDom(this.msgTarget);\r
27172                 t.innerHTML = msg;\r
27173                 t.style.display = this.msgDisplay;\r
27174                 break;\r
27175         }\r
27176         this.fireEvent('invalid', this, msg);\r
27177     },\r
27178 \r
27179     // private\r
27180     getErrorCt : function(){\r
27181         return this.el.findParent('.x-form-element', 5, true) || // use form element wrap if available\r
27182             this.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap\r
27183     },\r
27184 \r
27185     // private\r
27186     alignErrorIcon : function(){\r
27187         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);\r
27188     },\r
27189 \r
27190     \r
27191     clearInvalid : function(){\r
27192         if(!this.rendered || this.preventMark){ // not rendered\r
27193             return;\r
27194         }\r
27195         this.el.removeClass(this.invalidClass);\r
27196         switch(this.msgTarget){\r
27197             case 'qtip':\r
27198                 this.el.dom.qtip = '';\r
27199                 break;\r
27200             case 'title':\r
27201                 this.el.dom.title = '';\r
27202                 break;\r
27203             case 'under':\r
27204                 if(this.errorEl){\r
27205                     Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);\r
27206                 }\r
27207                 break;\r
27208             case 'side':\r
27209                 if(this.errorIcon){\r
27210                     this.errorIcon.dom.qtip = '';\r
27211                     this.errorIcon.hide();\r
27212                     this.un('resize', this.alignErrorIcon, this);\r
27213                 }\r
27214                 break;\r
27215             default:\r
27216                 var t = Ext.getDom(this.msgTarget);\r
27217                 t.innerHTML = '';\r
27218                 t.style.display = 'none';\r
27219                 break;\r
27220         }\r
27221         this.fireEvent('valid', this);\r
27222     },\r
27223 \r
27224     \r
27225     getRawValue : function(){\r
27226         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');\r
27227         if(v === this.emptyText){\r
27228             v = '';\r
27229         }\r
27230         return v;\r
27231     },\r
27232 \r
27233     \r
27234     getValue : function(){\r
27235         if(!this.rendered) {\r
27236             return this.value;\r
27237         }\r
27238         var v = this.el.getValue();\r
27239         if(v === this.emptyText || v === undefined){\r
27240             v = '';\r
27241         }\r
27242         return v;\r
27243     },\r
27244 \r
27245     \r
27246     setRawValue : function(v){\r
27247         return this.el.dom.value = (v === null || v === undefined ? '' : v);\r
27248     },\r
27249 \r
27250     \r
27251     setValue : function(v){\r
27252         this.value = v;\r
27253         if(this.rendered){\r
27254             this.el.dom.value = (v === null || v === undefined ? '' : v);\r
27255             this.validate();\r
27256         }\r
27257     },\r
27258 \r
27259     // private\r
27260     adjustSize : function(w, h){\r
27261         var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);\r
27262         s.width = this.adjustWidth(this.el.dom.tagName, s.width);\r
27263         return s;\r
27264     },\r
27265 \r
27266     // private\r
27267     adjustWidth : function(tag, w){\r
27268         tag = tag.toLowerCase();\r
27269         if(typeof w == 'number' && !Ext.isSafari){\r
27270             if(Ext.isIE && (tag == 'input' || tag == 'textarea')){\r
27271                 if(tag == 'input' && !Ext.isStrict){\r
27272                     return this.inEditor ? w : w - 3;\r
27273                 }\r
27274                 if(tag == 'input' && Ext.isStrict){\r
27275                     return w - (Ext.isIE6 ? 4 : 1);\r
27276                 }\r
27277                 if(tag == 'textarea' && Ext.isStrict){\r
27278                     return w-2;\r
27279                 }\r
27280             }else if(Ext.isOpera && Ext.isStrict){\r
27281                 if(tag == 'input'){\r
27282                     return w + 2;\r
27283                 }\r
27284                 if(tag == 'textarea'){\r
27285                     return w-2;\r
27286                 }\r
27287             }\r
27288         }\r
27289         return w;\r
27290     }\r
27291 \r
27292     \r
27293     \r
27294 \r
27295     \r
27296 });\r
27297 \r
27298 Ext.form.MessageTargets = {\r
27299     'qtip' : {\r
27300         mark: function(f){\r
27301             this.el.dom.qtip = msg;\r
27302             this.el.dom.qclass = 'x-form-invalid-tip';\r
27303             if(Ext.QuickTips){ // fix for floating editors interacting with DND\r
27304                 Ext.QuickTips.enable();\r
27305             }\r
27306         },\r
27307         clear: function(f){\r
27308             this.el.dom.qtip = '';\r
27309         }\r
27310     },\r
27311     'title' : {\r
27312         mark: function(f){\r
27313             this.el.dom.title = msg;\r
27314         },\r
27315         clear: function(f){\r
27316             this.el.dom.title = '';\r
27317         }\r
27318     },\r
27319     'under' : {\r
27320         mark: function(f){\r
27321             if(!this.errorEl){\r
27322                 var elp = this.getErrorCt();\r
27323                 if(!elp){ // field has no container el\r
27324                     this.el.dom.title = msg;\r
27325                     return;\r
27326                 }\r
27327                 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});\r
27328                 this.errorEl.setWidth(elp.getWidth(true)-20);\r
27329             }\r
27330             this.errorEl.update(msg);\r
27331             Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);\r
27332         },\r
27333         clear: function(f){\r
27334             if(this.errorEl){\r
27335                 Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);\r
27336             }else{\r
27337                 this.el.dom.title = '';\r
27338             }\r
27339         }\r
27340     },\r
27341     'side' : {\r
27342         mark: function(f){\r
27343             if(!this.errorIcon){\r
27344                 var elp = this.getErrorCt();\r
27345                 if(!elp){ // field has no container el\r
27346                     this.el.dom.title = msg;\r
27347                     return;\r
27348                 }\r
27349                 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});\r
27350             }\r
27351             this.alignErrorIcon();\r
27352             this.errorIcon.dom.qtip = msg;\r
27353             this.errorIcon.dom.qclass = 'x-form-invalid-tip';\r
27354             this.errorIcon.show();\r
27355             this.on('resize', this.alignErrorIcon, this);\r
27356         },\r
27357         clear: function(f){\r
27358             if(this.errorIcon){\r
27359                 this.errorIcon.dom.qtip = '';\r
27360                 this.errorIcon.hide();\r
27361                 this.un('resize', this.alignErrorIcon, this);\r
27362             }else{\r
27363                 this.el.dom.title = '';\r
27364             }\r
27365         }\r
27366     },\r
27367     'around' : {\r
27368         mark: function(f){\r
27369 \r
27370         },\r
27371         clear: function(f){\r
27372 \r
27373         }\r
27374     }\r
27375 };\r
27376 \r
27377 \r
27378 // anything other than normal should be considered experimental\r
27379 Ext.form.Field.msgFx = {\r
27380     normal : {\r
27381         show: function(msgEl, f){\r
27382             msgEl.setDisplayed('block');\r
27383         },\r
27384 \r
27385         hide : function(msgEl, f){\r
27386             msgEl.setDisplayed(false).update('');\r
27387         }\r
27388     },\r
27389 \r
27390     slide : {\r
27391         show: function(msgEl, f){\r
27392             msgEl.slideIn('t', {stopFx:true});\r
27393         },\r
27394 \r
27395         hide : function(msgEl, f){\r
27396             msgEl.slideOut('t', {stopFx:true,useDisplay:true});\r
27397         }\r
27398     },\r
27399 \r
27400     slideRight : {\r
27401         show: function(msgEl, f){\r
27402             msgEl.fixDisplay();\r
27403             msgEl.alignTo(f.el, 'tl-tr');\r
27404             msgEl.slideIn('l', {stopFx:true});\r
27405         },\r
27406 \r
27407         hide : function(msgEl, f){\r
27408             msgEl.slideOut('l', {stopFx:true,useDisplay:true});\r
27409         }\r
27410     }\r
27411 };\r
27412 Ext.reg('field', Ext.form.Field);\r
27413 \r
27414 \r
27415 Ext.form.TextField = Ext.extend(Ext.form.Field,  {\r
27416     \r
27417     \r
27418     \r
27419     grow : false,\r
27420     \r
27421     growMin : 30,\r
27422     \r
27423     growMax : 800,\r
27424     \r
27425     vtype : null,\r
27426     \r
27427     maskRe : null,\r
27428     \r
27429     disableKeyFilter : false,\r
27430     \r
27431     allowBlank : true,\r
27432     \r
27433     minLength : 0,\r
27434     \r
27435     maxLength : Number.MAX_VALUE,\r
27436     \r
27437     minLengthText : "The minimum length for this field is {0}",\r
27438     \r
27439     maxLengthText : "The maximum length for this field is {0}",\r
27440     \r
27441     selectOnFocus : false,\r
27442     \r
27443     blankText : "This field is required",\r
27444     \r
27445     validator : null,\r
27446     \r
27447     regex : null,\r
27448     \r
27449     regexText : "",\r
27450     \r
27451     emptyText : null,\r
27452     \r
27453     emptyClass : 'x-form-empty-field',\r
27454 \r
27455     \r
27456 \r
27457     initComponent : function(){\r
27458         Ext.form.TextField.superclass.initComponent.call(this);\r
27459         this.addEvents(\r
27460             \r
27461             'autosize',\r
27462 \r
27463             \r
27464             'keydown',\r
27465             \r
27466             'keyup',\r
27467             \r
27468             'keypress'\r
27469         );\r
27470     },\r
27471 \r
27472     // private\r
27473     initEvents : function(){\r
27474         Ext.form.TextField.superclass.initEvents.call(this);\r
27475         if(this.validationEvent == 'keyup'){\r
27476             this.validationTask = new Ext.util.DelayedTask(this.validate, this);\r
27477             this.el.on('keyup', this.filterValidation, this);\r
27478         }\r
27479         else if(this.validationEvent !== false){\r
27480             this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});\r
27481         }\r
27482         if(this.selectOnFocus || this.emptyText){\r
27483             this.on("focus", this.preFocus, this);\r
27484             this.el.on('mousedown', function(){\r
27485                 if(!this.hasFocus){\r
27486                     this.el.on('mouseup', function(e){\r
27487                         e.preventDefault();\r
27488                     }, this, {single:true});\r
27489                 }\r
27490             }, this);\r
27491             if(this.emptyText){\r
27492                 this.on('blur', this.postBlur, this);\r
27493                 this.applyEmptyText();\r
27494             }\r
27495         }\r
27496         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){\r
27497             this.el.on("keypress", this.filterKeys, this);\r
27498         }\r
27499         if(this.grow){\r
27500             this.el.on("keyup", this.onKeyUpBuffered,  this, {buffer:50});\r
27501             this.el.on("click", this.autoSize,  this);\r
27502         }\r
27503 \r
27504         if(this.enableKeyEvents){\r
27505             this.el.on("keyup", this.onKeyUp, this);\r
27506             this.el.on("keydown", this.onKeyDown, this);\r
27507             this.el.on("keypress", this.onKeyPress, this);\r
27508         }\r
27509     },\r
27510 \r
27511     processValue : function(value){\r
27512         if(this.stripCharsRe){\r
27513             var newValue = value.replace(this.stripCharsRe, '');\r
27514             if(newValue !== value){\r
27515                 this.setRawValue(newValue);\r
27516                 return newValue;\r
27517             }\r
27518         }\r
27519         return value;\r
27520     },\r
27521 \r
27522     filterValidation : function(e){\r
27523         if(!e.isNavKeyPress()){\r
27524             this.validationTask.delay(this.validationDelay);\r
27525         }\r
27526     },\r
27527     \r
27528     //private\r
27529     onDisable: function(){\r
27530         Ext.form.TextField.superclass.onDisable.call(this);\r
27531         if(Ext.isIE){\r
27532             this.el.dom.unselectable = 'on';\r
27533         }\r
27534     },\r
27535     \r
27536     //private\r
27537     onEnable: function(){\r
27538         Ext.form.TextField.superclass.onEnable.call(this);\r
27539         if(Ext.isIE){\r
27540             this.el.dom.unselectable = '';\r
27541         }\r
27542     },\r
27543 \r
27544     // private\r
27545     onKeyUpBuffered : function(e){\r
27546         if(!e.isNavKeyPress()){\r
27547             this.autoSize();\r
27548         }\r
27549     },\r
27550 \r
27551     // private\r
27552     onKeyUp : function(e){\r
27553         this.fireEvent('keyup', this, e);\r
27554     },\r
27555 \r
27556     // private\r
27557     onKeyDown : function(e){\r
27558         this.fireEvent('keydown', this, e);\r
27559     },\r
27560 \r
27561     // private\r
27562     onKeyPress : function(e){\r
27563         this.fireEvent('keypress', this, e);\r
27564     },\r
27565 \r
27566     \r
27567     reset : function(){\r
27568         Ext.form.TextField.superclass.reset.call(this);\r
27569         this.applyEmptyText();\r
27570     },\r
27571 \r
27572     applyEmptyText : function(){\r
27573         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){\r
27574             this.setRawValue(this.emptyText);\r
27575             this.el.addClass(this.emptyClass);\r
27576         }\r
27577     },\r
27578 \r
27579     // private\r
27580     preFocus : function(){\r
27581         if(this.emptyText){\r
27582             if(this.el.dom.value == this.emptyText){\r
27583                 this.setRawValue('');\r
27584             }\r
27585             this.el.removeClass(this.emptyClass);\r
27586         }\r
27587         if(this.selectOnFocus){\r
27588             this.el.dom.select();\r
27589         }\r
27590     },\r
27591 \r
27592     // private\r
27593     postBlur : function(){\r
27594         this.applyEmptyText();\r
27595     },\r
27596 \r
27597     // private\r
27598     filterKeys : function(e){\r
27599         if(e.ctrlKey){\r
27600             return;\r
27601         }\r
27602         var k = e.getKey();\r
27603         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){\r
27604             return;\r
27605         }\r
27606         var c = e.getCharCode(), cc = String.fromCharCode(c);\r
27607         if(!Ext.isGecko && e.isSpecialKey() && !cc){\r
27608             return;\r
27609         }\r
27610         if(!this.maskRe.test(cc)){\r
27611             e.stopEvent();\r
27612         }\r
27613     },\r
27614 \r
27615     setValue : function(v){\r
27616         if(this.emptyText && this.el && v !== undefined && v !== null && v !== ''){\r
27617             this.el.removeClass(this.emptyClass);\r
27618         }\r
27619         Ext.form.TextField.superclass.setValue.apply(this, arguments);\r
27620         this.applyEmptyText();\r
27621         this.autoSize();\r
27622     },\r
27623 \r
27624     \r
27625     validateValue : function(value){\r
27626         if(value.length < 1 || value === this.emptyText){ // if it's blank\r
27627              if(this.allowBlank){\r
27628                  this.clearInvalid();\r
27629                  return true;\r
27630              }else{\r
27631                  this.markInvalid(this.blankText);\r
27632                  return false;\r
27633              }\r
27634         }\r
27635         if(value.length < this.minLength){\r
27636             this.markInvalid(String.format(this.minLengthText, this.minLength));\r
27637             return false;\r
27638         }\r
27639         if(value.length > this.maxLength){\r
27640             this.markInvalid(String.format(this.maxLengthText, this.maxLength));\r
27641             return false;\r
27642         }\r
27643         if(this.vtype){\r
27644             var vt = Ext.form.VTypes;\r
27645             if(!vt[this.vtype](value, this)){\r
27646                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);\r
27647                 return false;\r
27648             }\r
27649         }\r
27650         if(typeof this.validator == "function"){\r
27651             var msg = this.validator(value);\r
27652             if(msg !== true){\r
27653                 this.markInvalid(msg);\r
27654                 return false;\r
27655             }\r
27656         }\r
27657         if(this.regex && !this.regex.test(value)){\r
27658             this.markInvalid(this.regexText);\r
27659             return false;\r
27660         }\r
27661         return true;\r
27662     },\r
27663 \r
27664     \r
27665     selectText : function(start, end){\r
27666         var v = this.getRawValue();\r
27667         var doFocus = false;\r
27668         if(v.length > 0){\r
27669             start = start === undefined ? 0 : start;\r
27670             end = end === undefined ? v.length : end;\r
27671             var d = this.el.dom;\r
27672             if(d.setSelectionRange){\r
27673                 d.setSelectionRange(start, end);\r
27674             }else if(d.createTextRange){\r
27675                 var range = d.createTextRange();\r
27676                 range.moveStart("character", start);\r
27677                 range.moveEnd("character", end-v.length);\r
27678                 range.select();\r
27679             }\r
27680             doFocus = Ext.isGecko || Ext.isOpera;\r
27681         }else{\r
27682             doFocus = true;\r
27683         }\r
27684         if(doFocus){\r
27685             this.focus();\r
27686         }\r
27687     },\r
27688 \r
27689     \r
27690     autoSize : function(){\r
27691         if(!this.grow || !this.rendered){\r
27692             return;\r
27693         }\r
27694         if(!this.metrics){\r
27695             this.metrics = Ext.util.TextMetrics.createInstance(this.el);\r
27696         }\r
27697         var el = this.el;\r
27698         var v = el.dom.value;\r
27699         var d = document.createElement('div');\r
27700         d.appendChild(document.createTextNode(v));\r
27701         v = d.innerHTML;\r
27702         Ext.removeNode(d);\r
27703         d = null;\r
27704         v += "&#160;";\r
27705         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));\r
27706         this.el.setWidth(w);\r
27707         this.fireEvent("autosize", this, w);\r
27708     }\r
27709 });\r
27710 Ext.reg('textfield', Ext.form.TextField);\r
27711 \r
27712 \r
27713 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {\r
27714     \r
27715     \r
27716     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},\r
27717     \r
27718     hideTrigger:false,\r
27719 \r
27720     \r
27721     autoSize: Ext.emptyFn,\r
27722     // private\r
27723     monitorTab : true,\r
27724     // private\r
27725     deferHeight : true,\r
27726     // private\r
27727     mimicing : false,\r
27728 \r
27729     // private\r
27730     onResize : function(w, h){\r
27731         Ext.form.TriggerField.superclass.onResize.call(this, w, h);\r
27732         if(typeof w == 'number'){\r
27733             this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));\r
27734         }\r
27735         this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());\r
27736     },\r
27737 \r
27738     // private\r
27739     adjustSize : Ext.BoxComponent.prototype.adjustSize,\r
27740 \r
27741     // private\r
27742     getResizeEl : function(){\r
27743         return this.wrap;\r
27744     },\r
27745 \r
27746     // private\r
27747     getPositionEl : function(){\r
27748         return this.wrap;\r
27749     },\r
27750 \r
27751     // private\r
27752     alignErrorIcon : function(){\r
27753         if(this.wrap){\r
27754             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);\r
27755         }\r
27756     },\r
27757 \r
27758     // private\r
27759     onRender : function(ct, position){\r
27760         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);\r
27761         this.wrap = this.el.wrap({cls: "x-form-field-wrap"});\r
27762         this.trigger = this.wrap.createChild(this.triggerConfig ||\r
27763                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});\r
27764         if(this.hideTrigger){\r
27765             this.trigger.setDisplayed(false);\r
27766         }\r
27767         this.initTrigger();\r
27768         if(!this.width){\r
27769             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());\r
27770         }\r
27771     },\r
27772 \r
27773     afterRender : function(){\r
27774         Ext.form.TriggerField.superclass.afterRender.call(this);\r
27775         var y;\r
27776         if(Ext.isIE && !this.hideTrigger && this.el.getY() != (y = this.trigger.getY())){\r
27777             this.el.position();\r
27778             this.el.setY(y);\r
27779         }\r
27780     },\r
27781 \r
27782     // private\r
27783     initTrigger : function(){\r
27784         this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});\r
27785         this.trigger.addClassOnOver('x-form-trigger-over');\r
27786         this.trigger.addClassOnClick('x-form-trigger-click');\r
27787     },\r
27788 \r
27789     // private\r
27790     onDestroy : function(){\r
27791         if(this.trigger){\r
27792             this.trigger.removeAllListeners();\r
27793             this.trigger.remove();\r
27794         }\r
27795         if(this.wrap){\r
27796             this.wrap.remove();\r
27797         }\r
27798         Ext.form.TriggerField.superclass.onDestroy.call(this);\r
27799     },\r
27800 \r
27801     // private\r
27802     onFocus : function(){\r
27803         Ext.form.TriggerField.superclass.onFocus.call(this);\r
27804         if(!this.mimicing){\r
27805             this.wrap.addClass('x-trigger-wrap-focus');\r
27806             this.mimicing = true;\r
27807             Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {delay: 10});\r
27808             if(this.monitorTab){\r
27809                 this.el.on("keydown", this.checkTab, this);\r
27810             }\r
27811         }\r
27812     },\r
27813 \r
27814     // private\r
27815     checkTab : function(e){\r
27816         if(e.getKey() == e.TAB){\r
27817             this.triggerBlur();\r
27818         }\r
27819     },\r
27820 \r
27821     // private\r
27822     onBlur : function(){\r
27823         // do nothing\r
27824     },\r
27825 \r
27826     // private\r
27827     mimicBlur : function(e){\r
27828         if(!this.wrap.contains(e.target) && this.validateBlur(e)){\r
27829             this.triggerBlur();\r
27830         }\r
27831     },\r
27832 \r
27833     // private\r
27834     triggerBlur : function(){\r
27835         this.mimicing = false;\r
27836         Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);\r
27837         if(this.monitorTab && this.el){\r
27838             this.el.un("keydown", this.checkTab, this);\r
27839         }\r
27840         this.beforeBlur();\r
27841         if(this.wrap){\r
27842             this.wrap.removeClass('x-trigger-wrap-focus');\r
27843         }\r
27844         Ext.form.TriggerField.superclass.onBlur.call(this);\r
27845     },\r
27846 \r
27847     beforeBlur : Ext.emptyFn, \r
27848 \r
27849     // private\r
27850     // This should be overriden by any subclass that needs to check whether or not the field can be blurred.\r
27851     validateBlur : function(e){\r
27852         return true;\r
27853     },\r
27854 \r
27855     // private\r
27856     onDisable : function(){\r
27857         Ext.form.TriggerField.superclass.onDisable.call(this);\r
27858         if(this.wrap){\r
27859             this.wrap.addClass(this.disabledClass);\r
27860             this.el.removeClass(this.disabledClass);\r
27861         }\r
27862     },\r
27863 \r
27864     // private\r
27865     onEnable : function(){\r
27866         Ext.form.TriggerField.superclass.onEnable.call(this);\r
27867         if(this.wrap){\r
27868             this.wrap.removeClass(this.disabledClass);\r
27869         }\r
27870     },\r
27871 \r
27872     // private\r
27873     onShow : function(){\r
27874         if(this.wrap){\r
27875             this.wrap.dom.style.display = '';\r
27876             this.wrap.dom.style.visibility = 'visible';\r
27877         }\r
27878     },\r
27879 \r
27880     // private\r
27881     onHide : function(){\r
27882         this.wrap.dom.style.display = 'none';\r
27883     },\r
27884 \r
27885     \r
27886     onTriggerClick : Ext.emptyFn\r
27887 \r
27888     \r
27889     \r
27890     \r
27891 });\r
27892 \r
27893 // TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class\r
27894 // to be extended by an implementing class.  For an example of implementing this class, see the custom\r
27895 // SearchField implementation here: http://extjs.com/deploy/ext/examples/form/custom.html\r
27896 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {\r
27897     initComponent : function(){\r
27898         Ext.form.TwinTriggerField.superclass.initComponent.call(this);\r
27899 \r
27900         this.triggerConfig = {\r
27901             tag:'span', cls:'x-form-twin-triggers', cn:[\r
27902             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},\r
27903             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}\r
27904         ]};\r
27905     },\r
27906 \r
27907     getTrigger : function(index){\r
27908         return this.triggers[index];\r
27909     },\r
27910 \r
27911     initTrigger : function(){\r
27912         var ts = this.trigger.select('.x-form-trigger', true);\r
27913         this.wrap.setStyle('overflow', 'hidden');\r
27914         var triggerField = this;\r
27915         ts.each(function(t, all, index){\r
27916             t.hide = function(){\r
27917                 var w = triggerField.wrap.getWidth();\r
27918                 this.dom.style.display = 'none';\r
27919                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
27920             };\r
27921             t.show = function(){\r
27922                 var w = triggerField.wrap.getWidth();\r
27923                 this.dom.style.display = '';\r
27924                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
27925             };\r
27926             var triggerIndex = 'Trigger'+(index+1);\r
27927 \r
27928             if(this['hide'+triggerIndex]){\r
27929                 t.dom.style.display = 'none';\r
27930             }\r
27931             t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});\r
27932             t.addClassOnOver('x-form-trigger-over');\r
27933             t.addClassOnClick('x-form-trigger-click');\r
27934         }, this);\r
27935         this.triggers = ts.elements;\r
27936     },\r
27937 \r
27938     onTrigger1Click : Ext.emptyFn,\r
27939     onTrigger2Click : Ext.emptyFn\r
27940 });\r
27941 Ext.reg('trigger', Ext.form.TriggerField);\r
27942 \r
27943 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {\r
27944     \r
27945     growMin : 60,\r
27946     \r
27947     growMax: 1000,\r
27948     growAppend : '&#160;\n&#160;',\r
27949     growPad : 0,\r
27950 \r
27951     enterIsSpecial : false,\r
27952 \r
27953     \r
27954     preventScrollbars: false,\r
27955     \r
27956 \r
27957     // private\r
27958     onRender : function(ct, position){\r
27959         if(!this.el){\r
27960             this.defaultAutoCreate = {\r
27961                 tag: "textarea",\r
27962                 style:"width:100px;height:60px;",\r
27963                 autocomplete: "off"\r
27964             };\r
27965         }\r
27966         Ext.form.TextArea.superclass.onRender.call(this, ct, position);\r
27967         if(this.grow){\r
27968             this.textSizeEl = Ext.DomHelper.append(document.body, {\r
27969                 tag: "pre", cls: "x-form-grow-sizer"\r
27970             });\r
27971             if(this.preventScrollbars){\r
27972                 this.el.setStyle("overflow", "hidden");\r
27973             }\r
27974             this.el.setHeight(this.growMin);\r
27975         }\r
27976     },\r
27977 \r
27978     onDestroy : function(){\r
27979         if(this.textSizeEl){\r
27980             Ext.removeNode(this.textSizeEl);\r
27981         }\r
27982         Ext.form.TextArea.superclass.onDestroy.call(this);\r
27983     },\r
27984 \r
27985     fireKey : function(e){\r
27986         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){\r
27987             this.fireEvent("specialkey", this, e);\r
27988         }\r
27989     },\r
27990 \r
27991     // private\r
27992     onKeyUp : function(e){\r
27993         if(!e.isNavKeyPress() || e.getKey() == e.ENTER){\r
27994             this.autoSize();\r
27995         }\r
27996         Ext.form.TextArea.superclass.onKeyUp.call(this, e);\r
27997     },\r
27998 \r
27999     \r
28000     autoSize : function(){\r
28001         if(!this.grow || !this.textSizeEl){\r
28002             return;\r
28003         }\r
28004         var el = this.el;\r
28005         var v = el.dom.value;\r
28006         var ts = this.textSizeEl;\r
28007         ts.innerHTML = '';\r
28008         ts.appendChild(document.createTextNode(v));\r
28009         v = ts.innerHTML;\r
28010 \r
28011         Ext.fly(ts).setWidth(this.el.getWidth());\r
28012         if(v.length < 1){\r
28013             v = "&#160;&#160;";\r
28014         }else{\r
28015             if(Ext.isIE){\r
28016                 v = v.replace(/\n/g, '<p>&#160;</p>');\r
28017             }\r
28018             v += this.growAppend;\r
28019         }\r
28020         ts.innerHTML = v;\r
28021         var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin)+this.growPad);\r
28022         if(h != this.lastHeight){\r
28023             this.lastHeight = h;\r
28024             this.el.setHeight(h);\r
28025             this.fireEvent("autosize", this, h);\r
28026         }\r
28027     }\r
28028 });\r
28029 Ext.reg('textarea', Ext.form.TextArea);\r
28030 \r
28031 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {\r
28032     \r
28033     \r
28034     fieldClass: "x-form-field x-form-num-field",\r
28035     \r
28036     allowDecimals : true,\r
28037     \r
28038     decimalSeparator : ".",\r
28039     \r
28040     decimalPrecision : 2,\r
28041     \r
28042     allowNegative : true,\r
28043     \r
28044     minValue : Number.NEGATIVE_INFINITY,\r
28045     \r
28046     maxValue : Number.MAX_VALUE,\r
28047     \r
28048     minText : "The minimum value for this field is {0}",\r
28049     \r
28050     maxText : "The maximum value for this field is {0}",\r
28051     \r
28052     nanText : "{0} is not a valid number",\r
28053     \r
28054     baseChars : "0123456789",\r
28055 \r
28056     // private\r
28057     initEvents : function(){\r
28058         Ext.form.NumberField.superclass.initEvents.call(this);\r
28059         var allowed = this.baseChars+'';\r
28060         if(this.allowDecimals){\r
28061             allowed += this.decimalSeparator;\r
28062         }\r
28063         if(this.allowNegative){\r
28064             allowed += "-";\r
28065         }\r
28066         this.stripCharsRe = new RegExp('[^'+allowed+']', 'gi');\r
28067         var keyPress = function(e){\r
28068             var k = e.getKey();\r
28069             if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){\r
28070                 return;\r
28071             }\r
28072             var c = e.getCharCode();\r
28073             if(allowed.indexOf(String.fromCharCode(c)) === -1){\r
28074                 e.stopEvent();\r
28075             }\r
28076         };\r
28077         this.el.on("keypress", keyPress, this);\r
28078     },\r
28079 \r
28080     // private\r
28081     validateValue : function(value){\r
28082         if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){\r
28083             return false;\r
28084         }\r
28085         if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid\r
28086              return true;\r
28087         }\r
28088         value = String(value).replace(this.decimalSeparator, ".");\r
28089         if(isNaN(value)){\r
28090             this.markInvalid(String.format(this.nanText, value));\r
28091             return false;\r
28092         }\r
28093         var num = this.parseValue(value);\r
28094         if(num < this.minValue){\r
28095             this.markInvalid(String.format(this.minText, this.minValue));\r
28096             return false;\r
28097         }\r
28098         if(num > this.maxValue){\r
28099             this.markInvalid(String.format(this.maxText, this.maxValue));\r
28100             return false;\r
28101         }\r
28102         return true;\r
28103     },\r
28104 \r
28105     getValue : function(){\r
28106         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));\r
28107     },\r
28108 \r
28109     setValue : function(v){\r
28110         v = typeof v == 'number' ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));\r
28111         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);\r
28112         Ext.form.NumberField.superclass.setValue.call(this, v);\r
28113     },\r
28114 \r
28115     // private\r
28116     parseValue : function(value){\r
28117         value = parseFloat(String(value).replace(this.decimalSeparator, "."));\r
28118         return isNaN(value) ? '' : value;\r
28119     },\r
28120 \r
28121     // private\r
28122     fixPrecision : function(value){\r
28123         var nan = isNaN(value);\r
28124         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){\r
28125            return nan ? '' : value;\r
28126         }\r
28127         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));\r
28128     },\r
28129 \r
28130     beforeBlur : function(){\r
28131         var v = this.parseValue(this.getRawValue());\r
28132         if(v || v === 0){\r
28133             this.setValue(this.fixPrecision(v));\r
28134         }\r
28135     }\r
28136 });\r
28137 Ext.reg('numberfield', Ext.form.NumberField);\r
28138 \r
28139 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {\r
28140     \r
28141     format : "m/d/Y",\r
28142     \r
28143     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",\r
28144     \r
28145     disabledDaysText : "Disabled",\r
28146     \r
28147     disabledDatesText : "Disabled",\r
28148     \r
28149     minText : "The date in this field must be equal to or after {0}",\r
28150     \r
28151     maxText : "The date in this field must be equal to or before {0}",\r
28152     \r
28153     invalidText : "{0} is not a valid date - it must be in the format {1}",\r
28154     \r
28155     triggerClass : 'x-form-date-trigger',\r
28156     \r
28157     showToday : true,\r
28158     \r
28159     \r
28160     \r
28161     \r
28162     \r
28163 \r
28164     // private\r
28165     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},\r
28166 \r
28167     initComponent : function(){\r
28168         Ext.form.DateField.superclass.initComponent.call(this);\r
28169         \r
28170         this.addEvents(\r
28171             \r
28172             'select'\r
28173         );\r
28174         \r
28175         if(typeof this.minValue == "string"){\r
28176             this.minValue = this.parseDate(this.minValue);\r
28177         }\r
28178         if(typeof this.maxValue == "string"){\r
28179             this.maxValue = this.parseDate(this.maxValue);\r
28180         }\r
28181         this.disabledDatesRE = null;\r
28182         this.initDisabledDays();\r
28183     },\r
28184 \r
28185     // private\r
28186     initDisabledDays : function(){\r
28187         if(this.disabledDates){\r
28188             var dd = this.disabledDates;\r
28189             var re = "(?:";\r
28190             for(var i = 0; i < dd.length; i++){\r
28191                 re += dd[i];\r
28192                 if(i != dd.length-1) re += "|";\r
28193             }\r
28194             this.disabledDatesRE = new RegExp(re + ")");\r
28195         }\r
28196     },\r
28197 \r
28198     \r
28199     setDisabledDates : function(dd){\r
28200         this.disabledDates = dd;\r
28201         this.initDisabledDays();\r
28202         if(this.menu){\r
28203             this.menu.picker.setDisabledDates(this.disabledDatesRE);\r
28204         }\r
28205     },\r
28206 \r
28207     \r
28208     setDisabledDays : function(dd){\r
28209         this.disabledDays = dd;\r
28210         if(this.menu){\r
28211             this.menu.picker.setDisabledDays(dd);\r
28212         }\r
28213     },\r
28214 \r
28215     \r
28216     setMinValue : function(dt){\r
28217         this.minValue = (typeof dt == "string" ? this.parseDate(dt) : dt);\r
28218         if(this.menu){\r
28219             this.menu.picker.setMinDate(this.minValue);\r
28220         }\r
28221     },\r
28222 \r
28223     \r
28224     setMaxValue : function(dt){\r
28225         this.maxValue = (typeof dt == "string" ? this.parseDate(dt) : dt);\r
28226         if(this.menu){\r
28227             this.menu.picker.setMaxDate(this.maxValue);\r
28228         }\r
28229     },\r
28230 \r
28231     // private\r
28232     validateValue : function(value){\r
28233         value = this.formatDate(value);\r
28234         if(!Ext.form.DateField.superclass.validateValue.call(this, value)){\r
28235             return false;\r
28236         }\r
28237         if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid\r
28238              return true;\r
28239         }\r
28240         var svalue = value;\r
28241         value = this.parseDate(value);\r
28242         if(!value){\r
28243             this.markInvalid(String.format(this.invalidText, svalue, this.format));\r
28244             return false;\r
28245         }\r
28246         var time = value.getTime();\r
28247         if(this.minValue && time < this.minValue.getTime()){\r
28248             this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));\r
28249             return false;\r
28250         }\r
28251         if(this.maxValue && time > this.maxValue.getTime()){\r
28252             this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));\r
28253             return false;\r
28254         }\r
28255         if(this.disabledDays){\r
28256             var day = value.getDay();\r
28257             for(var i = 0; i < this.disabledDays.length; i++) {\r
28258                 if(day === this.disabledDays[i]){\r
28259                     this.markInvalid(this.disabledDaysText);\r
28260                     return false;\r
28261                 }\r
28262             }\r
28263         }\r
28264         var fvalue = this.formatDate(value);\r
28265         if(this.disabledDatesRE && this.disabledDatesRE.test(fvalue)){\r
28266             this.markInvalid(String.format(this.disabledDatesText, fvalue));\r
28267             return false;\r
28268         }\r
28269         return true;\r
28270     },\r
28271 \r
28272     // private\r
28273     // Provides logic to override the default TriggerField.validateBlur which just returns true\r
28274     validateBlur : function(){\r
28275         return !this.menu || !this.menu.isVisible();\r
28276     },\r
28277 \r
28278     \r
28279     getValue : function(){\r
28280         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";\r
28281     },\r
28282 \r
28283     \r
28284     setValue : function(date){\r
28285         Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));\r
28286     },\r
28287 \r
28288     // private\r
28289     parseDate : function(value){\r
28290         if(!value || Ext.isDate(value)){\r
28291             return value;\r
28292         }\r
28293         var v = Date.parseDate(value, this.format);\r
28294         if(!v && this.altFormats){\r
28295             if(!this.altFormatsArray){\r
28296                 this.altFormatsArray = this.altFormats.split("|");\r
28297             }\r
28298             for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){\r
28299                 v = Date.parseDate(value, this.altFormatsArray[i]);\r
28300             }\r
28301         }\r
28302         return v;\r
28303     },\r
28304 \r
28305     // private\r
28306     onDestroy : function(){\r
28307         if(this.menu) {\r
28308             this.menu.destroy();\r
28309         }\r
28310         if(this.wrap){\r
28311             this.wrap.remove();\r
28312         }\r
28313         Ext.form.DateField.superclass.onDestroy.call(this);\r
28314     },\r
28315 \r
28316     // private\r
28317     formatDate : function(date){\r
28318         return Ext.isDate(date) ? date.dateFormat(this.format) : date;\r
28319     },\r
28320 \r
28321     // private\r
28322     menuListeners : {\r
28323         select: function(m, d){\r
28324             this.setValue(d);\r
28325             this.fireEvent('select', this, d);\r
28326         },\r
28327         show : function(){ // retain focus styling\r
28328             this.onFocus();\r
28329         },\r
28330         hide : function(){\r
28331             this.focus.defer(10, this);\r
28332             var ml = this.menuListeners;\r
28333             this.menu.un("select", ml.select,  this);\r
28334             this.menu.un("show", ml.show,  this);\r
28335             this.menu.un("hide", ml.hide,  this);\r
28336         }\r
28337     },\r
28338 \r
28339     \r
28340     // private\r
28341     // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker\r
28342     onTriggerClick : function(){\r
28343         if(this.disabled){\r
28344             return;\r
28345         }\r
28346         if(this.menu == null){\r
28347             this.menu = new Ext.menu.DateMenu();\r
28348         }\r
28349         Ext.apply(this.menu.picker,  {\r
28350             minDate : this.minValue,\r
28351             maxDate : this.maxValue,\r
28352             disabledDatesRE : this.disabledDatesRE,\r
28353             disabledDatesText : this.disabledDatesText,\r
28354             disabledDays : this.disabledDays,\r
28355             disabledDaysText : this.disabledDaysText,\r
28356             format : this.format,\r
28357             showToday : this.showToday,\r
28358             minText : String.format(this.minText, this.formatDate(this.minValue)),\r
28359             maxText : String.format(this.maxText, this.formatDate(this.maxValue))\r
28360         });\r
28361         this.menu.on(Ext.apply({}, this.menuListeners, {\r
28362             scope:this\r
28363         }));\r
28364         this.menu.picker.setValue(this.getValue() || new Date());\r
28365         this.menu.show(this.el, "tl-bl?");\r
28366     },\r
28367 \r
28368     // private\r
28369     beforeBlur : function(){\r
28370         var v = this.parseDate(this.getRawValue());\r
28371         if(v){\r
28372             this.setValue(v);\r
28373         }\r
28374     }\r
28375 \r
28376     \r
28377     \r
28378     \r
28379     \r
28380 });\r
28381 Ext.reg('datefield', Ext.form.DateField);\r
28382 \r
28383 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {\r
28384     \r
28385     \r
28386     \r
28387     \r
28388     \r
28389 \r
28390     // private\r
28391     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},\r
28392     \r
28393     \r
28394     \r
28395     \r
28396     \r
28397     \r
28398     listClass: '',\r
28399     \r
28400     selectedClass: 'x-combo-selected',\r
28401     \r
28402     triggerClass : 'x-form-arrow-trigger',\r
28403     \r
28404     shadow:'sides',\r
28405     \r
28406     listAlign: 'tl-bl?',\r
28407     \r
28408     maxHeight: 300,\r
28409     \r
28410     minHeight: 90,\r
28411     \r
28412     triggerAction: 'query',\r
28413     \r
28414     minChars : 4,\r
28415     \r
28416     typeAhead: false,\r
28417     \r
28418     queryDelay: 500,\r
28419     \r
28420     pageSize: 0,\r
28421     \r
28422     selectOnFocus:false,\r
28423     \r
28424     queryParam: 'query',\r
28425     \r
28426     loadingText: 'Loading...',\r
28427     \r
28428     resizable: false,\r
28429     \r
28430     handleHeight : 8,\r
28431     \r
28432     editable: true,\r
28433     \r
28434     allQuery: '',\r
28435     \r
28436     mode: 'remote',\r
28437     \r
28438     minListWidth : 70,\r
28439     \r
28440     forceSelection:false,\r
28441     \r
28442     typeAheadDelay : 250,\r
28443     \r
28444 \r
28445     \r
28446     lazyInit : true,\r
28447 \r
28448     \r
28449 \r
28450     // private\r
28451     initComponent : function(){\r
28452         Ext.form.ComboBox.superclass.initComponent.call(this);\r
28453         this.addEvents(\r
28454             \r
28455             'expand',\r
28456             \r
28457             'collapse',\r
28458             \r
28459             'beforeselect',\r
28460             \r
28461             'select',\r
28462             \r
28463             'beforequery'\r
28464         );\r
28465         if(this.transform){\r
28466             this.allowDomMove = false;\r
28467             var s = Ext.getDom(this.transform);\r
28468             if(!this.hiddenName){\r
28469                 this.hiddenName = s.name;\r
28470             }\r
28471             if(!this.store){\r
28472                 this.mode = 'local';\r
28473                 var d = [], opts = s.options;\r
28474                 for(var i = 0, len = opts.length;i < len; i++){\r
28475                     var o = opts[i];\r
28476                     var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;\r
28477                     if(o.selected) {\r
28478                         this.value = value;\r
28479                     }\r
28480                     d.push([value, o.text]);\r
28481                 }\r
28482                 this.store = new Ext.data.SimpleStore({\r
28483                     'id': 0,\r
28484                     fields: ['value', 'text'],\r
28485                     data : d\r
28486                 });\r
28487                 this.valueField = 'value';\r
28488                 this.displayField = 'text';\r
28489             }\r
28490             s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference\r
28491             if(!this.lazyRender){\r
28492                 this.target = true;\r
28493                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);\r
28494                 Ext.removeNode(s); // remove it\r
28495                 this.render(this.el.parentNode);\r
28496             }else{\r
28497                 Ext.removeNode(s); // remove it\r
28498             }\r
28499         }\r
28500         //auto-configure store from local array data\r
28501         else if(Ext.isArray(this.store)){\r
28502             if (Ext.isArray(this.store[0])){\r
28503                 this.store = new Ext.data.SimpleStore({\r
28504                     fields: ['value','text'],\r
28505                     data: this.store\r
28506                 });\r
28507                 this.valueField = 'value';\r
28508             }else{\r
28509                 this.store = new Ext.data.SimpleStore({\r
28510                     fields: ['text'],\r
28511                     data: this.store,\r
28512                     expandData: true\r
28513                 });\r
28514                 this.valueField = 'text';\r
28515             }\r
28516             this.displayField = 'text';\r
28517             this.mode = 'local';\r
28518         }\r
28519 \r
28520         this.selectedIndex = -1;\r
28521         if(this.mode == 'local'){\r
28522             if(this.initialConfig.queryDelay === undefined){\r
28523                 this.queryDelay = 10;\r
28524             }\r
28525             if(this.initialConfig.minChars === undefined){\r
28526                 this.minChars = 0;\r
28527             }\r
28528         }\r
28529     },\r
28530 \r
28531     // private\r
28532     onRender : function(ct, position){\r
28533         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);\r
28534         if(this.hiddenName){\r
28535             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,\r
28536                     id: (this.hiddenId||this.hiddenName)}, 'before', true);\r
28537 \r
28538             // prevent input submission\r
28539             this.el.dom.removeAttribute('name');\r
28540         }\r
28541         if(Ext.isGecko){\r
28542             this.el.dom.setAttribute('autocomplete', 'off');\r
28543         }\r
28544 \r
28545         if(!this.lazyInit){\r
28546             this.initList();\r
28547         }else{\r
28548             this.on('focus', this.initList, this, {single: true});\r
28549         }\r
28550 \r
28551         if(!this.editable){\r
28552             this.editable = true;\r
28553             this.setEditable(false);\r
28554         }\r
28555     },\r
28556 \r
28557     // private\r
28558     initValue : function(){\r
28559         Ext.form.ComboBox.superclass.initValue.call(this);\r
28560         if(this.hiddenField){\r
28561             this.hiddenField.value =\r
28562                 this.hiddenValue !== undefined ? this.hiddenValue :\r
28563                 this.value !== undefined ? this.value : '';\r
28564         }\r
28565     },\r
28566 \r
28567     // private\r
28568     initList : function(){\r
28569         if(!this.list){\r
28570             var cls = 'x-combo-list';\r
28571 \r
28572             this.list = new Ext.Layer({\r
28573                 shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false\r
28574             });\r
28575 \r
28576             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);\r
28577             this.list.setWidth(lw);\r
28578             this.list.swallowEvent('mousewheel');\r
28579             this.assetHeight = 0;\r
28580 \r
28581             if(this.title){\r
28582                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});\r
28583                 this.assetHeight += this.header.getHeight();\r
28584             }\r
28585 \r
28586             this.innerList = this.list.createChild({cls:cls+'-inner'});\r
28587             this.innerList.on('mouseover', this.onViewOver, this);\r
28588             this.innerList.on('mousemove', this.onViewMove, this);\r
28589             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
28590 \r
28591             if(this.pageSize){\r
28592                 this.footer = this.list.createChild({cls:cls+'-ft'});\r
28593                 this.pageTb = new Ext.PagingToolbar({\r
28594                     store:this.store,\r
28595                     pageSize: this.pageSize,\r
28596                     renderTo:this.footer\r
28597                 });\r
28598                 this.assetHeight += this.footer.getHeight();\r
28599             }\r
28600 \r
28601             if(!this.tpl){\r
28602                 \r
28603                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';\r
28604                 \r
28605             }\r
28606 \r
28607             \r
28608             this.view = new Ext.DataView({\r
28609                 applyTo: this.innerList,\r
28610                 tpl: this.tpl,\r
28611                 singleSelect: true,\r
28612                 selectedClass: this.selectedClass,\r
28613                 itemSelector: this.itemSelector || '.' + cls + '-item'\r
28614             });\r
28615 \r
28616             this.view.on('click', this.onViewClick, this);\r
28617 \r
28618             this.bindStore(this.store, true);\r
28619 \r
28620             if(this.resizable){\r
28621                 this.resizer = new Ext.Resizable(this.list,  {\r
28622                    pinned:true, handles:'se'\r
28623                 });\r
28624                 this.resizer.on('resize', function(r, w, h){\r
28625                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;\r
28626                     this.listWidth = w;\r
28627                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));\r
28628                     this.restrictHeight();\r
28629                 }, this);\r
28630                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');\r
28631             }\r
28632         }\r
28633     },\r
28634     \r
28635     \r
28636     getStore : function(){\r
28637         return this.store;\r
28638     },\r
28639 \r
28640     // private\r
28641     bindStore : function(store, initial){\r
28642         if(this.store && !initial){\r
28643             this.store.un('beforeload', this.onBeforeLoad, this);\r
28644             this.store.un('load', this.onLoad, this);\r
28645             this.store.un('loadexception', this.collapse, this);\r
28646             if(!store){\r
28647                 this.store = null;\r
28648                 if(this.view){\r
28649                     this.view.setStore(null);\r
28650                 }\r
28651             }\r
28652         }\r
28653         if(store){\r
28654             this.store = Ext.StoreMgr.lookup(store);\r
28655 \r
28656             this.store.on('beforeload', this.onBeforeLoad, this);\r
28657             this.store.on('load', this.onLoad, this);\r
28658             this.store.on('loadexception', this.collapse, this);\r
28659 \r
28660             if(this.view){\r
28661                 this.view.setStore(store);\r
28662             }\r
28663         }\r
28664     },\r
28665 \r
28666     // private\r
28667     initEvents : function(){\r
28668         Ext.form.ComboBox.superclass.initEvents.call(this);\r
28669 \r
28670         this.keyNav = new Ext.KeyNav(this.el, {\r
28671             "up" : function(e){\r
28672                 this.inKeyMode = true;\r
28673                 this.selectPrev();\r
28674             },\r
28675 \r
28676             "down" : function(e){\r
28677                 if(!this.isExpanded()){\r
28678                     this.onTriggerClick();\r
28679                 }else{\r
28680                     this.inKeyMode = true;\r
28681                     this.selectNext();\r
28682                 }\r
28683             },\r
28684 \r
28685             "enter" : function(e){\r
28686                 this.onViewClick();\r
28687                 this.delayedCheck = true;\r
28688                 this.unsetDelayCheck.defer(10, this);\r
28689             },\r
28690 \r
28691             "esc" : function(e){\r
28692                 this.collapse();\r
28693             },\r
28694 \r
28695             "tab" : function(e){\r
28696                 this.onViewClick(false);\r
28697                 return true;\r
28698             },\r
28699 \r
28700             scope : this,\r
28701 \r
28702             doRelay : function(foo, bar, hname){\r
28703                 if(hname == 'down' || this.scope.isExpanded()){\r
28704                    return Ext.KeyNav.prototype.doRelay.apply(this, arguments);\r
28705                 }\r
28706                 return true;\r
28707             },\r
28708 \r
28709             forceKeyDown : true\r
28710         });\r
28711         this.queryDelay = Math.max(this.queryDelay || 10,\r
28712                 this.mode == 'local' ? 10 : 250);\r
28713         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);\r
28714         if(this.typeAhead){\r
28715             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);\r
28716         }\r
28717         if(this.editable !== false){\r
28718             this.el.on("keyup", this.onKeyUp, this);\r
28719         }\r
28720         if(this.forceSelection){\r
28721             this.on('blur', this.doForce, this);\r
28722         }\r
28723     },\r
28724 \r
28725     // private\r
28726     onDestroy : function(){\r
28727         if(this.view){\r
28728             Ext.destroy(this.view);\r
28729         }\r
28730         if(this.list){\r
28731             if(this.innerList){\r
28732                 this.innerList.un('mouseover', this.onViewOver, this);\r
28733                 this.innerList.un('mousemove', this.onViewMove, this);\r
28734             }\r
28735             this.list.destroy();\r
28736         }\r
28737         if (this.dqTask){\r
28738             this.dqTask.cancel();\r
28739             this.dqTask = null;\r
28740         }\r
28741         this.bindStore(null);\r
28742         Ext.form.ComboBox.superclass.onDestroy.call(this);\r
28743     },\r
28744 \r
28745     // private\r
28746     unsetDelayCheck : function(){\r
28747         delete this.delayedCheck;\r
28748     },\r
28749 \r
28750     // private\r
28751     fireKey : function(e){\r
28752         if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){\r
28753             this.fireEvent("specialkey", this, e);\r
28754         }\r
28755     },\r
28756 \r
28757     // private\r
28758     onResize: function(w, h){\r
28759         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);\r
28760         if(this.list && this.listWidth === undefined){\r
28761             var lw = Math.max(w, this.minListWidth);\r
28762             this.list.setWidth(lw);\r
28763             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
28764         }\r
28765     },\r
28766 \r
28767     // private\r
28768     onEnable: function(){\r
28769         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);\r
28770         if(this.hiddenField){\r
28771             this.hiddenField.disabled = false;\r
28772         }\r
28773     },\r
28774 \r
28775     // private\r
28776     onDisable: function(){\r
28777         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);\r
28778         if(this.hiddenField){\r
28779             this.hiddenField.disabled = true;\r
28780         }\r
28781     },\r
28782 \r
28783     \r
28784     setEditable : function(value){\r
28785         if(value == this.editable){\r
28786             return;\r
28787         }\r
28788         this.editable = value;\r
28789         if(!value){\r
28790             this.el.dom.setAttribute('readOnly', true);\r
28791             this.el.on('mousedown', this.onTriggerClick,  this);\r
28792             this.el.addClass('x-combo-noedit');\r
28793         }else{\r
28794             this.el.dom.removeAttribute('readOnly');\r
28795             this.el.un('mousedown', this.onTriggerClick,  this);\r
28796             this.el.removeClass('x-combo-noedit');\r
28797         }\r
28798     },\r
28799 \r
28800     // private\r
28801     onBeforeLoad : function(){\r
28802         if(!this.hasFocus){\r
28803             return;\r
28804         }\r
28805         this.innerList.update(this.loadingText ?\r
28806                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');\r
28807         this.restrictHeight();\r
28808         this.selectedIndex = -1;\r
28809     },\r
28810 \r
28811     // private\r
28812     onLoad : function(){\r
28813         if(!this.hasFocus){\r
28814             return;\r
28815         }\r
28816         if(this.store.getCount() > 0){\r
28817             this.expand();\r
28818             this.restrictHeight();\r
28819             if(this.lastQuery == this.allQuery){\r
28820                 if(this.editable){\r
28821                     this.el.dom.select();\r
28822                 }\r
28823                 if(!this.selectByValue(this.value, true)){\r
28824                     this.select(0, true);\r
28825                 }\r
28826             }else{\r
28827                 this.selectNext();\r
28828                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){\r
28829                     this.taTask.delay(this.typeAheadDelay);\r
28830                 }\r
28831             }\r
28832         }else{\r
28833             this.onEmptyResults();\r
28834         }\r
28835         //this.el.focus();\r
28836     },\r
28837 \r
28838     // private\r
28839     onTypeAhead : function(){\r
28840         if(this.store.getCount() > 0){\r
28841             var r = this.store.getAt(0);\r
28842             var newValue = r.data[this.displayField];\r
28843             var len = newValue.length;\r
28844             var selStart = this.getRawValue().length;\r
28845             if(selStart != len){\r
28846                 this.setRawValue(newValue);\r
28847                 this.selectText(selStart, newValue.length);\r
28848             }\r
28849         }\r
28850     },\r
28851 \r
28852     // private\r
28853     onSelect : function(record, index){\r
28854         if(this.fireEvent('beforeselect', this, record, index) !== false){\r
28855             this.setValue(record.data[this.valueField || this.displayField]);\r
28856             this.collapse();\r
28857             this.fireEvent('select', this, record, index);\r
28858         }\r
28859     },\r
28860 \r
28861     \r
28862     getValue : function(){\r
28863         if(this.valueField){\r
28864             return typeof this.value != 'undefined' ? this.value : '';\r
28865         }else{\r
28866             return Ext.form.ComboBox.superclass.getValue.call(this);\r
28867         }\r
28868     },\r
28869 \r
28870     \r
28871     clearValue : function(){\r
28872         if(this.hiddenField){\r
28873             this.hiddenField.value = '';\r
28874         }\r
28875         this.setRawValue('');\r
28876         this.lastSelectionText = '';\r
28877         this.applyEmptyText();\r
28878         this.value = '';\r
28879     },\r
28880 \r
28881     \r
28882     setValue : function(v){\r
28883         var text = v;\r
28884         if(this.valueField){\r
28885             var r = this.findRecord(this.valueField, v);\r
28886             if(r){\r
28887                 text = r.data[this.displayField];\r
28888             }else if(this.valueNotFoundText !== undefined){\r
28889                 text = this.valueNotFoundText;\r
28890             }\r
28891         }\r
28892         this.lastSelectionText = text;\r
28893         if(this.hiddenField){\r
28894             this.hiddenField.value = v;\r
28895         }\r
28896         Ext.form.ComboBox.superclass.setValue.call(this, text);\r
28897         this.value = v;\r
28898     },\r
28899 \r
28900     // private\r
28901     findRecord : function(prop, value){\r
28902         var record;\r
28903         if(this.store.getCount() > 0){\r
28904             this.store.each(function(r){\r
28905                 if(r.data[prop] == value){\r
28906                     record = r;\r
28907                     return false;\r
28908                 }\r
28909             });\r
28910         }\r
28911         return record;\r
28912     },\r
28913 \r
28914     // private\r
28915     onViewMove : function(e, t){\r
28916         this.inKeyMode = false;\r
28917     },\r
28918 \r
28919     // private\r
28920     onViewOver : function(e, t){\r
28921         if(this.inKeyMode){ // prevent key nav and mouse over conflicts\r
28922             return;\r
28923         }\r
28924         var item = this.view.findItemFromChild(t);\r
28925         if(item){\r
28926             var index = this.view.indexOf(item);\r
28927             this.select(index, false);\r
28928         }\r
28929     },\r
28930 \r
28931     // private\r
28932     onViewClick : function(doFocus){\r
28933         var index = this.view.getSelectedIndexes()[0];\r
28934         var r = this.store.getAt(index);\r
28935         if(r){\r
28936             this.onSelect(r, index);\r
28937         }\r
28938         if(doFocus !== false){\r
28939             this.el.focus();\r
28940         }\r
28941     },\r
28942 \r
28943     // private\r
28944     restrictHeight : function(){\r
28945         this.innerList.dom.style.height = '';\r
28946         var inner = this.innerList.dom;\r
28947         var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;\r
28948         var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);\r
28949         var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;\r
28950         var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;\r
28951         var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;\r
28952         h = Math.min(h, space, this.maxHeight);\r
28953 \r
28954         this.innerList.setHeight(h);\r
28955         this.list.beginUpdate();\r
28956         this.list.setHeight(h+pad);\r
28957         this.list.alignTo(this.wrap, this.listAlign);\r
28958         this.list.endUpdate();\r
28959     },\r
28960 \r
28961     // private\r
28962     onEmptyResults : function(){\r
28963         this.collapse();\r
28964     },\r
28965 \r
28966     \r
28967     isExpanded : function(){\r
28968         return this.list && this.list.isVisible();\r
28969     },\r
28970 \r
28971     \r
28972     selectByValue : function(v, scrollIntoView){\r
28973         if(v !== undefined && v !== null){\r
28974             var r = this.findRecord(this.valueField || this.displayField, v);\r
28975             if(r){\r
28976                 this.select(this.store.indexOf(r), scrollIntoView);\r
28977                 return true;\r
28978             }\r
28979         }\r
28980         return false;\r
28981     },\r
28982 \r
28983     \r
28984     select : function(index, scrollIntoView){\r
28985         this.selectedIndex = index;\r
28986         this.view.select(index);\r
28987         if(scrollIntoView !== false){\r
28988             var el = this.view.getNode(index);\r
28989             if(el){\r
28990                 this.innerList.scrollChildIntoView(el, false);\r
28991             }\r
28992         }\r
28993     },\r
28994 \r
28995     // private\r
28996     selectNext : function(){\r
28997         var ct = this.store.getCount();\r
28998         if(ct > 0){\r
28999             if(this.selectedIndex == -1){\r
29000                 this.select(0);\r
29001             }else if(this.selectedIndex < ct-1){\r
29002                 this.select(this.selectedIndex+1);\r
29003             }\r
29004         }\r
29005     },\r
29006 \r
29007     // private\r
29008     selectPrev : function(){\r
29009         var ct = this.store.getCount();\r
29010         if(ct > 0){\r
29011             if(this.selectedIndex == -1){\r
29012                 this.select(0);\r
29013             }else if(this.selectedIndex != 0){\r
29014                 this.select(this.selectedIndex-1);\r
29015             }\r
29016         }\r
29017     },\r
29018 \r
29019     // private\r
29020     onKeyUp : function(e){\r
29021         if(this.editable !== false && !e.isSpecialKey()){\r
29022             this.lastKey = e.getKey();\r
29023             this.dqTask.delay(this.queryDelay);\r
29024         }\r
29025     },\r
29026 \r
29027     // private\r
29028     validateBlur : function(){\r
29029         return !this.list || !this.list.isVisible();\r
29030     },\r
29031 \r
29032     // private\r
29033     initQuery : function(){\r
29034         this.doQuery(this.getRawValue());\r
29035     },\r
29036 \r
29037     // private\r
29038     doForce : function(){\r
29039         if(this.el.dom.value.length > 0){\r
29040             this.el.dom.value =\r
29041                 this.lastSelectionText === undefined ? '' : this.lastSelectionText;\r
29042             this.applyEmptyText();\r
29043         }\r
29044     },\r
29045 \r
29046     \r
29047     doQuery : function(q, forceAll){\r
29048         if(q === undefined || q === null){\r
29049             q = '';\r
29050         }\r
29051         var qe = {\r
29052             query: q,\r
29053             forceAll: forceAll,\r
29054             combo: this,\r
29055             cancel:false\r
29056         };\r
29057         if(this.fireEvent('beforequery', qe)===false || qe.cancel){\r
29058             return false;\r
29059         }\r
29060         q = qe.query;\r
29061         forceAll = qe.forceAll;\r
29062         if(forceAll === true || (q.length >= this.minChars)){\r
29063             if(this.lastQuery !== q){\r
29064                 this.lastQuery = q;\r
29065                 if(this.mode == 'local'){\r
29066                     this.selectedIndex = -1;\r
29067                     if(forceAll){\r
29068                         this.store.clearFilter();\r
29069                     }else{\r
29070                         this.store.filter(this.displayField, q);\r
29071                     }\r
29072                     this.onLoad();\r
29073                 }else{\r
29074                     this.store.baseParams[this.queryParam] = q;\r
29075                     this.store.load({\r
29076                         params: this.getParams(q)\r
29077                     });\r
29078                     this.expand();\r
29079                 }\r
29080             }else{\r
29081                 this.selectedIndex = -1;\r
29082                 this.onLoad();\r
29083             }\r
29084         }\r
29085     },\r
29086 \r
29087     // private\r
29088     getParams : function(q){\r
29089         var p = {};\r
29090         //p[this.queryParam] = q;\r
29091         if(this.pageSize){\r
29092             p.start = 0;\r
29093             p.limit = this.pageSize;\r
29094         }\r
29095         return p;\r
29096     },\r
29097 \r
29098     \r
29099     collapse : function(){\r
29100         if(!this.isExpanded()){\r
29101             return;\r
29102         }\r
29103         this.list.hide();\r
29104         Ext.getDoc().un('mousewheel', this.collapseIf, this);\r
29105         Ext.getDoc().un('mousedown', this.collapseIf, this);\r
29106         this.fireEvent('collapse', this);\r
29107     },\r
29108 \r
29109     // private\r
29110     collapseIf : function(e){\r
29111         if(!e.within(this.wrap) && !e.within(this.list)){\r
29112             this.collapse();\r
29113         }\r
29114     },\r
29115 \r
29116     \r
29117     expand : function(){\r
29118         if(this.isExpanded() || !this.hasFocus){\r
29119             return;\r
29120         }\r
29121         this.list.alignTo(this.wrap, this.listAlign);\r
29122         this.list.show();\r
29123         this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac\r
29124         Ext.getDoc().on('mousewheel', this.collapseIf, this);\r
29125         Ext.getDoc().on('mousedown', this.collapseIf, this);\r
29126         this.fireEvent('expand', this);\r
29127     },\r
29128 \r
29129     \r
29130     // private\r
29131     // Implements the default empty TriggerField.onTriggerClick function\r
29132     onTriggerClick : function(){\r
29133         if(this.disabled){\r
29134             return;\r
29135         }\r
29136         if(this.isExpanded()){\r
29137             this.collapse();\r
29138             this.el.focus();\r
29139         }else {\r
29140             this.onFocus({});\r
29141             if(this.triggerAction == 'all') {\r
29142                 this.doQuery(this.allQuery, true);\r
29143             } else {\r
29144                 this.doQuery(this.getRawValue());\r
29145             }\r
29146             this.el.focus();\r
29147         }\r
29148     }\r
29149 \r
29150     \r
29151     \r
29152     \r
29153     \r
29154 \r
29155 });\r
29156 Ext.reg('combo', Ext.form.ComboBox);\r
29157 \r
29158 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {\r
29159     \r
29160     checkedCls: 'x-form-check-checked',\r
29161     \r
29162     focusCls: 'x-form-check-focus',\r
29163     \r
29164     overCls: 'x-form-check-over',\r
29165     \r
29166     mouseDownCls: 'x-form-check-down',\r
29167     \r
29168     tabIndex: 0,\r
29169     \r
29170     checked: false,\r
29171     \r
29172     defaultAutoCreate: {tag: 'input', type: 'checkbox', autocomplete: 'off'},\r
29173     \r
29174     \r
29175     \r
29176     \r
29177 \r
29178 \r
29179     // private\r
29180     baseCls: 'x-form-check',\r
29181 \r
29182     // private\r
29183     initComponent : function(){\r
29184         Ext.form.Checkbox.superclass.initComponent.call(this);\r
29185         this.addEvents(\r
29186             \r
29187             'check'\r
29188         );\r
29189     },\r
29190 \r
29191     // private\r
29192     initEvents : function(){\r
29193         Ext.form.Checkbox.superclass.initEvents.call(this);\r
29194         this.initCheckEvents();\r
29195     },\r
29196 \r
29197     // private\r
29198     initCheckEvents : function(){\r
29199         this.innerWrap.removeAllListeners();\r
29200         this.innerWrap.addClassOnOver(this.overCls);\r
29201         this.innerWrap.addClassOnClick(this.mouseDownCls);\r
29202         this.innerWrap.on('click', this.onClick, this);\r
29203         this.innerWrap.on('keyup', this.onKeyUp, this);\r
29204     },\r
29205 \r
29206     // private\r
29207     onRender : function(ct, position){\r
29208         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);\r
29209         if(this.inputValue !== undefined){\r
29210             this.el.dom.value = this.inputValue;\r
29211         }\r
29212         this.el.addClass('x-hidden');\r
29213 \r
29214         this.innerWrap = this.el.wrap({\r
29215             tabIndex: this.tabIndex,\r
29216             cls: this.baseCls+'-wrap-inner'\r
29217         });\r
29218         this.wrap = this.innerWrap.wrap({cls: this.baseCls+'-wrap'});\r
29219 \r
29220         if(this.boxLabel){\r
29221             this.labelEl = this.innerWrap.createChild({\r
29222                 tag: 'label',\r
29223                 htmlFor: this.el.id,\r
29224                 cls: 'x-form-cb-label',\r
29225                 html: this.boxLabel\r
29226             });\r
29227         }\r
29228 \r
29229         this.imageEl = this.innerWrap.createChild({\r
29230             tag: 'img',\r
29231             src: Ext.BLANK_IMAGE_URL,\r
29232             cls: this.baseCls\r
29233         }, this.el);\r
29234 \r
29235         if(this.checked){\r
29236             this.setValue(true);\r
29237         }else{\r
29238             this.checked = this.el.dom.checked;\r
29239         }\r
29240         this.originalValue = this.checked;\r
29241     },\r
29242     \r
29243     // private\r
29244     afterRender : function(){\r
29245         Ext.form.Checkbox.superclass.afterRender.call(this);\r
29246         this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);\r
29247     },\r
29248 \r
29249     // private\r
29250     onDestroy : function(){\r
29251         if(this.rendered){\r
29252             Ext.destroy(this.imageEl, this.labelEl, this.innerWrap, this.wrap);\r
29253         }\r
29254         Ext.form.Checkbox.superclass.onDestroy.call(this);\r
29255     },\r
29256 \r
29257     // private\r
29258     onFocus: function(e) {\r
29259         Ext.form.Checkbox.superclass.onFocus.call(this, e);\r
29260         this.el.addClass(this.focusCls);\r
29261     },\r
29262 \r
29263     // private\r
29264     onBlur: function(e) {\r
29265         Ext.form.Checkbox.superclass.onBlur.call(this, e);\r
29266         this.el.removeClass(this.focusCls);\r
29267     },\r
29268 \r
29269     // private\r
29270     onResize : function(){\r
29271         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);\r
29272         if(!this.boxLabel && !this.fieldLabel){\r
29273             this.el.alignTo(this.wrap, 'c-c');\r
29274         }\r
29275     },\r
29276 \r
29277     // private\r
29278     onKeyUp : function(e){\r
29279         if(e.getKey() == Ext.EventObject.SPACE){\r
29280             this.onClick(e);\r
29281         }\r
29282     },\r
29283 \r
29284     // private\r
29285     onClick : function(e){\r
29286         if (!this.disabled && !this.readOnly) {\r
29287             this.toggleValue();\r
29288         }\r
29289         e.stopEvent();\r
29290     },\r
29291 \r
29292     // private\r
29293     onEnable : function(){\r
29294         Ext.form.Checkbox.superclass.onEnable.call(this);\r
29295         this.initCheckEvents();\r
29296     },\r
29297 \r
29298     // private\r
29299     onDisable : function(){\r
29300         Ext.form.Checkbox.superclass.onDisable.call(this);\r
29301         this.innerWrap.removeAllListeners();\r
29302     },\r
29303 \r
29304     toggleValue : function(){\r
29305         this.setValue(!this.checked);\r
29306     },\r
29307 \r
29308     // private\r
29309     getResizeEl : function(){\r
29310         if(!this.resizeEl){\r
29311             this.resizeEl = Ext.isSafari ? this.wrap : (this.wrap.up('.x-form-element', 5) || this.wrap);\r
29312         }\r
29313         return this.resizeEl;\r
29314     },\r
29315 \r
29316     // private\r
29317     getPositionEl : function(){\r
29318         return this.wrap;\r
29319     },\r
29320 \r
29321     // private\r
29322     getActionEl : function(){\r
29323         return this.wrap;\r
29324     },\r
29325 \r
29326     \r
29327     markInvalid : Ext.emptyFn,\r
29328     \r
29329     clearInvalid : Ext.emptyFn,\r
29330 \r
29331     // private\r
29332     initValue : Ext.emptyFn,\r
29333 \r
29334     \r
29335     getValue : function(){\r
29336         if(this.rendered){\r
29337             return this.el.dom.checked;\r
29338         }\r
29339         return this.checked;\r
29340     },\r
29341 \r
29342     \r
29343     setValue : function(v) {\r
29344         var checked = this.checked;\r
29345         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');\r
29346         \r
29347         if(this.rendered){\r
29348             this.el.dom.checked = this.checked;\r
29349             this.el.dom.defaultChecked = this.checked;\r
29350             this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);\r
29351         }\r
29352 \r
29353         if(checked != this.checked){\r
29354             this.fireEvent("check", this, this.checked);\r
29355             if(this.handler){\r
29356                 this.handler.call(this.scope || this, this, this.checked);\r
29357             }\r
29358         }\r
29359     }\r
29360 \r
29361     \r
29362     \r
29363     \r
29364 });\r
29365 Ext.reg('checkbox', Ext.form.Checkbox);\r
29366 \r
29367 \r
29368 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {\r
29369     \r
29370     \r
29371     columns : 'auto',\r
29372     \r
29373     vertical : false,\r
29374     \r
29375     allowBlank : true,\r
29376     \r
29377     blankText : "You must select at least one item in this group",\r
29378     \r
29379     // private\r
29380     defaultType : 'checkbox',\r
29381     \r
29382     // private\r
29383     groupCls: 'x-form-check-group',\r
29384     \r
29385     // private\r
29386     onRender : function(ct, position){\r
29387         if(!this.el){\r
29388             var panelCfg = {\r
29389                 cls: this.groupCls,\r
29390                 layout: 'column',\r
29391                 border: false,\r
29392                 renderTo: ct\r
29393             };\r
29394             var colCfg = {\r
29395                 defaultType: this.defaultType,\r
29396                 layout: 'form',\r
29397                 border: false,\r
29398                 defaults: {\r
29399                     hideLabel: true,\r
29400                     anchor: '100%'\r
29401                 }\r
29402             }\r
29403             \r
29404             if(this.items[0].items){\r
29405                 \r
29406                 // The container has standard ColumnLayout configs, so pass them in directly\r
29407                 \r
29408                 Ext.apply(panelCfg, {\r
29409                     layoutConfig: {columns: this.items.length},\r
29410                     defaults: this.defaults,\r
29411                     items: this.items\r
29412                 })\r
29413                 for(var i=0, len=this.items.length; i<len; i++){\r
29414                     Ext.applyIf(this.items[i], colCfg);\r
29415                 };\r
29416                 \r
29417             }else{\r
29418                 \r
29419                 // The container has field item configs, so we have to generate the column\r
29420                 // panels first then move the items into the columns as needed.\r
29421                 \r
29422                 var numCols, cols = [];\r
29423                 \r
29424                 if(typeof this.columns == 'string'){ // 'auto' so create a col per item\r
29425                     this.columns = this.items.length;\r
29426                 }\r
29427                 if(!Ext.isArray(this.columns)){\r
29428                     var cs = [];\r
29429                     for(var i=0; i<this.columns; i++){\r
29430                         cs.push((100/this.columns)*.01); // distribute by even %\r
29431                     }\r
29432                     this.columns = cs;\r
29433                 }\r
29434                 \r
29435                 numCols = this.columns.length;\r
29436                 \r
29437                 // Generate the column configs with the correct width setting\r
29438                 for(var i=0; i<numCols; i++){\r
29439                     var cc = Ext.apply({items:[]}, colCfg);\r
29440                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];\r
29441                     if(this.defaults){\r
29442                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)\r
29443                     }\r
29444                     cols.push(cc);\r
29445                 };\r
29446                 \r
29447                 // Distribute the original items into the columns\r
29448                 if(this.vertical){\r
29449                     var rows = Math.ceil(this.items.length / numCols), ri = 0;\r
29450                     for(var i=0, len=this.items.length; i<len; i++){\r
29451                         if(i>0 && i%rows==0){\r
29452                             ri++;\r
29453                         }\r
29454                         if(this.items[i].fieldLabel){\r
29455                             this.items[i].hideLabel = false;\r
29456                         }\r
29457                         cols[ri].items.push(this.items[i]);\r
29458                     };\r
29459                 }else{\r
29460                     for(var i=0, len=this.items.length; i<len; i++){\r
29461                         var ci = i % numCols;\r
29462                         if(this.items[i].fieldLabel){\r
29463                             this.items[i].hideLabel = false;\r
29464                         }\r
29465                         cols[ci].items.push(this.items[i]);\r
29466                     };\r
29467                 }\r
29468                 \r
29469                 Ext.apply(panelCfg, {\r
29470                     layoutConfig: {columns: numCols},\r
29471                     items: cols\r
29472                 });\r
29473             }\r
29474             \r
29475             this.panel = new Ext.Panel(panelCfg);\r
29476             this.el = this.panel.getEl();\r
29477             \r
29478             if(this.forId && this.itemCls){\r
29479                 var l = this.el.up(this.itemCls).child('label', true);\r
29480                 if(l){\r
29481                     l.setAttribute('htmlFor', this.forId);\r
29482                 }\r
29483             }\r
29484             \r
29485             var fields = this.panel.findBy(function(c){\r
29486                 return c.isFormField;\r
29487             }, this);\r
29488             \r
29489             this.items = new Ext.util.MixedCollection();\r
29490             this.items.addAll(fields);\r
29491         }\r
29492         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);\r
29493     },\r
29494     \r
29495     // private\r
29496     validateValue : function(value){\r
29497         if(!this.allowBlank){\r
29498             var blank = true;\r
29499             this.items.each(function(f){\r
29500                 if(f.checked){\r
29501                     return blank = false;\r
29502                 }\r
29503             }, this);\r
29504             if(blank){\r
29505                 this.markInvalid(this.blankText);\r
29506                 return false;\r
29507             }\r
29508         }\r
29509         return true;\r
29510     },\r
29511     \r
29512     // private\r
29513     onDisable : function(){\r
29514         this.items.each(function(item){\r
29515             item.disable();\r
29516         })\r
29517     },\r
29518 \r
29519     // private\r
29520     onEnable : function(){\r
29521         this.items.each(function(item){\r
29522             item.enable();\r
29523         })\r
29524     },\r
29525     \r
29526     // private\r
29527     onResize : function(w, h){\r
29528         this.panel.setSize(w, h);\r
29529         this.panel.doLayout();\r
29530     },\r
29531     \r
29532     // inherit docs from Field\r
29533     reset : function(){\r
29534         Ext.form.CheckboxGroup.superclass.reset.call(this);\r
29535         this.items.each(function(c){\r
29536             if(c.reset){\r
29537                 c.reset();\r
29538             }\r
29539         }, this);\r
29540     },\r
29541     \r
29542     \r
29543     \r
29544     initValue : Ext.emptyFn,\r
29545     \r
29546     getValue : Ext.emptyFn,\r
29547     \r
29548     getRawValue : Ext.emptyFn,\r
29549     \r
29550     setValue : Ext.emptyFn,\r
29551     \r
29552     setRawValue : Ext.emptyFn\r
29553     \r
29554 });\r
29555 \r
29556 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);\r
29557 \r
29558 \r
29559 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {\r
29560     // private\r
29561     inputType: 'radio',\r
29562     // private\r
29563     baseCls: 'x-form-radio',\r
29564     \r
29565     \r
29566     getGroupValue : function(){\r
29567         var c = this.getParent().child('input[name='+this.el.dom.name+']:checked', true);\r
29568         return c ? c.value : null;\r
29569     },\r
29570     \r
29571     // private\r
29572     getParent : function(){\r
29573         return this.el.up('form') || Ext.getBody();\r
29574     },\r
29575 \r
29576     // private\r
29577     toggleValue : function() {\r
29578         if(!this.checked){\r
29579             var els = this.getParent().select('input[name='+this.el.dom.name+']');\r
29580             els.each(function(el){\r
29581                 if(el.dom.id == this.id){\r
29582                     this.setValue(true);\r
29583                 }else{\r
29584                     Ext.getCmp(el.dom.id).setValue(false);\r
29585                 }\r
29586             }, this);\r
29587         }\r
29588     },\r
29589     \r
29590     \r
29591     setValue : function(v){\r
29592         if(typeof v=='boolean') {\r
29593             Ext.form.Radio.superclass.setValue.call(this, v);\r
29594         }else{\r
29595             var r = this.getParent().child('input[name='+this.el.dom.name+'][value='+v+']', true);\r
29596             if(r && !r.checked){\r
29597                 Ext.getCmp(r.id).toggleValue();\r
29598             };\r
29599         }\r
29600     },\r
29601     \r
29602     \r
29603     markInvalid : Ext.emptyFn,\r
29604     \r
29605     clearInvalid : Ext.emptyFn\r
29606     \r
29607 });\r
29608 Ext.reg('radio', Ext.form.Radio);\r
29609 \r
29610 \r
29611 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {\r
29612     \r
29613     allowBlank : true,\r
29614     \r
29615     blankText : "You must select one item in this group",\r
29616     \r
29617     // private\r
29618     defaultType : 'radio',\r
29619     \r
29620     // private\r
29621     groupCls: 'x-form-radio-group'\r
29622 });\r
29623 \r
29624 Ext.reg('radiogroup', Ext.form.RadioGroup);\r
29625 \r
29626 \r
29627 Ext.form.Hidden = Ext.extend(Ext.form.Field, {\r
29628     // private\r
29629     inputType : 'hidden',\r
29630 \r
29631     // private\r
29632     onRender : function(){\r
29633         Ext.form.Hidden.superclass.onRender.apply(this, arguments);\r
29634     },\r
29635 \r
29636     // private\r
29637     initEvents : function(){\r
29638         this.originalValue = this.getValue();\r
29639     },\r
29640 \r
29641     // These are all private overrides\r
29642     setSize : Ext.emptyFn,\r
29643     setWidth : Ext.emptyFn,\r
29644     setHeight : Ext.emptyFn,\r
29645     setPosition : Ext.emptyFn,\r
29646     setPagePosition : Ext.emptyFn,\r
29647     markInvalid : Ext.emptyFn,\r
29648     clearInvalid : Ext.emptyFn\r
29649 });\r
29650 Ext.reg('hidden', Ext.form.Hidden);\r
29651 \r
29652 Ext.form.BasicForm = function(el, config){\r
29653     Ext.apply(this, config);\r
29654     \r
29655     this.items = new Ext.util.MixedCollection(false, function(o){\r
29656         return o.id || (o.id = Ext.id());\r
29657     });\r
29658     this.addEvents(\r
29659         \r
29660         'beforeaction',\r
29661         \r
29662         'actionfailed',\r
29663         \r
29664         'actioncomplete'\r
29665     );\r
29666 \r
29667     if(el){\r
29668         this.initEl(el);\r
29669     }\r
29670     Ext.form.BasicForm.superclass.constructor.call(this);\r
29671 };\r
29672 \r
29673 Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {\r
29674     \r
29675     \r
29676     \r
29677     \r
29678     \r
29679     \r
29680     \r
29681     timeout: 30,\r
29682 \r
29683     // private\r
29684     activeAction : null,\r
29685 \r
29686     \r
29687     trackResetOnLoad : false,\r
29688 \r
29689     \r
29690     \r
29691 \r
29692     // private\r
29693     initEl : function(el){\r
29694         this.el = Ext.get(el);\r
29695         this.id = this.el.id || Ext.id();\r
29696         if(!this.standardSubmit){\r
29697             this.el.on('submit', this.onSubmit, this);\r
29698         }\r
29699         this.el.addClass('x-form');\r
29700     },\r
29701 \r
29702     \r
29703     getEl: function(){\r
29704         return this.el;\r
29705     },\r
29706 \r
29707     // private\r
29708     onSubmit : function(e){\r
29709         e.stopEvent();\r
29710     },\r
29711 \r
29712     // private\r
29713     destroy: function() {\r
29714         this.items.each(function(f){\r
29715             Ext.destroy(f);\r
29716         });\r
29717         if(this.el){\r
29718             this.el.removeAllListeners();\r
29719             this.el.remove();\r
29720         }\r
29721         this.purgeListeners();\r
29722     },\r
29723 \r
29724     \r
29725     isValid : function(){\r
29726         var valid = true;\r
29727         this.items.each(function(f){\r
29728            if(!f.validate()){\r
29729                valid = false;\r
29730            }\r
29731         });\r
29732         return valid;\r
29733     },\r
29734 \r
29735     \r
29736     isDirty : function(){\r
29737         var dirty = false;\r
29738         this.items.each(function(f){\r
29739            if(f.isDirty()){\r
29740                dirty = true;\r
29741                return false;\r
29742            }\r
29743         });\r
29744         return dirty;\r
29745     },\r
29746 \r
29747     \r
29748     doAction : function(action, options){\r
29749         if(typeof action == 'string'){\r
29750             action = new Ext.form.Action.ACTION_TYPES[action](this, options);\r
29751         }\r
29752         if(this.fireEvent('beforeaction', this, action) !== false){\r
29753             this.beforeAction(action);\r
29754             action.run.defer(100, action);\r
29755         }\r
29756         return this;\r
29757     },\r
29758 \r
29759     \r
29760     submit : function(options){\r
29761         if(this.standardSubmit){\r
29762             var v = this.isValid();\r
29763             if(v){\r
29764                 this.el.dom.submit();\r
29765             }\r
29766             return v;\r
29767         }\r
29768         this.doAction('submit', options);\r
29769         return this;\r
29770     },\r
29771 \r
29772     \r
29773     load : function(options){\r
29774         this.doAction('load', options);\r
29775         return this;\r
29776     },\r
29777 \r
29778     \r
29779     updateRecord : function(record){\r
29780         record.beginEdit();\r
29781         var fs = record.fields;\r
29782         fs.each(function(f){\r
29783             var field = this.findField(f.name);\r
29784             if(field){\r
29785                 record.set(f.name, field.getValue());\r
29786             }\r
29787         }, this);\r
29788         record.endEdit();\r
29789         return this;\r
29790     },\r
29791 \r
29792     \r
29793     loadRecord : function(record){\r
29794         this.setValues(record.data);\r
29795         return this;\r
29796     },\r
29797 \r
29798     // private\r
29799     beforeAction : function(action){\r
29800         var o = action.options;\r
29801         if(o.waitMsg){\r
29802             if(this.waitMsgTarget === true){\r
29803                 this.el.mask(o.waitMsg, 'x-mask-loading');\r
29804             }else if(this.waitMsgTarget){\r
29805                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);\r
29806                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');\r
29807             }else{\r
29808                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');\r
29809             }\r
29810         }\r
29811     },\r
29812 \r
29813     // private\r
29814     afterAction : function(action, success){\r
29815         this.activeAction = null;\r
29816         var o = action.options;\r
29817         if(o.waitMsg){\r
29818             if(this.waitMsgTarget === true){\r
29819                 this.el.unmask();\r
29820             }else if(this.waitMsgTarget){\r
29821                 this.waitMsgTarget.unmask();\r
29822             }else{\r
29823                 Ext.MessageBox.updateProgress(1);\r
29824                 Ext.MessageBox.hide();\r
29825             }\r
29826         }\r
29827         if(success){\r
29828             if(o.reset){\r
29829                 this.reset();\r
29830             }\r
29831             Ext.callback(o.success, o.scope, [this, action]);\r
29832             this.fireEvent('actioncomplete', this, action);\r
29833         }else{\r
29834             Ext.callback(o.failure, o.scope, [this, action]);\r
29835             this.fireEvent('actionfailed', this, action);\r
29836         }\r
29837     },\r
29838 \r
29839     \r
29840     findField : function(id){\r
29841         var field = this.items.get(id);\r
29842         if(!field){\r
29843             this.items.each(function(f){\r
29844                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){\r
29845                     field = f;\r
29846                     return false;\r
29847                 }\r
29848             });\r
29849         }\r
29850         return field || null;\r
29851     },\r
29852 \r
29853 \r
29854     \r
29855     markInvalid : function(errors){\r
29856         if(Ext.isArray(errors)){\r
29857             for(var i = 0, len = errors.length; i < len; i++){\r
29858                 var fieldError = errors[i];\r
29859                 var f = this.findField(fieldError.id);\r
29860                 if(f){\r
29861                     f.markInvalid(fieldError.msg);\r
29862                 }\r
29863             }\r
29864         }else{\r
29865             var field, id;\r
29866             for(id in errors){\r
29867                 if(typeof errors[id] != 'function' && (field = this.findField(id))){\r
29868                     field.markInvalid(errors[id]);\r
29869                 }\r
29870             }\r
29871         }\r
29872         return this;\r
29873     },\r
29874 \r
29875     \r
29876     setValues : function(values){\r
29877         if(Ext.isArray(values)){ // array of objects\r
29878             for(var i = 0, len = values.length; i < len; i++){\r
29879                 var v = values[i];\r
29880                 var f = this.findField(v.id);\r
29881                 if(f){\r
29882                     f.setValue(v.value);\r
29883                     if(this.trackResetOnLoad){\r
29884                         f.originalValue = f.getValue();\r
29885                     }\r
29886                 }\r
29887             }\r
29888         }else{ // object hash\r
29889             var field, id;\r
29890             for(id in values){\r
29891                 if(typeof values[id] != 'function' && (field = this.findField(id))){\r
29892                     field.setValue(values[id]);\r
29893                     if(this.trackResetOnLoad){\r
29894                         field.originalValue = field.getValue();\r
29895                     }\r
29896                 }\r
29897             }\r
29898         }\r
29899         return this;\r
29900     },\r
29901 \r
29902     \r
29903     getValues : function(asString){\r
29904         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);\r
29905         if(asString === true){\r
29906             return fs;\r
29907         }\r
29908         return Ext.urlDecode(fs);\r
29909     },\r
29910 \r
29911     \r
29912     clearInvalid : function(){\r
29913         this.items.each(function(f){\r
29914            f.clearInvalid();\r
29915         });\r
29916         return this;\r
29917     },\r
29918 \r
29919     \r
29920     reset : function(){\r
29921         this.items.each(function(f){\r
29922             f.reset();\r
29923         });\r
29924         return this;\r
29925     },\r
29926 \r
29927     \r
29928     add : function(){\r
29929         this.items.addAll(Array.prototype.slice.call(arguments, 0));\r
29930         return this;\r
29931     },\r
29932 \r
29933 \r
29934     \r
29935     remove : function(field){\r
29936         this.items.remove(field);\r
29937         return this;\r
29938     },\r
29939 \r
29940     \r
29941     render : function(){\r
29942         this.items.each(function(f){\r
29943             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists\r
29944                 f.applyToMarkup(f.id);\r
29945             }\r
29946         });\r
29947         return this;\r
29948     },\r
29949 \r
29950     \r
29951     applyToFields : function(o){\r
29952         this.items.each(function(f){\r
29953            Ext.apply(f, o);\r
29954         });\r
29955         return this;\r
29956     },\r
29957 \r
29958     \r
29959     applyIfToFields : function(o){\r
29960         this.items.each(function(f){\r
29961            Ext.applyIf(f, o);\r
29962         });\r
29963         return this;\r
29964     }\r
29965 });\r
29966 \r
29967 // back compat\r
29968 Ext.BasicForm = Ext.form.BasicForm;\r
29969 \r
29970 Ext.FormPanel = Ext.extend(Ext.Panel, {\r
29971         \r
29972     \r
29973     \r
29974     \r
29975     \r
29976     buttonAlign:'center',\r
29977 \r
29978     \r
29979     minButtonWidth:75,\r
29980 \r
29981     \r
29982     labelAlign:'left',\r
29983 \r
29984     \r
29985     monitorValid : false,\r
29986 \r
29987     \r
29988     monitorPoll : 200,\r
29989 \r
29990     \r
29991     layout: 'form',\r
29992 \r
29993     // private\r
29994     initComponent :function(){\r
29995         this.form = this.createForm();\r
29996 \r
29997         this.bodyCfg = {\r
29998             tag: 'form',\r
29999             cls: this.baseCls + '-body',\r
30000             method : this.method || 'POST',\r
30001             id : this.formId || Ext.id()\r
30002         };\r
30003         if(this.fileUpload) {\r
30004             this.bodyCfg.enctype = 'multipart/form-data';\r
30005         }\r
30006 \r
30007         Ext.FormPanel.superclass.initComponent.call(this);\r
30008 \r
30009         this.initItems();\r
30010 \r
30011         this.addEvents(\r
30012             \r
30013             'clientvalidation'\r
30014         );\r
30015 \r
30016         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);\r
30017     },\r
30018 \r
30019     // private\r
30020     createForm: function(){\r
30021         delete this.initialConfig.listeners;\r
30022         return new Ext.form.BasicForm(null, this.initialConfig);\r
30023     },\r
30024 \r
30025     // private\r
30026     initFields : function(){\r
30027         var f = this.form;\r
30028         var formPanel = this;\r
30029         var fn = function(c){\r
30030             if(c.isFormField){\r
30031                 f.add(c);\r
30032             }else if(c.doLayout && c != formPanel){\r
30033                 Ext.applyIf(c, {\r
30034                     labelAlign: c.ownerCt.labelAlign,\r
30035                     labelWidth: c.ownerCt.labelWidth,\r
30036                     itemCls: c.ownerCt.itemCls\r
30037                 });\r
30038                 if(c.items){\r
30039                     c.items.each(fn);\r
30040                 }\r
30041             }\r
30042         }\r
30043         this.items.each(fn);\r
30044     },\r
30045 \r
30046     // private\r
30047     getLayoutTarget : function(){\r
30048         return this.form.el;\r
30049     },\r
30050 \r
30051     \r
30052     getForm : function(){\r
30053         return this.form;\r
30054     },\r
30055 \r
30056     // private\r
30057     onRender : function(ct, position){\r
30058         this.initFields();\r
30059 \r
30060         Ext.FormPanel.superclass.onRender.call(this, ct, position);\r
30061         this.form.initEl(this.body);\r
30062     },\r
30063     \r
30064     // private\r
30065     beforeDestroy: function(){\r
30066         Ext.FormPanel.superclass.beforeDestroy.call(this);\r
30067         this.stopMonitoring();\r
30068         Ext.destroy(this.form);\r
30069     },\r
30070 \r
30071     // private\r
30072     initEvents : function(){\r
30073         Ext.FormPanel.superclass.initEvents.call(this);\r
30074         this.items.on('remove', this.onRemove, this);\r
30075                 this.items.on('add', this.onAdd, this);\r
30076         if(this.monitorValid){ // initialize after render\r
30077             this.startMonitoring();\r
30078         }\r
30079     },\r
30080     \r
30081     // private\r
30082         onAdd : function(ct, c) {\r
30083                 if (c.isFormField) {\r
30084                         this.form.add(c);\r
30085                 }\r
30086         },\r
30087         \r
30088         // private\r
30089         onRemove : function(c) {\r
30090                 if (c.isFormField) {\r
30091                         Ext.destroy(c.container.up('.x-form-item'));\r
30092                         this.form.remove(c);\r
30093                 }\r
30094         },\r
30095 \r
30096     \r
30097     startMonitoring : function(){\r
30098         if(!this.bound){\r
30099             this.bound = true;\r
30100             Ext.TaskMgr.start({\r
30101                 run : this.bindHandler,\r
30102                 interval : this.monitorPoll || 200,\r
30103                 scope: this\r
30104             });\r
30105         }\r
30106     },\r
30107 \r
30108     \r
30109     stopMonitoring : function(){\r
30110         this.bound = false;\r
30111     },\r
30112 \r
30113     \r
30114     load : function(){\r
30115         this.form.load.apply(this.form, arguments);  \r
30116     },\r
30117 \r
30118     // private\r
30119     onDisable : function(){\r
30120         Ext.FormPanel.superclass.onDisable.call(this);\r
30121         if(this.form){\r
30122             this.form.items.each(function(){\r
30123                  this.disable();\r
30124             });\r
30125         }\r
30126     },\r
30127 \r
30128     // private\r
30129     onEnable : function(){\r
30130         Ext.FormPanel.superclass.onEnable.call(this);\r
30131         if(this.form){\r
30132             this.form.items.each(function(){\r
30133                  this.enable();\r
30134             });\r
30135         }\r
30136     },\r
30137 \r
30138     // private\r
30139     bindHandler : function(){\r
30140         if(!this.bound){\r
30141             return false; // stops binding\r
30142         }\r
30143         var valid = true;\r
30144         this.form.items.each(function(f){\r
30145             if(!f.isValid(true)){\r
30146                 valid = false;\r
30147                 return false;\r
30148             }\r
30149         });\r
30150         if(this.buttons){\r
30151             for(var i = 0, len = this.buttons.length; i < len; i++){\r
30152                 var btn = this.buttons[i];\r
30153                 if(btn.formBind === true && btn.disabled === valid){\r
30154                     btn.setDisabled(!valid);\r
30155                 }\r
30156             }\r
30157         }\r
30158         this.fireEvent('clientvalidation', this, valid);\r
30159     }\r
30160 });\r
30161 Ext.reg('form', Ext.FormPanel);\r
30162 \r
30163 Ext.form.FormPanel = Ext.FormPanel;\r
30164 \r
30165 \r
30166 \r
30167 Ext.form.FieldSet = Ext.extend(Ext.Panel, {\r
30168     \r
30169     \r
30170     \r
30171     \r
30172     \r
30173     baseCls:'x-fieldset',\r
30174     \r
30175     layout: 'form',\r
30176     \r
30177     animCollapse: false,\r
30178 \r
30179     // private\r
30180     onRender : function(ct, position){\r
30181         if(!this.el){\r
30182             this.el = document.createElement('fieldset');\r
30183             this.el.id = this.id;\r
30184             if (this.title || this.header || this.checkboxToggle) {\r
30185                 this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';\r
30186             }\r
30187         }\r
30188 \r
30189         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);\r
30190 \r
30191         if(this.checkboxToggle){\r
30192             var o = typeof this.checkboxToggle == 'object' ?\r
30193                     this.checkboxToggle :\r
30194                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};\r
30195             this.checkbox = this.header.insertFirst(o);\r
30196             this.checkbox.dom.checked = !this.collapsed;\r
30197             this.checkbox.on('click', this.onCheckClick, this);\r
30198         }\r
30199     },\r
30200 \r
30201     // private\r
30202     onCollapse : function(doAnim, animArg){\r
30203         if(this.checkbox){\r
30204             this.checkbox.dom.checked = false;\r
30205         }\r
30206         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);\r
30207 \r
30208     },\r
30209 \r
30210     // private\r
30211     onExpand : function(doAnim, animArg){\r
30212         if(this.checkbox){\r
30213             this.checkbox.dom.checked = true;\r
30214         }\r
30215         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);\r
30216     },\r
30217 \r
30218     \r
30219     onCheckClick : function(){\r
30220         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();\r
30221     },\r
30222     \r
30223     // private\r
30224     beforeDestroy : function(){\r
30225         if(this.checkbox){\r
30226             this.checkbox.un('click', this.onCheckClick, this);\r
30227         }\r
30228         Ext.form.FieldSet.superclass.beforeDestroy.call(this);\r
30229     }\r
30230 \r
30231     \r
30232     \r
30233     \r
30234     \r
30235     \r
30236     \r
30237     \r
30238     \r
30239     \r
30240     \r
30241     \r
30242     \r
30243     \r
30244     \r
30245     \r
30246     \r
30247     \r
30248     \r
30249     \r
30250     \r
30251     \r
30252     \r
30253     \r
30254     \r
30255     \r
30256     \r
30257     \r
30258     \r
30259     \r
30260     \r
30261     \r
30262     \r
30263     \r
30264     \r
30265     \r
30266     \r
30267     \r
30268 });\r
30269 Ext.reg('fieldset', Ext.form.FieldSet);\r
30270 \r
30271 \r
30272 \r
30273 \r
30274 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {\r
30275     \r
30276     enableFormat : true,\r
30277     \r
30278     enableFontSize : true,\r
30279     \r
30280     enableColors : true,\r
30281     \r
30282     enableAlignments : true,\r
30283     \r
30284     enableLists : true,\r
30285     \r
30286     enableSourceEdit : true,\r
30287     \r
30288     enableLinks : true,\r
30289     \r
30290     enableFont : true,\r
30291     \r
30292     createLinkText : 'Please enter the URL for the link:',\r
30293     \r
30294     defaultLinkValue : 'http:/'+'/',\r
30295     \r
30296     fontFamilies : [\r
30297         'Arial',\r
30298         'Courier New',\r
30299         'Tahoma',\r
30300         'Times New Roman',\r
30301         'Verdana'\r
30302     ],\r
30303     defaultFont: 'tahoma',\r
30304 \r
30305     // private properties\r
30306     validationEvent : false,\r
30307     deferHeight: true,\r
30308     initialized : false,\r
30309     activated : false,\r
30310     sourceEditMode : false,\r
30311     onFocus : Ext.emptyFn,\r
30312     iframePad:3,\r
30313     hideMode:'offsets',\r
30314     defaultAutoCreate : {\r
30315         tag: "textarea",\r
30316         style:"width:500px;height:300px;",\r
30317         autocomplete: "off"\r
30318     },\r
30319 \r
30320     // private\r
30321     initComponent : function(){\r
30322         this.addEvents(\r
30323             \r
30324             'initialize',\r
30325             \r
30326             'activate',\r
30327              \r
30328             'beforesync',\r
30329              \r
30330             'beforepush',\r
30331              \r
30332             'sync',\r
30333              \r
30334             'push',\r
30335              \r
30336             'editmodechange'\r
30337         )\r
30338     },\r
30339 \r
30340     // private\r
30341     createFontOptions : function(){\r
30342         var buf = [], fs = this.fontFamilies, ff, lc;\r
30343         for(var i = 0, len = fs.length; i< len; i++){\r
30344             ff = fs[i];\r
30345             lc = ff.toLowerCase();\r
30346             buf.push(\r
30347                 '<option value="',lc,'" style="font-family:',ff,';"',\r
30348                     (this.defaultFont == lc ? ' selected="true">' : '>'),\r
30349                     ff,\r
30350                 '</option>'\r
30351             );\r
30352         }\r
30353         return buf.join('');\r
30354     },\r
30355     \r
30356     \r
30357     createToolbar : function(editor){\r
30358         \r
30359         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();\r
30360         \r
30361         function btn(id, toggle, handler){\r
30362             return {\r
30363                 itemId : id,\r
30364                 cls : 'x-btn-icon x-edit-'+id,\r
30365                 enableToggle:toggle !== false,\r
30366                 scope: editor,\r
30367                 handler:handler||editor.relayBtnCmd,\r
30368                 clickEvent:'mousedown',\r
30369                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,\r
30370                 tabIndex:-1\r
30371             };\r
30372         }\r
30373 \r
30374         // build the toolbar\r
30375         var tb = new Ext.Toolbar({\r
30376             renderTo:this.wrap.dom.firstChild\r
30377         });\r
30378 \r
30379         // stop form submits\r
30380         tb.el.on('click', function(e){\r
30381             e.preventDefault();\r
30382         });\r
30383 \r
30384         if(this.enableFont && !Ext.isSafari2){\r
30385             this.fontSelect = tb.el.createChild({\r
30386                 tag:'select',\r
30387                 cls:'x-font-select',\r
30388                 html: this.createFontOptions()\r
30389             });\r
30390             this.fontSelect.on('change', function(){\r
30391                 var font = this.fontSelect.dom.value;\r
30392                 this.relayCmd('fontname', font);\r
30393                 this.deferFocus();\r
30394             }, this);\r
30395             tb.add(\r
30396                 this.fontSelect.dom,\r
30397                 '-'\r
30398             );\r
30399         };\r
30400 \r
30401         if(this.enableFormat){\r
30402             tb.add(\r
30403                 btn('bold'),\r
30404                 btn('italic'),\r
30405                 btn('underline')\r
30406             );\r
30407         };\r
30408 \r
30409         if(this.enableFontSize){\r
30410             tb.add(\r
30411                 '-',\r
30412                 btn('increasefontsize', false, this.adjustFont),\r
30413                 btn('decreasefontsize', false, this.adjustFont)\r
30414             );\r
30415         };\r
30416 \r
30417         if(this.enableColors){\r
30418             tb.add(\r
30419                 '-', {\r
30420                     itemId:'forecolor',\r
30421                     cls:'x-btn-icon x-edit-forecolor',\r
30422                     clickEvent:'mousedown',\r
30423                     tooltip: tipsEnabled ? editor.buttonTips['forecolor'] || undefined : undefined,\r
30424                     tabIndex:-1,\r
30425                     menu : new Ext.menu.ColorMenu({\r
30426                         allowReselect: true,\r
30427                         focus: Ext.emptyFn,\r
30428                         value:'000000',\r
30429                         plain:true,\r
30430                         selectHandler: function(cp, color){\r
30431                             this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);\r
30432                             this.deferFocus();\r
30433                         },\r
30434                         scope: this,\r
30435                         clickEvent:'mousedown'\r
30436                     })\r
30437                 }, {\r
30438                     itemId:'backcolor',\r
30439                     cls:'x-btn-icon x-edit-backcolor',\r
30440                     clickEvent:'mousedown',\r
30441                     tooltip: tipsEnabled ? editor.buttonTips['backcolor'] || undefined : undefined,\r
30442                     tabIndex:-1,\r
30443                     menu : new Ext.menu.ColorMenu({\r
30444                         focus: Ext.emptyFn,\r
30445                         value:'FFFFFF',\r
30446                         plain:true,\r
30447                         allowReselect: true,\r
30448                         selectHandler: function(cp, color){\r
30449                             if(Ext.isGecko){\r
30450                                 this.execCmd('useCSS', false);\r
30451                                 this.execCmd('hilitecolor', color);\r
30452                                 this.execCmd('useCSS', true);\r
30453                                 this.deferFocus();\r
30454                             }else{\r
30455                                 this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isSafari || Ext.isIE ? '#'+color : color);\r
30456                                 this.deferFocus();\r
30457                             }\r
30458                         },\r
30459                         scope:this,\r
30460                         clickEvent:'mousedown'\r
30461                     })\r
30462                 }\r
30463             );\r
30464         };\r
30465 \r
30466         if(this.enableAlignments){\r
30467             tb.add(\r
30468                 '-',\r
30469                 btn('justifyleft'),\r
30470                 btn('justifycenter'),\r
30471                 btn('justifyright')\r
30472             );\r
30473         };\r
30474 \r
30475         if(!Ext.isSafari2){\r
30476             if(this.enableLinks){\r
30477                 tb.add(\r
30478                     '-',\r
30479                     btn('createlink', false, this.createLink)\r
30480                 );\r
30481             };\r
30482 \r
30483             if(this.enableLists){\r
30484                 tb.add(\r
30485                     '-',\r
30486                     btn('insertorderedlist'),\r
30487                     btn('insertunorderedlist')\r
30488                 );\r
30489             }\r
30490             if(this.enableSourceEdit){\r
30491                 tb.add(\r
30492                     '-',\r
30493                     btn('sourceedit', true, function(btn){\r
30494                         this.toggleSourceEdit(btn.pressed);\r
30495                     })\r
30496                 );\r
30497             }\r
30498         }\r
30499 \r
30500         this.tb = tb;\r
30501     },\r
30502 \r
30503     \r
30504     getDocMarkup : function(){\r
30505         return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';\r
30506     },\r
30507 \r
30508     // private\r
30509     getEditorBody : function(){\r
30510         return this.doc.body || this.doc.documentElement;\r
30511     },\r
30512 \r
30513     // private\r
30514     getDoc : function(){\r
30515         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);\r
30516     },\r
30517 \r
30518     // private\r
30519     getWin : function(){\r
30520         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];\r
30521     },\r
30522 \r
30523     // private\r
30524     onRender : function(ct, position){\r
30525         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);\r
30526         this.el.dom.style.border = '0 none';\r
30527         this.el.dom.setAttribute('tabIndex', -1);\r
30528         this.el.addClass('x-hidden');\r
30529         if(Ext.isIE){ // fix IE 1px bogus margin\r
30530             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')\r
30531         }\r
30532         this.wrap = this.el.wrap({\r
30533             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}\r
30534         });\r
30535 \r
30536         this.createToolbar(this);\r
30537 \r
30538         this.tb.items.each(function(item){\r
30539            if(item.itemId != 'sourceedit'){\r
30540                 item.disable();\r
30541             }\r
30542         });\r
30543 \r
30544         var iframe = document.createElement('iframe');\r
30545         iframe.name = Ext.id();\r
30546         iframe.frameBorder = '0';\r
30547 \r
30548         iframe.src = Ext.isIE ? Ext.SSL_SECURE_URL : "javascript:;";\r
30549 \r
30550         this.wrap.dom.appendChild(iframe);\r
30551 \r
30552         this.iframe = iframe;\r
30553 \r
30554         this.initFrame();\r
30555 \r
30556         if(this.autoMonitorDesignMode !== false){\r
30557             this.monitorTask = Ext.TaskMgr.start({\r
30558                 run: this.checkDesignMode,\r
30559                 scope: this,\r
30560                 interval:100\r
30561             });\r
30562         }\r
30563 \r
30564         if(!this.width){\r
30565             var sz = this.el.getSize();\r
30566             this.setSize(sz.width, this.height || sz.height);\r
30567         }\r
30568     },\r
30569 \r
30570     initFrame : function(){\r
30571         this.doc = this.getDoc();\r
30572         this.win = this.getWin();\r
30573 \r
30574         this.doc.open();\r
30575         this.doc.write(this.getDocMarkup());\r
30576         this.doc.close();\r
30577 \r
30578         var task = { // must defer to wait for browser to be ready\r
30579             run : function(){\r
30580                 if(this.doc.body || this.doc.readyState == 'complete'){\r
30581                     Ext.TaskMgr.stop(task);\r
30582                     this.doc.designMode="on";\r
30583                     this.initEditor.defer(10, this);\r
30584                 }\r
30585             },\r
30586             interval : 10,\r
30587             duration:10000,\r
30588             scope: this\r
30589         };\r
30590         Ext.TaskMgr.start(task);\r
30591     },\r
30592 \r
30593 \r
30594     checkDesignMode : function(){\r
30595         if(this.wrap && this.wrap.dom.offsetWidth){\r
30596             var doc = this.getDoc();\r
30597             if(!doc){\r
30598                 return;\r
30599             }\r
30600             if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){\r
30601                 this.initFrame();\r
30602             }\r
30603         }\r
30604     },\r
30605 \r
30606     // private\r
30607     onResize : function(w, h){\r
30608         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);\r
30609         if(this.el && this.iframe){\r
30610             if(typeof w == 'number'){\r
30611                 var aw = w - this.wrap.getFrameWidth('lr');\r
30612                 this.el.setWidth(this.adjustWidth('textarea', aw));\r
30613                 this.iframe.style.width = Math.max(aw, 0) + 'px';\r
30614             }\r
30615             if(typeof h == 'number'){\r
30616                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();\r
30617                 this.el.setHeight(this.adjustWidth('textarea', ah));\r
30618                 this.iframe.style.height = Math.max(ah, 0) + 'px';\r
30619                 if(this.doc){\r
30620                     this.getEditorBody().style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';\r
30621                 }\r
30622             }\r
30623         }\r
30624     },\r
30625 \r
30626     \r
30627     toggleSourceEdit : function(sourceEditMode){\r
30628         if(sourceEditMode === undefined){\r
30629             sourceEditMode = !this.sourceEditMode;\r
30630         }\r
30631         this.sourceEditMode = sourceEditMode === true;\r
30632         var btn = this.tb.items.get('sourceedit');\r
30633         if(btn.pressed !== this.sourceEditMode){\r
30634             btn.toggle(this.sourceEditMode);\r
30635             return;\r
30636         }\r
30637         if(this.sourceEditMode){\r
30638             this.tb.items.each(function(item){\r
30639                 if(item.itemId != 'sourceedit'){\r
30640                     item.disable();\r
30641                 }\r
30642             });\r
30643             this.syncValue();\r
30644             this.iframe.className = 'x-hidden';\r
30645             this.el.removeClass('x-hidden');\r
30646             this.el.dom.removeAttribute('tabIndex');\r
30647             this.el.focus();\r
30648         }else{\r
30649             if(this.initialized){\r
30650                 this.tb.items.each(function(item){\r
30651                     item.enable();\r
30652                 });\r
30653             }\r
30654             this.pushValue();\r
30655             this.iframe.className = '';\r
30656             this.el.addClass('x-hidden');\r
30657             this.el.dom.setAttribute('tabIndex', -1);\r
30658             this.deferFocus();\r
30659         }\r
30660         var lastSize = this.lastSize;\r
30661         if(lastSize){\r
30662             delete this.lastSize;\r
30663             this.setSize(lastSize);\r
30664         }\r
30665         this.fireEvent('editmodechange', this, this.sourceEditMode);\r
30666     },\r
30667 \r
30668     // private used internally\r
30669     createLink : function(){\r
30670         var url = prompt(this.createLinkText, this.defaultLinkValue);\r
30671         if(url && url != 'http:/'+'/'){\r
30672             this.relayCmd('createlink', url);\r
30673         }\r
30674     },\r
30675 \r
30676     // private (for BoxComponent)\r
30677     adjustSize : Ext.BoxComponent.prototype.adjustSize,\r
30678 \r
30679     // private (for BoxComponent)\r
30680     getResizeEl : function(){\r
30681         return this.wrap;\r
30682     },\r
30683 \r
30684     // private (for BoxComponent)\r
30685     getPositionEl : function(){\r
30686         return this.wrap;\r
30687     },\r
30688 \r
30689     // private\r
30690     initEvents : function(){\r
30691         this.originalValue = this.getValue();\r
30692     },\r
30693 \r
30694     \r
30695     markInvalid : Ext.emptyFn,\r
30696     \r
30697     \r
30698     clearInvalid : Ext.emptyFn,\r
30699 \r
30700     // docs inherit from Field\r
30701     setValue : function(v){\r
30702         Ext.form.HtmlEditor.superclass.setValue.call(this, v);\r
30703         this.pushValue();\r
30704     },\r
30705 \r
30706     \r
30707     cleanHtml : function(html){\r
30708         html = String(html);\r
30709         if(html.length > 5){\r
30710             if(Ext.isSafari){ // strip safari nonsense\r
30711                 html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');\r
30712             }\r
30713         }\r
30714         if(html == '&nbsp;'){\r
30715             html = '';\r
30716         }\r
30717         return html;\r
30718     },\r
30719 \r
30720     \r
30721     syncValue : function(){\r
30722         if(this.initialized){\r
30723             var bd = this.getEditorBody();\r
30724             var html = bd.innerHTML;\r
30725             if(Ext.isSafari){\r
30726                 var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!\r
30727                 var m = bs.match(/text-align:(.*?);/i);\r
30728                 if(m && m[1]){\r
30729                     html = '<div style="'+m[0]+'">' + html + '</div>';\r
30730                 }\r
30731             }\r
30732             html = this.cleanHtml(html);\r
30733             if(this.fireEvent('beforesync', this, html) !== false){\r
30734                 this.el.dom.value = html;\r
30735                 this.fireEvent('sync', this, html);\r
30736             }\r
30737         }\r
30738     },\r
30739     \r
30740     //docs inherit from Field\r
30741     getValue : function() {\r
30742         this.syncValue();\r
30743         return Ext.form.HtmlEditor.superclass.getValue.call(this);\r
30744     },\r
30745 \r
30746 \r
30747     \r
30748     pushValue : function(){\r
30749         if(this.initialized){\r
30750             var v = this.el.dom.value;\r
30751             if(!this.activated && v.length < 1){\r
30752                 v = '&nbsp;';\r
30753             }\r
30754             if(this.fireEvent('beforepush', this, v) !== false){\r
30755                 this.getEditorBody().innerHTML = v;\r
30756                 this.fireEvent('push', this, v);\r
30757             }\r
30758         }\r
30759     },\r
30760 \r
30761     // private\r
30762     deferFocus : function(){\r
30763         this.focus.defer(10, this);\r
30764     },\r
30765 \r
30766     // docs inherit from Field\r
30767     focus : function(){\r
30768         if(this.win && !this.sourceEditMode){\r
30769             this.win.focus();\r
30770         }else{\r
30771             this.el.focus();\r
30772         }\r
30773     },\r
30774 \r
30775     // private\r
30776     initEditor : function(){\r
30777         var dbody = this.getEditorBody();\r
30778         var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');\r
30779         ss['background-attachment'] = 'fixed'; // w3c\r
30780         dbody.bgProperties = 'fixed'; // ie\r
30781 \r
30782         Ext.DomHelper.applyStyles(dbody, ss);\r
30783 \r
30784         if(this.doc){\r
30785             try{\r
30786                 Ext.EventManager.removeAll(this.doc);\r
30787             }catch(e){}\r
30788         }\r
30789 \r
30790         this.doc = this.getDoc();\r
30791 \r
30792         Ext.EventManager.on(this.doc, {\r
30793             'mousedown': this.onEditorEvent,\r
30794             'dblclick': this.onEditorEvent,\r
30795             'click': this.onEditorEvent,\r
30796             'keyup': this.onEditorEvent,\r
30797             buffer:100,\r
30798             scope: this\r
30799         });\r
30800 \r
30801         if(Ext.isGecko){\r
30802             Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);\r
30803         }\r
30804         if(Ext.isIE || Ext.isSafari || Ext.isOpera){\r
30805             Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);\r
30806         }\r
30807         this.initialized = true;\r
30808 \r
30809         this.fireEvent('initialize', this);\r
30810 \r
30811         this.doc.editorInitialized = true;\r
30812 \r
30813         this.pushValue();\r
30814     },\r
30815 \r
30816     // private\r
30817     onDestroy : function(){\r
30818         if(this.monitorTask){\r
30819             Ext.TaskMgr.stop(this.monitorTask);\r
30820         }\r
30821         if(this.rendered){\r
30822             this.tb.items.each(function(item){\r
30823                 if(item.menu){\r
30824                     item.menu.removeAll();\r
30825                     if(item.menu.el){\r
30826                         item.menu.el.destroy();\r
30827                     }\r
30828                 }\r
30829                 item.destroy();\r
30830             });\r
30831             this.wrap.dom.innerHTML = '';\r
30832             this.wrap.remove();\r
30833         }\r
30834     },\r
30835 \r
30836     // private\r
30837     onFirstFocus : function(){\r
30838         this.activated = true;\r
30839         this.tb.items.each(function(item){\r
30840            item.enable();\r
30841         });\r
30842         if(Ext.isGecko){ // prevent silly gecko errors\r
30843             this.win.focus();\r
30844             var s = this.win.getSelection();\r
30845             if(!s.focusNode || s.focusNode.nodeType != 3){\r
30846                 var r = s.getRangeAt(0);\r
30847                 r.selectNodeContents(this.getEditorBody());\r
30848                 r.collapse(true);\r
30849                 this.deferFocus();\r
30850             }\r
30851             try{\r
30852                 this.execCmd('useCSS', true);\r
30853                 this.execCmd('styleWithCSS', false);\r
30854             }catch(e){}\r
30855         }\r
30856         this.fireEvent('activate', this);\r
30857     },\r
30858 \r
30859     // private\r
30860     adjustFont: function(btn){\r
30861         var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;\r
30862 \r
30863         var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);\r
30864         if(Ext.isSafari3 || Ext.isAir){\r
30865             // Safari 3 values\r
30866             // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px\r
30867             if(v <= 10){\r
30868                 v = 1 + adjust;\r
30869             }else if(v <= 13){\r
30870                 v = 2 + adjust;\r
30871             }else if(v <= 16){\r
30872                 v = 3 + adjust;\r
30873             }else if(v <= 18){\r
30874                 v = 4 + adjust;\r
30875             }else if(v <= 24){\r
30876                 v = 5 + adjust;\r
30877             }else {\r
30878                 v = 6 + adjust;\r
30879             }\r
30880             v = v.constrain(1, 6);\r
30881         }else{\r
30882             if(Ext.isSafari){ // safari\r
30883                 adjust *= 2;\r
30884             }\r
30885             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);\r
30886         }\r
30887         this.execCmd('FontSize', v);\r
30888     },\r
30889 \r
30890     // private\r
30891     onEditorEvent : function(e){\r
30892         this.updateToolbar();\r
30893     },\r
30894 \r
30895 \r
30896     \r
30897     updateToolbar: function(){\r
30898 \r
30899         if(!this.activated){\r
30900             this.onFirstFocus();\r
30901             return;\r
30902         }\r
30903 \r
30904         var btns = this.tb.items.map, doc = this.doc;\r
30905 \r
30906         if(this.enableFont && !Ext.isSafari2){\r
30907             var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();\r
30908             if(name != this.fontSelect.dom.value){\r
30909                 this.fontSelect.dom.value = name;\r
30910             }\r
30911         }\r
30912         if(this.enableFormat){\r
30913             btns.bold.toggle(doc.queryCommandState('bold'));\r
30914             btns.italic.toggle(doc.queryCommandState('italic'));\r
30915             btns.underline.toggle(doc.queryCommandState('underline'));\r
30916         }\r
30917         if(this.enableAlignments){\r
30918             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));\r
30919             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));\r
30920             btns.justifyright.toggle(doc.queryCommandState('justifyright'));\r
30921         }\r
30922         if(!Ext.isSafari2 && this.enableLists){\r
30923             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));\r
30924             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));\r
30925         }\r
30926         \r
30927         Ext.menu.MenuMgr.hideAll();\r
30928 \r
30929         this.syncValue();\r
30930     },\r
30931 \r
30932     // private\r
30933     relayBtnCmd : function(btn){\r
30934         this.relayCmd(btn.itemId);\r
30935     },\r
30936 \r
30937     \r
30938     relayCmd : function(cmd, value){\r
30939         (function(){\r
30940             this.focus();\r
30941             this.execCmd(cmd, value);\r
30942             this.updateToolbar();\r
30943         }).defer(10, this);\r
30944     },\r
30945 \r
30946     \r
30947     execCmd : function(cmd, value){\r
30948         this.doc.execCommand(cmd, false, value === undefined ? null : value);\r
30949         this.syncValue();\r
30950     },\r
30951 \r
30952     // private\r
30953     applyCommand : function(e){\r
30954         if(e.ctrlKey){\r
30955             var c = e.getCharCode(), cmd;\r
30956             if(c > 0){\r
30957                 c = String.fromCharCode(c);\r
30958                 switch(c){\r
30959                     case 'b':\r
30960                         cmd = 'bold';\r
30961                     break;\r
30962                     case 'i':\r
30963                         cmd = 'italic';\r
30964                     break;\r
30965                     case 'u':\r
30966                         cmd = 'underline';\r
30967                     break;\r
30968                 }\r
30969                 if(cmd){\r
30970                     this.win.focus();\r
30971                     this.execCmd(cmd);\r
30972                     this.deferFocus();\r
30973                     e.preventDefault();\r
30974                 }\r
30975             }\r
30976         }\r
30977     },\r
30978 \r
30979     \r
30980     insertAtCursor : function(text){\r
30981         if(!this.activated){\r
30982             return;\r
30983         }\r
30984         if(Ext.isIE){\r
30985             this.win.focus();\r
30986             var r = this.doc.selection.createRange();\r
30987             if(r){\r
30988                 r.collapse(true);\r
30989                 r.pasteHTML(text);\r
30990                 this.syncValue();\r
30991                 this.deferFocus();\r
30992             }\r
30993         }else if(Ext.isGecko || Ext.isOpera){\r
30994             this.win.focus();\r
30995             this.execCmd('InsertHTML', text);\r
30996             this.deferFocus();\r
30997         }else if(Ext.isSafari){\r
30998             this.execCmd('InsertText', text);\r
30999             this.deferFocus();\r
31000         }\r
31001     },\r
31002 \r
31003     // private\r
31004     fixKeys : function(){ // load time branching for fastest keydown performance\r
31005         if(Ext.isIE){\r
31006             return function(e){\r
31007                 var k = e.getKey(), r;\r
31008                 if(k == e.TAB){\r
31009                     e.stopEvent();\r
31010                     r = this.doc.selection.createRange();\r
31011                     if(r){\r
31012                         r.collapse(true);\r
31013                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');\r
31014                         this.deferFocus();\r
31015                     }\r
31016                 }else if(k == e.ENTER){\r
31017                     r = this.doc.selection.createRange();\r
31018                     if(r){\r
31019                         var target = r.parentElement();\r
31020                         if(!target || target.tagName.toLowerCase() != 'li'){\r
31021                             e.stopEvent();\r
31022                             r.pasteHTML('<br />');\r
31023                             r.collapse(false);\r
31024                             r.select();\r
31025                         }\r
31026                     }\r
31027                 }\r
31028             };\r
31029         }else if(Ext.isOpera){\r
31030             return function(e){\r
31031                 var k = e.getKey();\r
31032                 if(k == e.TAB){\r
31033                     e.stopEvent();\r
31034                     this.win.focus();\r
31035                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');\r
31036                     this.deferFocus();\r
31037                 }\r
31038             };\r
31039         }else if(Ext.isSafari){\r
31040             return function(e){\r
31041                 var k = e.getKey();\r
31042                 if(k == e.TAB){\r
31043                     e.stopEvent();\r
31044                     this.execCmd('InsertText','\t');\r
31045                     this.deferFocus();\r
31046                 }\r
31047              };\r
31048         }\r
31049     }(),\r
31050 \r
31051     \r
31052     getToolbar : function(){\r
31053         return this.tb;\r
31054     },\r
31055 \r
31056     \r
31057     buttonTips : {\r
31058         bold : {\r
31059             title: 'Bold (Ctrl+B)',\r
31060             text: 'Make the selected text bold.',\r
31061             cls: 'x-html-editor-tip'\r
31062         },\r
31063         italic : {\r
31064             title: 'Italic (Ctrl+I)',\r
31065             text: 'Make the selected text italic.',\r
31066             cls: 'x-html-editor-tip'\r
31067         },\r
31068         underline : {\r
31069             title: 'Underline (Ctrl+U)',\r
31070             text: 'Underline the selected text.',\r
31071             cls: 'x-html-editor-tip'\r
31072         },\r
31073         increasefontsize : {\r
31074             title: 'Grow Text',\r
31075             text: 'Increase the font size.',\r
31076             cls: 'x-html-editor-tip'\r
31077         },\r
31078         decreasefontsize : {\r
31079             title: 'Shrink Text',\r
31080             text: 'Decrease the font size.',\r
31081             cls: 'x-html-editor-tip'\r
31082         },\r
31083         backcolor : {\r
31084             title: 'Text Highlight Color',\r
31085             text: 'Change the background color of the selected text.',\r
31086             cls: 'x-html-editor-tip'\r
31087         },\r
31088         forecolor : {\r
31089             title: 'Font Color',\r
31090             text: 'Change the color of the selected text.',\r
31091             cls: 'x-html-editor-tip'\r
31092         },\r
31093         justifyleft : {\r
31094             title: 'Align Text Left',\r
31095             text: 'Align text to the left.',\r
31096             cls: 'x-html-editor-tip'\r
31097         },\r
31098         justifycenter : {\r
31099             title: 'Center Text',\r
31100             text: 'Center text in the editor.',\r
31101             cls: 'x-html-editor-tip'\r
31102         },\r
31103         justifyright : {\r
31104             title: 'Align Text Right',\r
31105             text: 'Align text to the right.',\r
31106             cls: 'x-html-editor-tip'\r
31107         },\r
31108         insertunorderedlist : {\r
31109             title: 'Bullet List',\r
31110             text: 'Start a bulleted list.',\r
31111             cls: 'x-html-editor-tip'\r
31112         },\r
31113         insertorderedlist : {\r
31114             title: 'Numbered List',\r
31115             text: 'Start a numbered list.',\r
31116             cls: 'x-html-editor-tip'\r
31117         },\r
31118         createlink : {\r
31119             title: 'Hyperlink',\r
31120             text: 'Make the selected text a hyperlink.',\r
31121             cls: 'x-html-editor-tip'\r
31122         },\r
31123         sourceedit : {\r
31124             title: 'Source Edit',\r
31125             text: 'Switch to source editing mode.',\r
31126             cls: 'x-html-editor-tip'\r
31127         }\r
31128     }\r
31129 \r
31130     // hide stuff that is not compatible\r
31131     \r
31132     \r
31133     \r
31134     \r
31135     \r
31136     \r
31137     \r
31138     \r
31139     \r
31140     \r
31141     \r
31142     \r
31143     \r
31144     \r
31145     \r
31146     \r
31147     \r
31148     \r
31149     \r
31150     \r
31151     \r
31152     \r
31153     \r
31154     \r
31155     \r
31156     \r
31157     \r
31158     \r
31159     \r
31160     \r
31161     \r
31162     \r
31163     \r
31164 });\r
31165 Ext.reg('htmleditor', Ext.form.HtmlEditor);\r
31166 \r
31167 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {\r
31168     \r
31169     minValue : null,\r
31170     \r
31171     maxValue : null,\r
31172     \r
31173     minText : "The time in this field must be equal to or after {0}",\r
31174     \r
31175     maxText : "The time in this field must be equal to or before {0}",\r
31176     \r
31177     invalidText : "{0} is not a valid time",\r
31178     \r
31179     format : "g:i A",\r
31180     \r
31181     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",\r
31182     \r
31183     increment: 15,\r
31184 \r
31185     // private override\r
31186     mode: 'local',\r
31187     // private override\r
31188     triggerAction: 'all',\r
31189     // private override\r
31190     typeAhead: false,\r
31191     \r
31192     // private - This is the date to use when generating time values in the absence of either minValue\r
31193     // or maxValue.  Using the current date causes DST issues on DST boundary dates, so this is an \r
31194     // arbitrary "safe" date that can be any date aside from DST boundary dates.\r
31195     initDate: '1/1/2008',\r
31196 \r
31197     // private\r
31198     initComponent : function(){\r
31199         Ext.form.TimeField.superclass.initComponent.call(this);\r
31200 \r
31201         if(typeof this.minValue == "string"){\r
31202             this.minValue = this.parseDate(this.minValue);\r
31203         }\r
31204         if(typeof this.maxValue == "string"){\r
31205             this.maxValue = this.parseDate(this.maxValue);\r
31206         }\r
31207 \r
31208         if(!this.store){\r
31209             var min = this.parseDate(this.minValue);\r
31210             if(!min){\r
31211                 min = new Date(this.initDate).clearTime();\r
31212             }\r
31213             var max = this.parseDate(this.maxValue);\r
31214             if(!max){\r
31215                 max = new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);\r
31216             }\r
31217             var times = [];\r
31218             while(min <= max){\r
31219                 times.push([min.dateFormat(this.format)]);\r
31220                 min = min.add('mi', this.increment);\r
31221             }\r
31222             this.store = new Ext.data.SimpleStore({\r
31223                 fields: ['text'],\r
31224                 data : times\r
31225             });\r
31226             this.displayField = 'text';\r
31227         }\r
31228     },\r
31229 \r
31230     // inherited docs\r
31231     getValue : function(){\r
31232         var v = Ext.form.TimeField.superclass.getValue.call(this);\r
31233         return this.formatDate(this.parseDate(v)) || '';\r
31234     },\r
31235 \r
31236     // inherited docs\r
31237     setValue : function(value){\r
31238         Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));\r
31239     },\r
31240 \r
31241     // private overrides\r
31242     validateValue : Ext.form.DateField.prototype.validateValue,\r
31243     parseDate : Ext.form.DateField.prototype.parseDate,\r
31244     formatDate : Ext.form.DateField.prototype.formatDate,\r
31245 \r
31246     // private\r
31247     beforeBlur : function(){\r
31248         var v = this.parseDate(this.getRawValue());\r
31249         if(v){\r
31250             this.setValue(v.dateFormat(this.format));\r
31251         }\r
31252     }\r
31253 \r
31254     \r
31255     \r
31256     \r
31257     \r
31258 });\r
31259 Ext.reg('timefield', Ext.form.TimeField);\r
31260 \r
31261 Ext.form.Label = Ext.extend(Ext.BoxComponent, {\r
31262     \r
31263     \r
31264     \r
31265 \r
31266     // private\r
31267     onRender : function(ct, position){\r
31268         if(!this.el){\r
31269             this.el = document.createElement('label');\r
31270             this.el.id = this.getId();\r
31271             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');\r
31272             if(this.forId){\r
31273                 this.el.setAttribute('for', this.forId);\r
31274             }\r
31275         }\r
31276         Ext.form.Label.superclass.onRender.call(this, ct, position);\r
31277     },\r
31278     \r
31279     \r
31280     setText: function(t, encode){\r
31281         this.text = t;\r
31282         if(this.rendered){\r
31283             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;\r
31284         }\r
31285         return this;\r
31286     }\r
31287 });\r
31288 \r
31289 Ext.reg('label', Ext.form.Label);\r
31290 \r
31291 Ext.form.Action = function(form, options){\r
31292     this.form = form;\r
31293     this.options = options || {};\r
31294 };\r
31295 \r
31296 \r
31297 Ext.form.Action.CLIENT_INVALID = 'client';\r
31298 \r
31299 Ext.form.Action.SERVER_INVALID = 'server';\r
31300 \r
31301 Ext.form.Action.CONNECT_FAILURE = 'connect';\r
31302 \r
31303 Ext.form.Action.LOAD_FAILURE = 'load';\r
31304 \r
31305 Ext.form.Action.prototype = {\r
31306 \r
31307 \r
31308 \r
31309 \r
31310 \r
31311 \r
31312 \r
31313 \r
31314 \r
31315 \r
31316 \r
31317 \r
31318     type : 'default',\r
31319 \r
31320 \r
31321     // interface method\r
31322     run : function(options){\r
31323 \r
31324     },\r
31325 \r
31326     // interface method\r
31327     success : function(response){\r
31328 \r
31329     },\r
31330 \r
31331     // interface method\r
31332     handleResponse : function(response){\r
31333 \r
31334     },\r
31335 \r
31336     // default connection failure\r
31337     failure : function(response){\r
31338         this.response = response;\r
31339         this.failureType = Ext.form.Action.CONNECT_FAILURE;\r
31340         this.form.afterAction(this, false);\r
31341     },\r
31342 \r
31343     // private\r
31344     processResponse : function(response){\r
31345         this.response = response;\r
31346         if(!response.responseText){\r
31347             return true;\r
31348         }\r
31349         this.result = this.handleResponse(response);\r
31350         return this.result;\r
31351     },\r
31352 \r
31353     // utility functions used internally\r
31354     getUrl : function(appendParams){\r
31355         var url = this.options.url || this.form.url || this.form.el.dom.action;\r
31356         if(appendParams){\r
31357             var p = this.getParams();\r
31358             if(p){\r
31359                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;\r
31360             }\r
31361         }\r
31362         return url;\r
31363     },\r
31364 \r
31365     // private\r
31366     getMethod : function(){\r
31367         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();\r
31368     },\r
31369 \r
31370     // private\r
31371     getParams : function(){\r
31372         var bp = this.form.baseParams;\r
31373         var p = this.options.params;\r
31374         if(p){\r
31375             if(typeof p == "object"){\r
31376                 p = Ext.urlEncode(Ext.applyIf(p, bp));\r
31377             }else if(typeof p == 'string' && bp){\r
31378                 p += '&' + Ext.urlEncode(bp);\r
31379             }\r
31380         }else if(bp){\r
31381             p = Ext.urlEncode(bp);\r
31382         }\r
31383         return p;\r
31384     },\r
31385 \r
31386     // private\r
31387     createCallback : function(opts){\r
31388                 var opts = opts || {};\r
31389         return {\r
31390             success: this.success,\r
31391             failure: this.failure,\r
31392             scope: this,\r
31393             timeout: (opts.timeout*1000) || (this.form.timeout*1000),\r
31394             upload: this.form.fileUpload ? this.success : undefined\r
31395         };\r
31396     }\r
31397 };\r
31398 \r
31399 \r
31400 Ext.form.Action.Submit = function(form, options){\r
31401     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);\r
31402 };\r
31403 \r
31404 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {\r
31405     \r
31406     \r
31407     type : 'submit',\r
31408 \r
31409     // private\r
31410     run : function(){\r
31411         var o = this.options;\r
31412         var method = this.getMethod();\r
31413         var isGet = method == 'GET';\r
31414         if(o.clientValidation === false || this.form.isValid()){\r
31415             Ext.Ajax.request(Ext.apply(this.createCallback(o), {\r
31416                 form:this.form.el.dom,\r
31417                 url:this.getUrl(isGet),\r
31418                 method: method,\r
31419                 headers: o.headers,\r
31420                 params:!isGet ? this.getParams() : null,\r
31421                 isUpload: this.form.fileUpload\r
31422             }));\r
31423         }else if (o.clientValidation !== false){ // client validation failed\r
31424             this.failureType = Ext.form.Action.CLIENT_INVALID;\r
31425             this.form.afterAction(this, false);\r
31426         }\r
31427     },\r
31428 \r
31429     // private\r
31430     success : function(response){\r
31431         var result = this.processResponse(response);\r
31432         if(result === true || result.success){\r
31433             this.form.afterAction(this, true);\r
31434             return;\r
31435         }\r
31436         if(result.errors){\r
31437             this.form.markInvalid(result.errors);\r
31438             this.failureType = Ext.form.Action.SERVER_INVALID;\r
31439         }\r
31440         this.form.afterAction(this, false);\r
31441     },\r
31442 \r
31443     // private\r
31444     handleResponse : function(response){\r
31445         if(this.form.errorReader){\r
31446             var rs = this.form.errorReader.read(response);\r
31447             var errors = [];\r
31448             if(rs.records){\r
31449                 for(var i = 0, len = rs.records.length; i < len; i++) {\r
31450                     var r = rs.records[i];\r
31451                     errors[i] = r.data;\r
31452                 }\r
31453             }\r
31454             if(errors.length < 1){\r
31455                 errors = null;\r
31456             }\r
31457             return {\r
31458                 success : rs.success,\r
31459                 errors : errors\r
31460             };\r
31461         }\r
31462         return Ext.decode(response.responseText);\r
31463     }\r
31464 });\r
31465 \r
31466 \r
31467 \r
31468 Ext.form.Action.Load = function(form, options){\r
31469     Ext.form.Action.Load.superclass.constructor.call(this, form, options);\r
31470     this.reader = this.form.reader;\r
31471 };\r
31472 \r
31473 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {\r
31474     // private\r
31475     type : 'load',\r
31476 \r
31477     // private\r
31478     run : function(){\r
31479         Ext.Ajax.request(Ext.apply(\r
31480                 this.createCallback(this.options), {\r
31481                     method:this.getMethod(),\r
31482                     url:this.getUrl(false),\r
31483                     headers: this.options.headers,\r
31484                     params:this.getParams()\r
31485         }));\r
31486     },\r
31487 \r
31488     // private\r
31489     success : function(response){\r
31490         var result = this.processResponse(response);\r
31491         if(result === true || !result.success || !result.data){\r
31492             this.failureType = Ext.form.Action.LOAD_FAILURE;\r
31493             this.form.afterAction(this, false);\r
31494             return;\r
31495         }\r
31496         this.form.clearInvalid();\r
31497         this.form.setValues(result.data);\r
31498         this.form.afterAction(this, true);\r
31499     },\r
31500 \r
31501     // private\r
31502     handleResponse : function(response){\r
31503         if(this.form.reader){\r
31504             var rs = this.form.reader.read(response);\r
31505             var data = rs.records && rs.records[0] ? rs.records[0].data : null;\r
31506             return {\r
31507                 success : rs.success,\r
31508                 data : data\r
31509             };\r
31510         }\r
31511         return Ext.decode(response.responseText);\r
31512     }\r
31513 });\r
31514 \r
31515 Ext.form.Action.ACTION_TYPES = {\r
31516     'load' : Ext.form.Action.Load,\r
31517     'submit' : Ext.form.Action.Submit\r
31518 };\r
31519 \r
31520 \r
31521 Ext.form.VTypes = function(){\r
31522     // closure these in so they are only created once.\r
31523     var alpha = /^[a-zA-Z_]+$/;\r
31524     var alphanum = /^[a-zA-Z0-9_]+$/;\r
31525     var email = /^([\w]+)(\.[\w]+)*@([\w\-]+\.){1,5}([A-Za-z]){2,4}$/;\r
31526     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;\r
31527 \r
31528     // All these messages and functions are configurable\r
31529     return {\r
31530         \r
31531         'email' : function(v){\r
31532             return email.test(v);\r
31533         },\r
31534         \r
31535         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',\r
31536         \r
31537         'emailMask' : /[a-z0-9_\.\-@]/i,\r
31538 \r
31539         \r
31540         'url' : function(v){\r
31541             return url.test(v);\r
31542         },\r
31543         \r
31544         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',\r
31545         \r
31546         \r
31547         'alpha' : function(v){\r
31548             return alpha.test(v);\r
31549         },\r
31550         \r
31551         'alphaText' : 'This field should only contain letters and _',\r
31552         \r
31553         'alphaMask' : /[a-z_]/i,\r
31554 \r
31555         \r
31556         'alphanum' : function(v){\r
31557             return alphanum.test(v);\r
31558         },\r
31559         \r
31560         'alphanumText' : 'This field should only contain letters, numbers and _',\r
31561         \r
31562         'alphanumMask' : /[a-z0-9_]/i\r
31563     };\r
31564 }();\r
31565 \r
31566 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {\r
31567     \r
31568     \r
31569     \r
31570     \r
31571     \r
31572     \r
31573     \r
31574     \r
31575     \r
31576     \r
31577     \r
31578     \r
31579 \r
31580     \r
31581     ddText : "{0} selected row{1}",\r
31582     \r
31583     minColumnWidth : 25,\r
31584     \r
31585     trackMouseOver : true,\r
31586     \r
31587     enableDragDrop : false,\r
31588     \r
31589     enableColumnMove : true,\r
31590     \r
31591     enableColumnHide : true,\r
31592     \r
31593     enableHdMenu : true,\r
31594     \r
31595     stripeRows : false,\r
31596     \r
31597     autoExpandColumn : false,\r
31598     \r
31599     autoExpandMin : 50,\r
31600     \r
31601     autoExpandMax : 1000,\r
31602     \r
31603     view : null,\r
31604     \r
31605     loadMask : false,\r
31606 \r
31607     \r
31608     deferRowRender : true,\r
31609 \r
31610     // private\r
31611     rendered : false,\r
31612     // private\r
31613     viewReady: false,\r
31614     \r
31615     stateEvents: ["columnmove", "columnresize", "sortchange"],\r
31616 \r
31617     // private\r
31618     initComponent : function(){\r
31619         Ext.grid.GridPanel.superclass.initComponent.call(this);\r
31620 \r
31621         // override any provided value since it isn't valid\r
31622         this.autoScroll = false;\r
31623         this.autoWidth = false;\r
31624 \r
31625         if(Ext.isArray(this.columns)){\r
31626             this.colModel = new Ext.grid.ColumnModel(this.columns);\r
31627             delete this.columns;\r
31628         }\r
31629 \r
31630         // check and correct shorthanded configs\r
31631         if(this.ds){\r
31632             this.store = this.ds;\r
31633             delete this.ds;\r
31634         }\r
31635         if(this.cm){\r
31636             this.colModel = this.cm;\r
31637             delete this.cm;\r
31638         }\r
31639         if(this.sm){\r
31640             this.selModel = this.sm;\r
31641             delete this.sm;\r
31642         }\r
31643         this.store = Ext.StoreMgr.lookup(this.store);\r
31644 \r
31645         this.addEvents(\r
31646             // raw events\r
31647             \r
31648             "click",\r
31649             \r
31650             "dblclick",\r
31651             \r
31652             "contextmenu",\r
31653             \r
31654             "mousedown",\r
31655             \r
31656             "mouseup",\r
31657             \r
31658             "mouseover",\r
31659             \r
31660             "mouseout",\r
31661             \r
31662             "keypress",\r
31663             \r
31664             "keydown",\r
31665 \r
31666             // custom events\r
31667             \r
31668             "cellmousedown",\r
31669             \r
31670             "rowmousedown",\r
31671             \r
31672             "headermousedown",\r
31673 \r
31674             \r
31675             "cellclick",\r
31676             \r
31677             "celldblclick",\r
31678             \r
31679             "rowclick",\r
31680             \r
31681             "rowdblclick",\r
31682             \r
31683             "headerclick",\r
31684             \r
31685             "headerdblclick",\r
31686             \r
31687             "rowcontextmenu",\r
31688             \r
31689             "cellcontextmenu",\r
31690             \r
31691             "headercontextmenu",\r
31692             \r
31693             "bodyscroll",\r
31694             \r
31695             "columnresize",\r
31696             \r
31697             "columnmove",\r
31698             \r
31699             "sortchange"\r
31700         );\r
31701     },\r
31702 \r
31703     // private\r
31704     onRender : function(ct, position){\r
31705         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);\r
31706 \r
31707         var c = this.body;\r
31708 \r
31709         this.el.addClass('x-grid-panel');\r
31710 \r
31711         var view = this.getView();\r
31712         view.init(this);\r
31713 \r
31714         c.on("mousedown", this.onMouseDown, this);\r
31715         c.on("click", this.onClick, this);\r
31716         c.on("dblclick", this.onDblClick, this);\r
31717         c.on("contextmenu", this.onContextMenu, this);\r
31718         c.on("keydown", this.onKeyDown, this);\r
31719 \r
31720         this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);\r
31721 \r
31722         this.getSelectionModel().init(this);\r
31723         this.view.render();\r
31724     },\r
31725 \r
31726     // private\r
31727     initEvents : function(){\r
31728         Ext.grid.GridPanel.superclass.initEvents.call(this);\r
31729 \r
31730         if(this.loadMask){\r
31731             this.loadMask = new Ext.LoadMask(this.bwrap,\r
31732                     Ext.apply({store:this.store}, this.loadMask));\r
31733         }\r
31734     },\r
31735 \r
31736     initStateEvents : function(){\r
31737         Ext.grid.GridPanel.superclass.initStateEvents.call(this);\r
31738         this.colModel.on('hiddenchange', this.saveState, this, {delay: 100});\r
31739     },\r
31740 \r
31741     applyState : function(state){\r
31742         var cm = this.colModel;\r
31743         var cs = state.columns;\r
31744         if(cs){\r
31745             for(var i = 0, len = cs.length; i < len; i++){\r
31746                 var s = cs[i];\r
31747                 var c = cm.getColumnById(s.id);\r
31748                 if(c){\r
31749                     c.hidden = s.hidden;\r
31750                     c.width = s.width;\r
31751                     var oldIndex = cm.getIndexById(s.id);\r
31752                     if(oldIndex != i){\r
31753                         cm.moveColumn(oldIndex, i);\r
31754                     }\r
31755                 }\r
31756             }\r
31757         }\r
31758         if(state.sort){\r
31759             this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);\r
31760         }\r
31761     },\r
31762 \r
31763     getState : function(){\r
31764         var o = {columns: []};\r
31765         for(var i = 0, c; c = this.colModel.config[i]; i++){\r
31766             o.columns[i] = {\r
31767                 id: c.id,\r
31768                 width: c.width\r
31769             };\r
31770             if(c.hidden){\r
31771                 o.columns[i].hidden = true;\r
31772             }\r
31773         }\r
31774         var ss = this.store.getSortState();\r
31775         if(ss){\r
31776             o.sort = ss;\r
31777         }\r
31778         return o;\r
31779     },\r
31780 \r
31781     // private\r
31782     afterRender : function(){\r
31783         Ext.grid.GridPanel.superclass.afterRender.call(this);\r
31784         this.view.layout();\r
31785         if(this.deferRowRender){\r
31786             this.view.afterRender.defer(10, this.view);\r
31787         }else{\r
31788             this.view.afterRender();\r
31789         }\r
31790         this.viewReady = true;\r
31791     },\r
31792 \r
31793     \r
31794     reconfigure : function(store, colModel){\r
31795         if(this.loadMask){\r
31796             this.loadMask.destroy();\r
31797             this.loadMask = new Ext.LoadMask(this.bwrap,\r
31798                     Ext.apply({store:store}, this.initialConfig.loadMask));\r
31799         }\r
31800         this.view.bind(store, colModel);\r
31801         this.store = store;\r
31802         this.colModel = colModel;\r
31803         if(this.rendered){\r
31804             this.view.refresh(true);\r
31805         }\r
31806     },\r
31807 \r
31808     // private\r
31809     onKeyDown : function(e){\r
31810         this.fireEvent("keydown", e);\r
31811     },\r
31812 \r
31813     // private\r
31814     onDestroy : function(){\r
31815         if(this.rendered){\r
31816             if(this.loadMask){\r
31817                 this.loadMask.destroy();\r
31818             }\r
31819             var c = this.body;\r
31820             c.removeAllListeners();\r
31821             this.view.destroy();\r
31822             c.update("");\r
31823         }\r
31824         this.colModel.purgeListeners();\r
31825         Ext.grid.GridPanel.superclass.onDestroy.call(this);\r
31826     },\r
31827 \r
31828     // private\r
31829     processEvent : function(name, e){\r
31830         this.fireEvent(name, e);\r
31831         var t = e.getTarget();\r
31832         var v = this.view;\r
31833         var header = v.findHeaderIndex(t);\r
31834         if(header !== false){\r
31835             this.fireEvent("header" + name, this, header, e);\r
31836         }else{\r
31837             var row = v.findRowIndex(t);\r
31838             var cell = v.findCellIndex(t);\r
31839             if(row !== false){\r
31840                 this.fireEvent("row" + name, this, row, e);\r
31841                 if(cell !== false){\r
31842                     this.fireEvent("cell" + name, this, row, cell, e);\r
31843                 }\r
31844             }\r
31845         }\r
31846     },\r
31847 \r
31848     // private\r
31849     onClick : function(e){\r
31850         this.processEvent("click", e);\r
31851     },\r
31852 \r
31853     // private\r
31854     onMouseDown : function(e){\r
31855         this.processEvent("mousedown", e);\r
31856     },\r
31857 \r
31858     // private\r
31859     onContextMenu : function(e, t){\r
31860         this.processEvent("contextmenu", e);\r
31861     },\r
31862 \r
31863     // private\r
31864     onDblClick : function(e){\r
31865         this.processEvent("dblclick", e);\r
31866     },\r
31867 \r
31868     // private\r
31869     walkCells : function(row, col, step, fn, scope){\r
31870         var cm = this.colModel, clen = cm.getColumnCount();\r
31871         var ds = this.store, rlen = ds.getCount(), first = true;\r
31872         if(step < 0){\r
31873             if(col < 0){\r
31874                 row--;\r
31875                 first = false;\r
31876             }\r
31877             while(row >= 0){\r
31878                 if(!first){\r
31879                     col = clen-1;\r
31880                 }\r
31881                 first = false;\r
31882                 while(col >= 0){\r
31883                     if(fn.call(scope || this, row, col, cm) === true){\r
31884                         return [row, col];\r
31885                     }\r
31886                     col--;\r
31887                 }\r
31888                 row--;\r
31889             }\r
31890         } else {\r
31891             if(col >= clen){\r
31892                 row++;\r
31893                 first = false;\r
31894             }\r
31895             while(row < rlen){\r
31896                 if(!first){\r
31897                     col = 0;\r
31898                 }\r
31899                 first = false;\r
31900                 while(col < clen){\r
31901                     if(fn.call(scope || this, row, col, cm) === true){\r
31902                         return [row, col];\r
31903                     }\r
31904                     col++;\r
31905                 }\r
31906                 row++;\r
31907             }\r
31908         }\r
31909         return null;\r
31910     },\r
31911 \r
31912     // private\r
31913     getSelections : function(){\r
31914         return this.selModel.getSelections();\r
31915     },\r
31916 \r
31917     // private\r
31918     onResize : function(){\r
31919         Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);\r
31920         if(this.viewReady){\r
31921             this.view.layout();\r
31922         }\r
31923     },\r
31924 \r
31925     \r
31926     getGridEl : function(){\r
31927         return this.body;\r
31928     },\r
31929 \r
31930     // private for compatibility, overridden by editor grid\r
31931     stopEditing : Ext.emptyFn,\r
31932 \r
31933     \r
31934     getSelectionModel : function(){\r
31935         if(!this.selModel){\r
31936             this.selModel = new Ext.grid.RowSelectionModel(\r
31937                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);\r
31938         }\r
31939         return this.selModel;\r
31940     },\r
31941 \r
31942     \r
31943     getStore : function(){\r
31944         return this.store;\r
31945     },\r
31946 \r
31947     \r
31948     getColumnModel : function(){\r
31949         return this.colModel;\r
31950     },\r
31951 \r
31952     \r
31953     getView : function(){\r
31954         if(!this.view){\r
31955             this.view = new Ext.grid.GridView(this.viewConfig);\r
31956         }\r
31957         return this.view;\r
31958     },\r
31959     \r
31960     getDragDropText : function(){\r
31961         var count = this.selModel.getCount();\r
31962         return String.format(this.ddText, count, count == 1 ? '' : 's');\r
31963     }\r
31964 \r
31965     \r
31966     \r
31967     \r
31968     \r
31969     \r
31970     \r
31971     \r
31972     \r
31973     \r
31974     \r
31975     \r
31976     \r
31977     \r
31978     \r
31979     \r
31980     \r
31981     \r
31982     \r
31983     \r
31984     \r
31985     \r
31986     \r
31987     \r
31988     \r
31989     \r
31990     \r
31991     \r
31992     \r
31993     \r
31994     \r
31995     \r
31996 \r
31997 \r
31998 \r
31999     \r
32000     \r
32001     \r
32002     \r
32003     \r
32004     \r
32005     \r
32006     \r
32007     \r
32008     \r
32009     \r
32010     \r
32011     \r
32012     \r
32013     \r
32014 });\r
32015 Ext.reg('grid', Ext.grid.GridPanel);\r
32016 \r
32017 Ext.grid.GridView = function(config){\r
32018     Ext.apply(this, config);\r
32019     // These events are only used internally by the grid components\r
32020     this.addEvents(\r
32021       \r
32022       "beforerowremoved",\r
32023       \r
32024       "beforerowsinserted",\r
32025       \r
32026       "beforerefresh",\r
32027       \r
32028       "rowremoved",\r
32029       \r
32030       "rowsinserted",\r
32031       \r
32032       "rowupdated",\r
32033       \r
32034       "refresh"\r
32035   );\r
32036     Ext.grid.GridView.superclass.constructor.call(this);\r
32037 };\r
32038 \r
32039 Ext.extend(Ext.grid.GridView, Ext.util.Observable, {\r
32040     \r
32041     \r
32042     \r
32043     \r
32044     \r
32045     deferEmptyText: true,\r
32046     \r
32047     scrollOffset: 19,\r
32048     \r
32049     autoFill: false,\r
32050     \r
32051     forceFit: false,\r
32052     \r
32053     sortClasses : ["sort-asc", "sort-desc"],\r
32054     \r
32055     sortAscText : "Sort Ascending",\r
32056     \r
32057     sortDescText : "Sort Descending",\r
32058     \r
32059     columnsText : "Columns",\r
32060 \r
32061     // private\r
32062     borderWidth: 2,\r
32063     tdClass: 'x-grid3-cell',\r
32064     hdCls: 'x-grid3-hd',\r
32065 \r
32066     \r
32067     cellSelectorDepth: 4,\r
32068     \r
32069     rowSelectorDepth: 10,\r
32070 \r
32071     \r
32072     cellSelector: 'td.x-grid3-cell',\r
32073     \r
32074     rowSelector: 'div.x-grid3-row',\r
32075 \r
32076     \r
32077 \r
32078     // private\r
32079     initTemplates : function(){\r
32080         var ts = this.templates || {};\r
32081         if(!ts.master){\r
32082             ts.master = new Ext.Template(\r
32083                     '<div class="x-grid3" hidefocus="true">',\r
32084                         '<div class="x-grid3-viewport">',\r
32085                             '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}</div></div><div class="x-clear"></div></div>',\r
32086                             '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',\r
32087                         "</div>",\r
32088                         '<div class="x-grid3-resize-marker">&#160;</div>',\r
32089                         '<div class="x-grid3-resize-proxy">&#160;</div>',\r
32090                     "</div>"\r
32091                     );\r
32092         }\r
32093 \r
32094         if(!ts.header){\r
32095             ts.header = new Ext.Template(\r
32096                     '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
32097                     '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',\r
32098                     "</table>"\r
32099                     );\r
32100         }\r
32101 \r
32102         if(!ts.hcell){\r
32103             ts.hcell = new Ext.Template(\r
32104                     '<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>' : '',\r
32105                     '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',\r
32106                     "</div></td>"\r
32107                     );\r
32108         }\r
32109 \r
32110         if(!ts.body){\r
32111             ts.body = new Ext.Template('{rows}');\r
32112         }\r
32113 \r
32114         if(!ts.row){\r
32115             ts.row = new Ext.Template(\r
32116                     '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
32117                     '<tbody><tr>{cells}</tr>',\r
32118                     (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>' : ''),\r
32119                     '</tbody></table></div>'\r
32120                     );\r
32121         }\r
32122 \r
32123         if(!ts.cell){\r
32124             ts.cell = new Ext.Template(\r
32125                     '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',\r
32126                     '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',\r
32127                     "</td>"\r
32128                     );\r
32129         }\r
32130 \r
32131         for(var k in ts){\r
32132             var t = ts[k];\r
32133             if(t && typeof t.compile == 'function' && !t.compiled){\r
32134                 t.disableFormats = true;\r
32135                 t.compile();\r
32136             }\r
32137         }\r
32138 \r
32139         this.templates = ts;\r
32140         this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");\r
32141     },\r
32142 \r
32143     // private\r
32144     fly : function(el){\r
32145         if(!this._flyweight){\r
32146             this._flyweight = new Ext.Element.Flyweight(document.body);\r
32147         }\r
32148         this._flyweight.dom = el;\r
32149         return this._flyweight;\r
32150     },\r
32151 \r
32152     // private\r
32153     getEditorParent : function(){\r
32154         return this.scroller.dom;\r
32155     },\r
32156 \r
32157     // private\r
32158     initElements : function(){\r
32159         var E = Ext.Element;\r
32160 \r
32161         var el = this.grid.getGridEl().dom.firstChild;\r
32162         var cs = el.childNodes;\r
32163 \r
32164         this.el = new E(el);\r
32165 \r
32166         this.mainWrap = new E(cs[0]);\r
32167         this.mainHd = new E(this.mainWrap.dom.firstChild);\r
32168 \r
32169         if(this.grid.hideHeaders){\r
32170             this.mainHd.setDisplayed(false);\r
32171         }\r
32172 \r
32173         this.innerHd = this.mainHd.dom.firstChild;\r
32174         this.scroller = new E(this.mainWrap.dom.childNodes[1]);\r
32175         if(this.forceFit){\r
32176             this.scroller.setStyle('overflow-x', 'hidden');\r
32177         }\r
32178         \r
32179         this.mainBody = new E(this.scroller.dom.firstChild);\r
32180 \r
32181         this.focusEl = new E(this.scroller.dom.childNodes[1]);\r
32182         this.focusEl.swallowEvent("click", true);\r
32183 \r
32184         this.resizeMarker = new E(cs[1]);\r
32185         this.resizeProxy = new E(cs[2]);\r
32186     },\r
32187 \r
32188     // private\r
32189     getRows : function(){\r
32190         return this.hasRows() ? this.mainBody.dom.childNodes : [];\r
32191     },\r
32192 \r
32193     // finder methods, used with delegation\r
32194 \r
32195     // private\r
32196     findCell : function(el){\r
32197         if(!el){\r
32198             return false;\r
32199         }\r
32200         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);\r
32201     },\r
32202 \r
32203     // private\r
32204     findCellIndex : function(el, requiredCls){\r
32205         var cell = this.findCell(el);\r
32206         if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){\r
32207             return this.getCellIndex(cell);\r
32208         }\r
32209         return false;\r
32210     },\r
32211 \r
32212     // private\r
32213     getCellIndex : function(el){\r
32214         if(el){\r
32215             var m = el.className.match(this.colRe);\r
32216             if(m && m[1]){\r
32217                 return this.cm.getIndexById(m[1]);\r
32218             }\r
32219         }\r
32220         return false;\r
32221     },\r
32222 \r
32223     // private\r
32224     findHeaderCell : function(el){\r
32225         var cell = this.findCell(el);\r
32226         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;\r
32227     },\r
32228 \r
32229     // private\r
32230     findHeaderIndex : function(el){\r
32231         return this.findCellIndex(el, this.hdCls);\r
32232     },\r
32233 \r
32234 \r
32235     findRow : function(el){\r
32236         if(!el){\r
32237             return false;\r
32238         }\r
32239         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);\r
32240     },\r
32241 \r
32242 \r
32243     findRowIndex : function(el){\r
32244         var r = this.findRow(el);\r
32245         return r ? r.rowIndex : false;\r
32246     },\r
32247 \r
32248     // getter methods for fetching elements dynamically in the grid\r
32249 \r
32250 \r
32251     getRow : function(row){\r
32252         return this.getRows()[row];\r
32253     },\r
32254 \r
32255 \r
32256     getCell : function(row, col){\r
32257         return this.getRow(row).getElementsByTagName('td')[col];\r
32258     },\r
32259 \r
32260 \r
32261     getHeaderCell : function(index){\r
32262       return this.mainHd.dom.getElementsByTagName('td')[index];\r
32263     },\r
32264 \r
32265     // manipulating elements\r
32266 \r
32267     // private - use getRowClass to apply custom row classes\r
32268     addRowClass : function(row, cls){\r
32269         var r = this.getRow(row);\r
32270         if(r){\r
32271             this.fly(r).addClass(cls);\r
32272         }\r
32273     },\r
32274 \r
32275     // private\r
32276     removeRowClass : function(row, cls){\r
32277         var r = this.getRow(row);\r
32278         if(r){\r
32279             this.fly(r).removeClass(cls);\r
32280         }\r
32281     },\r
32282 \r
32283     // private\r
32284     removeRow : function(row){\r
32285         Ext.removeNode(this.getRow(row));\r
32286         this.syncFocusEl(row);\r
32287     },\r
32288     \r
32289     // private\r
32290     removeRows : function(firstRow, lastRow){\r
32291         var bd = this.mainBody.dom;\r
32292         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){\r
32293             Ext.removeNode(bd.childNodes[firstRow]);\r
32294         }\r
32295         this.syncFocusEl(firstRow);\r
32296     },\r
32297 \r
32298     // scrolling stuff\r
32299 \r
32300     // private\r
32301     getScrollState : function(){\r
32302         var sb = this.scroller.dom;\r
32303         return {left: sb.scrollLeft, top: sb.scrollTop};\r
32304     },\r
32305 \r
32306     // private\r
32307     restoreScroll : function(state){\r
32308         var sb = this.scroller.dom;\r
32309         sb.scrollLeft = state.left;\r
32310         sb.scrollTop = state.top;\r
32311     },\r
32312 \r
32313     \r
32314     scrollToTop : function(){\r
32315         this.scroller.dom.scrollTop = 0;\r
32316         this.scroller.dom.scrollLeft = 0;\r
32317     },\r
32318 \r
32319     // private\r
32320     syncScroll : function(){\r
32321       this.syncHeaderScroll();\r
32322       var mb = this.scroller.dom;\r
32323         this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);\r
32324     },\r
32325 \r
32326     // private\r
32327     syncHeaderScroll : function(){\r
32328         var mb = this.scroller.dom;\r
32329         this.innerHd.scrollLeft = mb.scrollLeft;\r
32330         this.innerHd.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)\r
32331     },\r
32332 \r
32333     // private\r
32334     updateSortIcon : function(col, dir){\r
32335         var sc = this.sortClasses;\r
32336         var hds = this.mainHd.select('td').removeClass(sc);\r
32337         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);\r
32338     },\r
32339 \r
32340     // private\r
32341     updateAllColumnWidths : function(){\r
32342         var tw = this.getTotalWidth();\r
32343         var clen = this.cm.getColumnCount();\r
32344         var ws = [];\r
32345         for(var i = 0; i < clen; i++){\r
32346             ws[i] = this.getColumnWidth(i);\r
32347         }\r
32348 \r
32349         this.innerHd.firstChild.firstChild.style.width = tw;\r
32350 \r
32351         for(var i = 0; i < clen; i++){\r
32352             var hd = this.getHeaderCell(i);\r
32353             hd.style.width = ws[i];\r
32354         }\r
32355 \r
32356         var ns = this.getRows(), row, trow;\r
32357         for(var i = 0, len = ns.length; i < len; i++){\r
32358             row = ns[i];\r
32359             row.style.width = tw;\r
32360             if(row.firstChild){\r
32361                 row.firstChild.style.width = tw;\r
32362                 trow = row.firstChild.rows[0];\r
32363                 for (var j = 0; j < clen; j++) {\r
32364                    trow.childNodes[j].style.width = ws[j];\r
32365                 }\r
32366             }\r
32367         }\r
32368 \r
32369         this.onAllColumnWidthsUpdated(ws, tw);\r
32370     },\r
32371 \r
32372     // private\r
32373     updateColumnWidth : function(col, width){\r
32374         var w = this.getColumnWidth(col);\r
32375         var tw = this.getTotalWidth();\r
32376 \r
32377         this.innerHd.firstChild.firstChild.style.width = tw;\r
32378         var hd = this.getHeaderCell(col);\r
32379         hd.style.width = w;\r
32380 \r
32381         var ns = this.getRows(), row;\r
32382         for(var i = 0, len = ns.length; i < len; i++){\r
32383             row = ns[i];\r
32384             row.style.width = tw;\r
32385             if(row.firstChild){\r
32386                 row.firstChild.style.width = tw;\r
32387                 row.firstChild.rows[0].childNodes[col].style.width = w;\r
32388             }\r
32389         }\r
32390 \r
32391         this.onColumnWidthUpdated(col, w, tw);\r
32392     },\r
32393 \r
32394     // private\r
32395     updateColumnHidden : function(col, hidden){\r
32396         var tw = this.getTotalWidth();\r
32397 \r
32398         this.innerHd.firstChild.firstChild.style.width = tw;\r
32399 \r
32400         var display = hidden ? 'none' : '';\r
32401 \r
32402         var hd = this.getHeaderCell(col);\r
32403         hd.style.display = display;\r
32404 \r
32405         var ns = this.getRows(), row;\r
32406         for(var i = 0, len = ns.length; i < len; i++){\r
32407             row = ns[i];\r
32408             row.style.width = tw;\r
32409             if(row.firstChild){\r
32410                 row.firstChild.style.width = tw;\r
32411                 row.firstChild.rows[0].childNodes[col].style.display = display;\r
32412             }\r
32413         }\r
32414 \r
32415         this.onColumnHiddenUpdated(col, hidden, tw);\r
32416 \r
32417         delete this.lastViewWidth; // force recalc\r
32418         this.layout();\r
32419     },\r
32420 \r
32421     // private\r
32422     doRender : function(cs, rs, ds, startRow, colCount, stripe){\r
32423         var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;\r
32424         var tstyle = 'width:'+this.getTotalWidth()+';';\r
32425         // buffers\r
32426         var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;\r
32427         for(var j = 0, len = rs.length; j < len; j++){\r
32428             r = rs[j]; cb = [];\r
32429             var rowIndex = (j+startRow);\r
32430             for(var i = 0; i < colCount; i++){\r
32431                 c = cs[i];\r
32432                 p.id = c.id;\r
32433                 p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
32434                 p.attr = p.cellAttr = "";\r
32435                 p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);\r
32436                 p.style = c.style;\r
32437                 if(p.value == undefined || p.value === "") p.value = "&#160;";\r
32438                 if(r.dirty && typeof r.modified[c.name] !== 'undefined'){\r
32439                     p.css += ' x-grid3-dirty-cell';\r
32440                 }\r
32441                 cb[cb.length] = ct.apply(p);\r
32442             }\r
32443             var alt = [];\r
32444             if(stripe && ((rowIndex+1) % 2 == 0)){\r
32445                 alt[0] = "x-grid3-row-alt";\r
32446             }\r
32447             if(r.dirty){\r
32448                 alt[1] = " x-grid3-dirty-row";\r
32449             }\r
32450             rp.cols = colCount;\r
32451             if(this.getRowClass){\r
32452                 alt[2] = this.getRowClass(r, rowIndex, rp, ds);\r
32453             }\r
32454             rp.alt = alt.join(" ");\r
32455             rp.cells = cb.join("");\r
32456             buf[buf.length] =  rt.apply(rp);\r
32457         }\r
32458         return buf.join("");\r
32459     },\r
32460 \r
32461     // private\r
32462     processRows : function(startRow, skipStripe){\r
32463         if(this.ds.getCount() < 1){\r
32464             return;\r
32465         }\r
32466         skipStripe = skipStripe || !this.grid.stripeRows;\r
32467         startRow = startRow || 0;\r
32468         var rows = this.getRows();\r
32469         var cls = ' x-grid3-row-alt ';\r
32470         rows[0].className += ' x-grid3-row-first';\r
32471         rows[rows.length - 1].className += ' x-grid3-row-last';\r
32472         for(var i = startRow, len = rows.length; i < len; i++){\r
32473             var row = rows[i];\r
32474             row.rowIndex = i;\r
32475             if(!skipStripe){\r
32476                 var isAlt = ((i+1) % 2 == 0);\r
32477                 var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;\r
32478                 if(isAlt == hasAlt){\r
32479                     continue;\r
32480                 }\r
32481                 if(isAlt){\r
32482                     row.className += " x-grid3-row-alt";\r
32483                 }else{\r
32484                     row.className = row.className.replace("x-grid3-row-alt", "");\r
32485                 }\r
32486             }\r
32487         }\r
32488     },\r
32489 \r
32490     afterRender: function(){\r
32491         this.mainBody.dom.innerHTML = this.renderRows();\r
32492         this.processRows(0, true);\r
32493 \r
32494         if(this.deferEmptyText !== true){\r
32495             this.applyEmptyText();\r
32496         }\r
32497     },\r
32498 \r
32499     // private\r
32500     renderUI : function(){\r
32501 \r
32502         var header = this.renderHeaders();\r
32503         var body = this.templates.body.apply({rows:''});\r
32504 \r
32505 \r
32506         var html = this.templates.master.apply({\r
32507             body: body,\r
32508             header: header\r
32509         });\r
32510 \r
32511         var g = this.grid;\r
32512 \r
32513         g.getGridEl().dom.innerHTML = html;\r
32514 \r
32515         this.initElements();\r
32516 \r
32517         // get mousedowns early\r
32518         Ext.fly(this.innerHd).on("click", this.handleHdDown, this);\r
32519         this.mainHd.on("mouseover", this.handleHdOver, this);\r
32520         this.mainHd.on("mouseout", this.handleHdOut, this);\r
32521         this.mainHd.on("mousemove", this.handleHdMove, this);\r
32522 \r
32523         this.scroller.on('scroll', this.syncScroll,  this);\r
32524         if(g.enableColumnResize !== false){\r
32525             this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);\r
32526         }\r
32527 \r
32528         if(g.enableColumnMove){\r
32529             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);\r
32530             this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);\r
32531         }\r
32532 \r
32533         if(g.enableHdMenu !== false){\r
32534             if(g.enableColumnHide !== false){\r
32535                 this.colMenu = new Ext.menu.Menu({id:g.id + "-hcols-menu"});\r
32536                 this.colMenu.on("beforeshow", this.beforeColMenuShow, this);\r
32537                 this.colMenu.on("itemclick", this.handleHdMenuClick, this);\r
32538             }\r
32539             this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});\r
32540             this.hmenu.add(\r
32541                 {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},\r
32542                 {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}\r
32543             );\r
32544             if(g.enableColumnHide !== false){\r
32545                 this.hmenu.add('-',\r
32546                     {id:"columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon'}\r
32547                 );\r
32548             }\r
32549             this.hmenu.on("itemclick", this.handleHdMenuClick, this);\r
32550 \r
32551             //g.on("headercontextmenu", this.handleHdCtx, this);\r
32552         }\r
32553 \r
32554         if(g.trackMouseOver){\r
32555             this.mainBody.on("mouseover", this.onRowOver, this);\r
32556             this.mainBody.on("mouseout", this.onRowOut, this);\r
32557         }\r
32558         if(g.enableDragDrop || g.enableDrag){\r
32559             this.dragZone = new Ext.grid.GridDragZone(g, {\r
32560                 ddGroup : g.ddGroup || 'GridDD'\r
32561             });\r
32562         }\r
32563 \r
32564         this.updateHeaderSortState();\r
32565 \r
32566     },\r
32567 \r
32568     // private\r
32569     layout : function(){\r
32570         if(!this.mainBody){\r
32571             return; // not rendered\r
32572         }\r
32573         var g = this.grid;\r
32574         var c = g.getGridEl();\r
32575         var csize = c.getSize(true);\r
32576         var vw = csize.width;\r
32577 \r
32578         if(vw < 20 || csize.height < 20){ // display: none?\r
32579             return;\r
32580         }\r
32581 \r
32582         if(g.autoHeight){\r
32583             this.scroller.dom.style.overflow = 'visible';\r
32584             if(Ext.isSafari){\r
32585                 this.scroller.dom.style.position = 'static';\r
32586             }\r
32587         }else{\r
32588             this.el.setSize(csize.width, csize.height);\r
32589 \r
32590             var hdHeight = this.mainHd.getHeight();\r
32591             var vh = csize.height - (hdHeight);\r
32592 \r
32593             this.scroller.setSize(vw, vh);\r
32594             if(this.innerHd){\r
32595                 this.innerHd.style.width = (vw)+'px';\r
32596             }\r
32597         }\r
32598         if(this.forceFit){\r
32599             if(this.lastViewWidth != vw){\r
32600                 this.fitColumns(false, false);\r
32601                 this.lastViewWidth = vw;\r
32602             }\r
32603         }else {\r
32604             this.autoExpand();\r
32605             this.syncHeaderScroll();\r
32606         }\r
32607         this.onLayout(vw, vh);\r
32608     },\r
32609 \r
32610     // template functions for subclasses and plugins\r
32611     // these functions include precalculated values\r
32612     onLayout : function(vw, vh){\r
32613         // do nothing\r
32614     },\r
32615 \r
32616     onColumnWidthUpdated : function(col, w, tw){\r
32617         //template method\r
32618         this.focusEl.setWidth(tw);\r
32619     },\r
32620 \r
32621     onAllColumnWidthsUpdated : function(ws, tw){\r
32622         //template method\r
32623         this.focusEl.setWidth(tw);\r
32624     },\r
32625 \r
32626     onColumnHiddenUpdated : function(col, hidden, tw){\r
32627         // template method\r
32628         this.focusEl.setWidth(tw);\r
32629     },\r
32630 \r
32631     updateColumnText : function(col, text){\r
32632         // template method\r
32633     },\r
32634 \r
32635     afterMove : function(colIndex){\r
32636         // template method\r
32637     },\r
32638 \r
32639     \r
32640     // private\r
32641     init: function(grid){\r
32642         this.grid = grid;\r
32643 \r
32644         this.initTemplates();\r
32645         this.initData(grid.store, grid.colModel);\r
32646         this.initUI(grid);\r
32647     },\r
32648 \r
32649     // private\r
32650     getColumnId : function(index){\r
32651       return this.cm.getColumnId(index);\r
32652     },\r
32653 \r
32654     // private\r
32655     renderHeaders : function(){\r
32656         var cm = this.cm, ts = this.templates;\r
32657         var ct = ts.hcell;\r
32658 \r
32659         var cb = [], sb = [], p = {};\r
32660         var len = cm.getColumnCount();\r
32661         var last = len - 1;\r
32662         for(var i = 0; i < len; i++){\r
32663             p.id = cm.getColumnId(i);\r
32664             p.value = cm.getColumnHeader(i) || "";\r
32665             p.style = this.getColumnStyle(i, true);\r
32666             p.tooltip = this.getColumnTooltip(i);\r
32667             p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');\r
32668             if(cm.config[i].align == 'right'){\r
32669                 p.istyle = 'padding-right:16px';\r
32670             } else {\r
32671                 delete p.istyle;\r
32672             }\r
32673             cb[cb.length] = ct.apply(p);\r
32674         }\r
32675         return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});\r
32676     },\r
32677 \r
32678     // private\r
32679     getColumnTooltip : function(i){\r
32680         var tt = this.cm.getColumnTooltip(i);\r
32681         if(tt){\r
32682             if(Ext.QuickTips.isEnabled()){\r
32683                 return 'ext:qtip="'+tt+'"';\r
32684             }else{\r
32685                 return 'title="'+tt+'"';\r
32686             }\r
32687         }\r
32688         return "";\r
32689     },\r
32690 \r
32691     // private\r
32692     beforeUpdate : function(){\r
32693         this.grid.stopEditing(true);\r
32694     },\r
32695 \r
32696     // private\r
32697     updateHeaders : function(){\r
32698         this.innerHd.firstChild.innerHTML = this.renderHeaders();\r
32699     },\r
32700 \r
32701     \r
32702     focusRow : function(row){\r
32703         this.focusCell(row, 0, false);\r
32704     },\r
32705 \r
32706     \r
32707     focusCell : function(row, col, hscroll){\r
32708                 this.syncFocusEl(this.ensureVisible(row, col, hscroll));\r
32709         if(Ext.isGecko){\r
32710             this.focusEl.focus();\r
32711         }else{\r
32712             this.focusEl.focus.defer(1, this.focusEl);\r
32713         }\r
32714     },\r
32715 \r
32716         resolveCell : function(row, col, hscroll){\r
32717                 if(typeof row != "number"){\r
32718             row = row.rowIndex;\r
32719         }\r
32720         if(!this.ds){\r
32721             return null;\r
32722         }\r
32723         if(row < 0 || row >= this.ds.getCount()){\r
32724             return null;\r
32725         }\r
32726         col = (col !== undefined ? col : 0);\r
32727 \r
32728         var rowEl = this.getRow(row), cellEl;\r
32729         if(!(hscroll === false && col === 0)){\r
32730             while(this.cm.isHidden(col)){\r
32731                 col++;\r
32732             }\r
32733             cellEl = this.getCell(row, col);\r
32734         }\r
32735 \r
32736                 return {row: rowEl, cell: cellEl};\r
32737         },\r
32738 \r
32739         getResolvedXY : function(resolved){\r
32740                 if(!resolved){\r
32741                         return null;\r
32742                 }\r
32743                 var s = this.scroller.dom, c = resolved.cell, r = resolved.row;\r
32744                 return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];\r
32745         },\r
32746 \r
32747         syncFocusEl : function(row, col, hscroll){\r
32748                 var xy = row;\r
32749                 if(!Ext.isArray(xy)){\r
32750                         row = Math.min(row, Math.max(0, this.getRows().length-1));\r
32751                 xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));\r
32752                 }\r
32753         this.focusEl.setXY(xy||this.scroller.getXY());\r
32754     },\r
32755 \r
32756         ensureVisible : function(row, col, hscroll){\r
32757         var resolved = this.resolveCell(row, col, hscroll);\r
32758                 if(!resolved || !resolved.row){\r
32759                         return;\r
32760                 }\r
32761 \r
32762                 var rowEl = resolved.row, cellEl = resolved.cell;\r
32763 \r
32764                 var c = this.scroller.dom;\r
32765 \r
32766         var ctop = 0;\r
32767         var p = rowEl, stop = this.el.dom;\r
32768         while(p && p != stop){\r
32769             ctop += p.offsetTop;\r
32770             p = p.offsetParent;\r
32771         }\r
32772         ctop -= this.mainHd.dom.offsetHeight;\r
32773 \r
32774         var cbot = ctop + rowEl.offsetHeight;\r
32775 \r
32776         var ch = c.clientHeight;\r
32777         var stop = parseInt(c.scrollTop, 10);\r
32778         var sbot = stop + ch;\r
32779 \r
32780                 if(ctop < stop){\r
32781           c.scrollTop = ctop;\r
32782         }else if(cbot > sbot){\r
32783             c.scrollTop = cbot-ch;\r
32784         }\r
32785 \r
32786         if(hscroll !== false){\r
32787             var cleft = parseInt(cellEl.offsetLeft, 10);\r
32788             var cright = cleft + cellEl.offsetWidth;\r
32789 \r
32790             var sleft = parseInt(c.scrollLeft, 10);\r
32791             var sright = sleft + c.clientWidth;\r
32792             if(cleft < sleft){\r
32793                 c.scrollLeft = cleft;\r
32794             }else if(cright > sright){\r
32795                 c.scrollLeft = cright-c.clientWidth;\r
32796             }\r
32797         }\r
32798         return this.getResolvedXY(resolved);\r
32799     },\r
32800 \r
32801     // private\r
32802     insertRows : function(dm, firstRow, lastRow, isUpdate){\r
32803         if(!isUpdate && firstRow === 0 && lastRow >= dm.getCount()-1){\r
32804             this.refresh();\r
32805         }else{\r
32806             if(!isUpdate){\r
32807                 this.fireEvent("beforerowsinserted", this, firstRow, lastRow);\r
32808             }\r
32809             var html = this.renderRows(firstRow, lastRow);\r
32810             var before = this.getRow(firstRow);\r
32811             if(before){\r
32812                 Ext.DomHelper.insertHtml('beforeBegin', before, html);\r
32813             }else{\r
32814                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);\r
32815             }\r
32816             if(!isUpdate){\r
32817                 this.fireEvent("rowsinserted", this, firstRow, lastRow);\r
32818                 this.processRows(firstRow);\r
32819             }\r
32820         }\r
32821         this.syncFocusEl(firstRow);\r
32822     },\r
32823 \r
32824     // private\r
32825     deleteRows : function(dm, firstRow, lastRow){\r
32826         if(dm.getRowCount()<1){\r
32827             this.refresh();\r
32828         }else{\r
32829             this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);\r
32830 \r
32831             this.removeRows(firstRow, lastRow);\r
32832 \r
32833             this.processRows(firstRow);\r
32834             this.fireEvent("rowsdeleted", this, firstRow, lastRow);\r
32835         }\r
32836     },\r
32837 \r
32838     // private\r
32839     getColumnStyle : function(col, isHeader){\r
32840         var style = !isHeader ? (this.cm.config[col].css || '') : '';\r
32841         style += 'width:'+this.getColumnWidth(col)+';';\r
32842         if(this.cm.isHidden(col)){\r
32843             style += 'display:none;';\r
32844         }\r
32845         var align = this.cm.config[col].align;\r
32846         if(align){\r
32847             style += 'text-align:'+align+';';\r
32848         }\r
32849         return style;\r
32850     },\r
32851 \r
32852     // private\r
32853     getColumnWidth : function(col){\r
32854         var w = this.cm.getColumnWidth(col);\r
32855         if(typeof w == 'number'){\r
32856             return (Ext.isBorderBox ? w : (w-this.borderWidth > 0 ? w-this.borderWidth:0)) + 'px';\r
32857         }\r
32858         return w;\r
32859     },\r
32860 \r
32861     // private\r
32862     getTotalWidth : function(){\r
32863         return this.cm.getTotalWidth()+'px';\r
32864     },\r
32865 \r
32866     // private\r
32867     fitColumns : function(preventRefresh, onlyExpand, omitColumn){\r
32868         var cm = this.cm, leftOver, dist, i;\r
32869         var tw = cm.getTotalWidth(false);\r
32870         var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;\r
32871 \r
32872         if(aw < 20){ // not initialized, so don't screw up the default widths\r
32873             return;\r
32874         }\r
32875         var extra = aw - tw;\r
32876 \r
32877         if(extra === 0){\r
32878             return false;\r
32879         }\r
32880 \r
32881         var vc = cm.getColumnCount(true);\r
32882         var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);\r
32883         if(ac === 0){\r
32884             ac = 1;\r
32885             omitColumn = undefined;\r
32886         }\r
32887         var colCount = cm.getColumnCount();\r
32888         var cols = [];\r
32889         var extraCol = 0;\r
32890         var width = 0;\r
32891         var w;\r
32892         for (i = 0; i < colCount; i++){\r
32893             if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){\r
32894                 w = cm.getColumnWidth(i);\r
32895                 cols.push(i);\r
32896                 extraCol = i;\r
32897                 cols.push(w);\r
32898                 width += w;\r
32899             }\r
32900         }\r
32901         var frac = (aw - cm.getTotalWidth())/width;\r
32902         while (cols.length){\r
32903             w = cols.pop();\r
32904             i = cols.pop();\r
32905             cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);\r
32906         }\r
32907 \r
32908         if((tw = cm.getTotalWidth(false)) > aw){\r
32909             var adjustCol = ac != vc ? omitColumn : extraCol;\r
32910              cm.setColumnWidth(adjustCol, Math.max(1,\r
32911                      cm.getColumnWidth(adjustCol)- (tw-aw)), true);\r
32912         }\r
32913 \r
32914         if(preventRefresh !== true){\r
32915             this.updateAllColumnWidths();\r
32916         }\r
32917 \r
32918 \r
32919         return true;\r
32920     },\r
32921 \r
32922     // private\r
32923     autoExpand : function(preventUpdate){\r
32924         var g = this.grid, cm = this.cm;\r
32925         if(!this.userResized && g.autoExpandColumn){\r
32926             var tw = cm.getTotalWidth(false);\r
32927             var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;\r
32928             if(tw != aw){\r
32929                 var ci = cm.getIndexById(g.autoExpandColumn);\r
32930                 var currentWidth = cm.getColumnWidth(ci);\r
32931                 var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);\r
32932                 if(cw != currentWidth){\r
32933                     cm.setColumnWidth(ci, cw, true);\r
32934                     if(preventUpdate !== true){\r
32935                         this.updateColumnWidth(ci, cw);\r
32936                     }\r
32937                 }\r
32938             }\r
32939         }\r
32940     },\r
32941 \r
32942     // private\r
32943     getColumnData : function(){\r
32944         // build a map for all the columns\r
32945         var cs = [], cm = this.cm, colCount = cm.getColumnCount();\r
32946         for(var i = 0; i < colCount; i++){\r
32947             var name = cm.getDataIndex(i);\r
32948             cs[i] = {\r
32949                 name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),\r
32950                 renderer : cm.getRenderer(i),\r
32951                 id : cm.getColumnId(i),\r
32952                 style : this.getColumnStyle(i)\r
32953             };\r
32954         }\r
32955         return cs;\r
32956     },\r
32957 \r
32958     // private\r
32959     renderRows : function(startRow, endRow){\r
32960         // pull in all the crap needed to render rows\r
32961         var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;\r
32962         var colCount = cm.getColumnCount();\r
32963 \r
32964         if(ds.getCount() < 1){\r
32965             return "";\r
32966         }\r
32967 \r
32968         var cs = this.getColumnData();\r
32969 \r
32970         startRow = startRow || 0;\r
32971         endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;\r
32972 \r
32973         // records to render\r
32974         var rs = ds.getRange(startRow, endRow);\r
32975 \r
32976         return this.doRender(cs, rs, ds, startRow, colCount, stripe);\r
32977     },\r
32978 \r
32979     // private\r
32980     renderBody : function(){\r
32981         var markup = this.renderRows();\r
32982         return this.templates.body.apply({rows: markup});\r
32983     },\r
32984 \r
32985     // private\r
32986     refreshRow : function(record){\r
32987         var ds = this.ds, index;\r
32988         if(typeof record == 'number'){\r
32989             index = record;\r
32990             record = ds.getAt(index);\r
32991         }else{\r
32992             index = ds.indexOf(record);\r
32993         }\r
32994         var cls = [];\r
32995         this.insertRows(ds, index, index, true);\r
32996         this.getRow(index).rowIndex = index;\r
32997         this.onRemove(ds, record, index+1, true);\r
32998         this.fireEvent("rowupdated", this, index, record);\r
32999     },\r
33000 \r
33001     \r
33002     refresh : function(headersToo){\r
33003         this.fireEvent("beforerefresh", this);\r
33004         this.grid.stopEditing(true);\r
33005 \r
33006         var result = this.renderBody();\r
33007         this.mainBody.update(result);\r
33008 \r
33009         if(headersToo === true){\r
33010             this.updateHeaders();\r
33011             this.updateHeaderSortState();\r
33012         }\r
33013         this.processRows(0, true);\r
33014         this.layout();\r
33015         this.applyEmptyText();\r
33016         this.fireEvent("refresh", this);\r
33017     },\r
33018 \r
33019     // private\r
33020     applyEmptyText : function(){\r
33021         if(this.emptyText && !this.hasRows()){\r
33022             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');\r
33023         }\r
33024     },\r
33025 \r
33026     // private\r
33027     updateHeaderSortState : function(){\r
33028         var state = this.ds.getSortState();\r
33029         if(!state){\r
33030             return;\r
33031         }\r
33032         if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){\r
33033             this.grid.fireEvent('sortchange', this.grid, state);\r
33034         }\r
33035         this.sortState = state;\r
33036         var sortColumn = this.cm.findColumnIndex(state.field);\r
33037         if(sortColumn != -1){\r
33038             var sortDir = state.direction;\r
33039             this.updateSortIcon(sortColumn, sortDir);\r
33040         }\r
33041     },\r
33042 \r
33043     // private\r
33044     destroy : function(){\r
33045         if(this.colMenu){\r
33046             Ext.menu.MenuMgr.unregister(this.colMenu);\r
33047             this.colMenu.destroy();\r
33048             delete this.colMenu;\r
33049         }\r
33050         if(this.hmenu){\r
33051             Ext.menu.MenuMgr.unregister(this.hmenu);\r
33052             this.hmenu.destroy();\r
33053             delete this.hmenu;\r
33054         }\r
33055         if(this.grid.enableColumnMove){\r
33056             var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];\r
33057             if(dds){\r
33058                 for(var dd in dds){\r
33059                     if(!dds[dd].config.isTarget && dds[dd].dragElId){\r
33060                         var elid = dds[dd].dragElId;\r
33061                         dds[dd].unreg();\r
33062                         Ext.get(elid).remove();\r
33063                     } else if(dds[dd].config.isTarget){\r
33064                         dds[dd].proxyTop.remove();\r
33065                         dds[dd].proxyBottom.remove();\r
33066                         dds[dd].unreg();\r
33067                     }\r
33068                     if(Ext.dd.DDM.locationCache[dd]){\r
33069                         delete Ext.dd.DDM.locationCache[dd];\r
33070                     }\r
33071                 }\r
33072                 delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];\r
33073             }\r
33074         }\r
33075         \r
33076         if(this.dragZone){\r
33077             this.dragZone.unreg();\r
33078         }\r
33079         \r
33080         Ext.fly(this.innerHd).removeAllListeners();\r
33081         Ext.removeNode(this.innerHd);\r
33082         \r
33083         Ext.destroy(this.resizeMarker, this.resizeProxy, this.focusEl, this.mainBody, \r
33084                     this.scroller, this.mainHd, this.mainWrap, this.dragZone, \r
33085                     this.splitZone, this.columnDrag, this.columnDrop);\r
33086 \r
33087         this.initData(null, null);\r
33088         Ext.EventManager.removeResizeListener(this.onWindowResize, this);\r
33089         this.purgeListeners();\r
33090     },\r
33091 \r
33092     // private\r
33093     onDenyColumnHide : function(){\r
33094 \r
33095     },\r
33096 \r
33097     // private\r
33098     render : function(){\r
33099         if(this.autoFill){\r
33100             var ct = this.grid.ownerCt;\r
33101             if (ct && ct.getLayout()){\r
33102                 ct.on('afterlayout', function(){ \r
33103                     this.fitColumns(true, true);\r
33104                     this.updateHeaders(); \r
33105                 }, this, {single: true}); \r
33106             }else{ \r
33107                 this.fitColumns(true, true); \r
33108             }\r
33109         }else if(this.forceFit){\r
33110             this.fitColumns(true, false);\r
33111         }else if(this.grid.autoExpandColumn){\r
33112             this.autoExpand(true);\r
33113         }\r
33114 \r
33115         this.renderUI();\r
33116     },\r
33117 \r
33118     \r
33119     // private\r
33120     initData : function(ds, cm){\r
33121         if(this.ds){\r
33122             this.ds.un("load", this.onLoad, this);\r
33123             this.ds.un("datachanged", this.onDataChange, this);\r
33124             this.ds.un("add", this.onAdd, this);\r
33125             this.ds.un("remove", this.onRemove, this);\r
33126             this.ds.un("update", this.onUpdate, this);\r
33127             this.ds.un("clear", this.onClear, this);\r
33128         }\r
33129         if(ds){\r
33130             ds.on("load", this.onLoad, this);\r
33131             ds.on("datachanged", this.onDataChange, this);\r
33132             ds.on("add", this.onAdd, this);\r
33133             ds.on("remove", this.onRemove, this);\r
33134             ds.on("update", this.onUpdate, this);\r
33135             ds.on("clear", this.onClear, this);\r
33136         }\r
33137         this.ds = ds;\r
33138 \r
33139         if(this.cm){\r
33140             this.cm.un("configchange", this.onColConfigChange, this);\r
33141             this.cm.un("widthchange", this.onColWidthChange, this);\r
33142             this.cm.un("headerchange", this.onHeaderChange, this);\r
33143             this.cm.un("hiddenchange", this.onHiddenChange, this);\r
33144             this.cm.un("columnmoved", this.onColumnMove, this);\r
33145             this.cm.un("columnlockchange", this.onColumnLock, this);\r
33146         }\r
33147         if(cm){\r
33148             delete this.lastViewWidth;\r
33149             cm.on("configchange", this.onColConfigChange, this);\r
33150             cm.on("widthchange", this.onColWidthChange, this);\r
33151             cm.on("headerchange", this.onHeaderChange, this);\r
33152             cm.on("hiddenchange", this.onHiddenChange, this);\r
33153             cm.on("columnmoved", this.onColumnMove, this);\r
33154             cm.on("columnlockchange", this.onColumnLock, this);\r
33155         }\r
33156         this.cm = cm;\r
33157     },\r
33158 \r
33159     // private\r
33160     onDataChange : function(){\r
33161         this.refresh();\r
33162         this.updateHeaderSortState();\r
33163         this.syncFocusEl(0);\r
33164     },\r
33165 \r
33166     // private\r
33167     onClear : function(){\r
33168         this.refresh();\r
33169         this.syncFocusEl(0);\r
33170     },\r
33171 \r
33172     // private\r
33173     onUpdate : function(ds, record){\r
33174         this.refreshRow(record);\r
33175     },\r
33176 \r
33177     // private\r
33178     onAdd : function(ds, records, index){\r
33179         this.insertRows(ds, index, index + (records.length-1));\r
33180     },\r
33181 \r
33182     // private\r
33183     onRemove : function(ds, record, index, isUpdate){\r
33184         if(isUpdate !== true){\r
33185             this.fireEvent("beforerowremoved", this, index, record);\r
33186         }\r
33187         this.removeRow(index);\r
33188         if(isUpdate !== true){\r
33189             this.processRows(index);\r
33190             this.applyEmptyText();\r
33191             this.fireEvent("rowremoved", this, index, record);\r
33192         }\r
33193     },\r
33194 \r
33195     // private\r
33196     onLoad : function(){\r
33197         this.scrollToTop();\r
33198     },\r
33199 \r
33200     // private\r
33201     onColWidthChange : function(cm, col, width){\r
33202         this.updateColumnWidth(col, width);\r
33203     },\r
33204 \r
33205     // private\r
33206     onHeaderChange : function(cm, col, text){\r
33207         this.updateHeaders();\r
33208     },\r
33209 \r
33210     // private\r
33211     onHiddenChange : function(cm, col, hidden){\r
33212         this.updateColumnHidden(col, hidden);\r
33213     },\r
33214 \r
33215     // private\r
33216     onColumnMove : function(cm, oldIndex, newIndex){\r
33217         this.indexMap = null;\r
33218         var s = this.getScrollState();\r
33219         this.refresh(true);\r
33220         this.restoreScroll(s);\r
33221         this.afterMove(newIndex);\r
33222     },\r
33223 \r
33224     // private\r
33225     onColConfigChange : function(){\r
33226         delete this.lastViewWidth;\r
33227         this.indexMap = null;\r
33228         this.refresh(true);\r
33229     },\r
33230 \r
33231     \r
33232     // private\r
33233     initUI : function(grid){\r
33234         grid.on("headerclick", this.onHeaderClick, this);\r
33235     },\r
33236 \r
33237     // private\r
33238     initEvents : function(){\r
33239 \r
33240     },\r
33241 \r
33242     // private\r
33243     onHeaderClick : function(g, index){\r
33244         if(this.headersDisabled || !this.cm.isSortable(index)){\r
33245             return;\r
33246         }\r
33247         g.stopEditing(true);\r
33248         g.store.sort(this.cm.getDataIndex(index));\r
33249     },\r
33250 \r
33251     // private\r
33252     onRowOver : function(e, t){\r
33253         var row;\r
33254         if((row = this.findRowIndex(t)) !== false){\r
33255             this.addRowClass(row, "x-grid3-row-over");\r
33256         }\r
33257     },\r
33258 \r
33259     // private\r
33260     onRowOut : function(e, t){\r
33261         var row;\r
33262         if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){\r
33263             this.removeRowClass(row, "x-grid3-row-over");\r
33264         }\r
33265     },\r
33266 \r
33267     // private\r
33268     handleWheel : function(e){\r
33269         e.stopPropagation();\r
33270     },\r
33271 \r
33272     // private\r
33273     onRowSelect : function(row){\r
33274         this.addRowClass(row, "x-grid3-row-selected");\r
33275     },\r
33276 \r
33277     // private\r
33278     onRowDeselect : function(row){\r
33279         this.removeRowClass(row, "x-grid3-row-selected");\r
33280     },\r
33281 \r
33282     // private\r
33283     onCellSelect : function(row, col){\r
33284         var cell = this.getCell(row, col);\r
33285         if(cell){\r
33286             this.fly(cell).addClass("x-grid3-cell-selected");\r
33287         }\r
33288     },\r
33289 \r
33290     // private\r
33291     onCellDeselect : function(row, col){\r
33292         var cell = this.getCell(row, col);\r
33293         if(cell){\r
33294             this.fly(cell).removeClass("x-grid3-cell-selected");\r
33295         }\r
33296     },\r
33297 \r
33298     // private\r
33299     onColumnSplitterMoved : function(i, w){\r
33300         this.userResized = true;\r
33301         var cm = this.grid.colModel;\r
33302         cm.setColumnWidth(i, w, true);\r
33303 \r
33304         if(this.forceFit){\r
33305             this.fitColumns(true, false, i);\r
33306             this.updateAllColumnWidths();\r
33307         }else{\r
33308             this.updateColumnWidth(i, w);\r
33309             this.syncHeaderScroll();\r
33310         }\r
33311 \r
33312         this.grid.fireEvent("columnresize", i, w);\r
33313     },\r
33314 \r
33315     // private\r
33316     handleHdMenuClick : function(item){\r
33317         var index = this.hdCtxIndex;\r
33318         var cm = this.cm, ds = this.ds;\r
33319         switch(item.id){\r
33320             case "asc":\r
33321                 ds.sort(cm.getDataIndex(index), "ASC");\r
33322                 break;\r
33323             case "desc":\r
33324                 ds.sort(cm.getDataIndex(index), "DESC");\r
33325                 break;\r
33326             default:\r
33327                 index = cm.getIndexById(item.id.substr(4));\r
33328                 if(index != -1){\r
33329                     if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){\r
33330                         this.onDenyColumnHide();\r
33331                         return false;\r
33332                     }\r
33333                     cm.setHidden(index, item.checked);\r
33334                 }\r
33335         }\r
33336         return true;\r
33337     },\r
33338 \r
33339     // private\r
33340     isHideableColumn : function(c){\r
33341         return !c.hidden && !c.fixed;\r
33342     },\r
33343 \r
33344     // private\r
33345     beforeColMenuShow : function(){\r
33346         var cm = this.cm,  colCount = cm.getColumnCount();\r
33347         this.colMenu.removeAll();\r
33348         for(var i = 0; i < colCount; i++){\r
33349             if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){\r
33350                 this.colMenu.add(new Ext.menu.CheckItem({\r
33351                     id: "col-"+cm.getColumnId(i),\r
33352                     text: cm.getColumnHeader(i),\r
33353                     checked: !cm.isHidden(i),\r
33354                     hideOnClick:false,\r
33355                     disabled: cm.config[i].hideable === false\r
33356                 }));\r
33357             }\r
33358         }\r
33359     },\r
33360 \r
33361     // private\r
33362     handleHdDown : function(e, t){\r
33363         if(Ext.fly(t).hasClass('x-grid3-hd-btn')){\r
33364             e.stopEvent();\r
33365             var hd = this.findHeaderCell(t);\r
33366             Ext.fly(hd).addClass('x-grid3-hd-menu-open');\r
33367             var index = this.getCellIndex(hd);\r
33368             this.hdCtxIndex = index;\r
33369             var ms = this.hmenu.items, cm = this.cm;\r
33370             ms.get("asc").setDisabled(!cm.isSortable(index));\r
33371             ms.get("desc").setDisabled(!cm.isSortable(index));\r
33372             this.hmenu.on("hide", function(){\r
33373                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');\r
33374             }, this, {single:true});\r
33375             this.hmenu.show(t, "tl-bl?");\r
33376         }\r
33377     },\r
33378 \r
33379     // private\r
33380     handleHdOver : function(e, t){\r
33381         var hd = this.findHeaderCell(t);\r
33382         if(hd && !this.headersDisabled){\r
33383             this.activeHd = hd;\r
33384             this.activeHdIndex = this.getCellIndex(hd);\r
33385             var fly = this.fly(hd);\r
33386             this.activeHdRegion = fly.getRegion();\r
33387             if(!this.cm.isMenuDisabled(this.activeHdIndex)){\r
33388                 fly.addClass("x-grid3-hd-over");\r
33389                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');\r
33390                 if(this.activeHdBtn){\r
33391                     this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';\r
33392                 }\r
33393             }\r
33394         }\r
33395     },\r
33396 \r
33397     // private\r
33398     handleHdMove : function(e, t){\r
33399         if(this.activeHd && !this.headersDisabled){\r
33400             var hw = this.splitHandleWidth || 5;\r
33401             var r = this.activeHdRegion;\r
33402             var x = e.getPageX();\r
33403             var ss = this.activeHd.style;\r
33404             if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){\r
33405                 ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'e-resize' : 'col-resize'; // col-resize not always supported\r
33406             }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){\r
33407                 ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'w-resize' : 'col-resize';\r
33408             }else{\r
33409                 ss.cursor = '';\r
33410             }\r
33411         }\r
33412     },\r
33413 \r
33414     // private\r
33415     handleHdOut : function(e, t){\r
33416         var hd = this.findHeaderCell(t);\r
33417         if(hd && (!Ext.isIE || !e.within(hd, true))){\r
33418             this.activeHd = null;\r
33419             this.fly(hd).removeClass("x-grid3-hd-over");\r
33420             hd.style.cursor = '';\r
33421         }\r
33422     },\r
33423 \r
33424     // private\r
33425     hasRows : function(){\r
33426         var fc = this.mainBody.dom.firstChild;\r
33427         return fc && fc.className != 'x-grid-empty';\r
33428     },\r
33429 \r
33430     // back compat\r
33431     bind : function(d, c){\r
33432         this.initData(d, c);\r
33433     }\r
33434 });\r
33435 \r
33436 \r
33437 // private\r
33438 // This is a support class used internally by the Grid components\r
33439 Ext.grid.GridView.SplitDragZone = function(grid, hd){\r
33440     this.grid = grid;\r
33441     this.view = grid.getView();\r
33442     this.marker = this.view.resizeMarker;\r
33443     this.proxy = this.view.resizeProxy;\r
33444     Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,\r
33445         "gridSplitters" + this.grid.getGridEl().id, {\r
33446         dragElId : Ext.id(this.proxy.dom), resizeFrame:false\r
33447     });\r
33448     this.scroll = false;\r
33449     this.hw = this.view.splitHandleWidth || 5;\r
33450 };\r
33451 Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {\r
33452 \r
33453     b4StartDrag : function(x, y){\r
33454         this.view.headersDisabled = true;\r
33455         var h = this.view.mainWrap.getHeight();\r
33456         this.marker.setHeight(h);\r
33457         this.marker.show();\r
33458         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);\r
33459         this.proxy.setHeight(h);\r
33460         var w = this.cm.getColumnWidth(this.cellIndex);\r
33461         var minw = Math.max(w-this.grid.minColumnWidth, 0);\r
33462         this.resetConstraints();\r
33463         this.setXConstraint(minw, 1000);\r
33464         this.setYConstraint(0, 0);\r
33465         this.minX = x - minw;\r
33466         this.maxX = x + 1000;\r
33467         this.startPos = x;\r
33468         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);\r
33469     },\r
33470 \r
33471 \r
33472     handleMouseDown : function(e){\r
33473         var t = this.view.findHeaderCell(e.getTarget());\r
33474         if(t){\r
33475             var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];\r
33476             var exy = e.getXY(), ex = exy[0], ey = exy[1];\r
33477             var w = t.offsetWidth, adjust = false;\r
33478             if((ex - x) <= this.hw){\r
33479                 adjust = -1;\r
33480             }else if((x+w) - ex <= this.hw){\r
33481                 adjust = 0;\r
33482             }\r
33483             if(adjust !== false){\r
33484                 this.cm = this.grid.colModel;\r
33485                 var ci = this.view.getCellIndex(t);\r
33486                 if(adjust == -1){\r
33487                   if (ci + adjust < 0) {\r
33488                     return;\r
33489                   }\r
33490                     while(this.cm.isHidden(ci+adjust)){\r
33491                         --adjust;\r
33492                         if(ci+adjust < 0){\r
33493                             return;\r
33494                         }\r
33495                     }\r
33496                 }\r
33497                 this.cellIndex = ci+adjust;\r
33498                 this.split = t.dom;\r
33499                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){\r
33500                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);\r
33501                 }\r
33502             }else if(this.view.columnDrag){\r
33503                 this.view.columnDrag.callHandleMouseDown(e);\r
33504             }\r
33505         }\r
33506     },\r
33507 \r
33508     endDrag : function(e){\r
33509         this.marker.hide();\r
33510         var v = this.view;\r
33511         var endX = Math.max(this.minX, e.getPageX());\r
33512         var diff = endX - this.startPos;\r
33513         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);\r
33514         setTimeout(function(){\r
33515             v.headersDisabled = false;\r
33516         }, 50);\r
33517     },\r
33518 \r
33519     autoOffset : function(){\r
33520         this.setDelta(0,0);\r
33521     }\r
33522 });\r
33523 \r
33524 \r
33525 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {\r
33526     \r
33527     hideGroupedColumn:false,\r
33528     \r
33529     showGroupName:true,\r
33530     \r
33531     startCollapsed:false,\r
33532     \r
33533     enableGrouping:true,\r
33534     \r
33535     enableGroupingMenu:true,\r
33536     \r
33537     enableNoGroups:true,\r
33538     \r
33539     emptyGroupText : '(None)',\r
33540     \r
33541     ignoreAdd: false,\r
33542     \r
33543     groupTextTpl : '{text}',\r
33544     \r
33545     \r
33546 \r
33547     // private\r
33548     gidSeed : 1000,\r
33549 \r
33550     // private\r
33551     initTemplates : function(){\r
33552         Ext.grid.GroupingView.superclass.initTemplates.call(this);\r
33553         this.state = {};\r
33554 \r
33555         var sm = this.grid.getSelectionModel();\r
33556         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',\r
33557                 this.onBeforeRowSelect, this);\r
33558 \r
33559         if(!this.startGroup){\r
33560             this.startGroup = new Ext.XTemplate(\r
33561                 '<div id="{groupId}" class="x-grid-group {cls}">',\r
33562                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>', this.groupTextTpl ,'</div></div>',\r
33563                     '<div id="{groupId}-bd" class="x-grid-group-body">'\r
33564             );\r
33565         }\r
33566         this.startGroup.compile();\r
33567         this.endGroup = '</div></div>';\r
33568     },\r
33569 \r
33570     // private\r
33571     findGroup : function(el){\r
33572         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);\r
33573     },\r
33574 \r
33575     // private\r
33576     getGroups : function(){\r
33577         return this.hasRows() ? this.mainBody.dom.childNodes : [];\r
33578     },\r
33579 \r
33580     // private\r
33581     onAdd : function(){\r
33582         if(this.enableGrouping && !this.ignoreAdd){\r
33583             var ss = this.getScrollState();\r
33584             this.refresh();\r
33585             this.restoreScroll(ss);\r
33586         }else if(!this.enableGrouping){\r
33587             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);\r
33588         }\r
33589     },\r
33590 \r
33591     // private\r
33592     onRemove : function(ds, record, index, isUpdate){\r
33593         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);\r
33594         var g = document.getElementById(record._groupId);\r
33595         if(g && g.childNodes[1].childNodes.length < 1){\r
33596             Ext.removeNode(g);\r
33597         }\r
33598         this.applyEmptyText();\r
33599     },\r
33600 \r
33601     // private\r
33602     refreshRow : function(record){\r
33603         if(this.ds.getCount()==1){\r
33604             this.refresh();\r
33605         }else{\r
33606             this.isUpdating = true;\r
33607             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);\r
33608             this.isUpdating = false;\r
33609         }\r
33610     },\r
33611 \r
33612     // private\r
33613     beforeMenuShow : function(){\r
33614         var field = this.getGroupField();\r
33615         var g = this.hmenu.items.get('groupBy');\r
33616         if(g){\r
33617             g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);\r
33618         }\r
33619         var s = this.hmenu.items.get('showGroups');\r
33620         if(s){\r
33621            s.setDisabled(!field && this.cm.config[this.hdCtxIndex].groupable === false);\r
33622                         s.setChecked(!!field, true);\r
33623         }\r
33624     },\r
33625 \r
33626     // private\r
33627     renderUI : function(){\r
33628         Ext.grid.GroupingView.superclass.renderUI.call(this);\r
33629         this.mainBody.on('mousedown', this.interceptMouse, this);\r
33630 \r
33631         if(this.enableGroupingMenu && this.hmenu){\r
33632             this.hmenu.add('-',{\r
33633                 id:'groupBy',\r
33634                 text: this.groupByText,\r
33635                 handler: this.onGroupByClick,\r
33636                 scope: this,\r
33637                 iconCls:'x-group-by-icon'\r
33638             });\r
33639             if(this.enableNoGroups){\r
33640                 this.hmenu.add({\r
33641                     id:'showGroups',\r
33642                     text: this.showGroupsText,\r
33643                     checked: true,\r
33644                     checkHandler: this.onShowGroupsClick,\r
33645                     scope: this\r
33646                 });\r
33647             }\r
33648             this.hmenu.on('beforeshow', this.beforeMenuShow, this);\r
33649         }\r
33650     },\r
33651 \r
33652     // private\r
33653     onGroupByClick : function(){\r
33654         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));\r
33655         this.beforeMenuShow(); // Make sure the checkboxes get properly set when changing groups\r
33656     },\r
33657 \r
33658     // private\r
33659     onShowGroupsClick : function(mi, checked){\r
33660         if(checked){\r
33661             this.onGroupByClick();\r
33662         }else{\r
33663             this.grid.store.clearGrouping();\r
33664         }\r
33665     },\r
33666 \r
33667     \r
33668     toggleGroup : function(group, expanded){\r
33669         this.grid.stopEditing(true);\r
33670         group = Ext.getDom(group);\r
33671         var gel = Ext.fly(group);\r
33672         expanded = expanded !== undefined ?\r
33673                 expanded : gel.hasClass('x-grid-group-collapsed');\r
33674 \r
33675         this.state[gel.dom.id] = expanded;\r
33676         gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');\r
33677     },\r
33678 \r
33679     \r
33680     toggleAllGroups : function(expanded){\r
33681         var groups = this.getGroups();\r
33682         for(var i = 0, len = groups.length; i < len; i++){\r
33683             this.toggleGroup(groups[i], expanded);\r
33684         }\r
33685     },\r
33686 \r
33687     \r
33688     expandAllGroups : function(){\r
33689         this.toggleAllGroups(true);\r
33690     },\r
33691 \r
33692     \r
33693     collapseAllGroups : function(){\r
33694         this.toggleAllGroups(false);\r
33695     },\r
33696 \r
33697     // private\r
33698     interceptMouse : function(e){\r
33699         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);\r
33700         if(hd){\r
33701             e.stopEvent();\r
33702             this.toggleGroup(hd.parentNode);\r
33703         }\r
33704     },\r
33705 \r
33706     // private\r
33707     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){\r
33708         var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);\r
33709         if(g === ''){\r
33710             g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;\r
33711         }\r
33712         return g;\r
33713     },\r
33714 \r
33715     // private\r
33716     getGroupField : function(){\r
33717         return this.grid.store.getGroupState();\r
33718     },\r
33719 \r
33720     // private\r
33721     renderRows : function(){\r
33722         var groupField = this.getGroupField();\r
33723         var eg = !!groupField;\r
33724         // if they turned off grouping and the last grouped field is hidden\r
33725         if(this.hideGroupedColumn) {\r
33726             var colIndex = this.cm.findColumnIndex(groupField);\r
33727             if(!eg && this.lastGroupField !== undefined) {\r
33728                 this.mainBody.update('');\r
33729                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);\r
33730                 delete this.lastGroupField;\r
33731             }else if (eg && this.lastGroupField === undefined) {\r
33732                 this.lastGroupField = groupField;\r
33733                 this.cm.setHidden(colIndex, true);\r
33734             }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {\r
33735                 this.mainBody.update('');\r
33736                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);\r
33737                 this.cm.setHidden(oldIndex, false);\r
33738                 this.lastGroupField = groupField;\r
33739                 this.cm.setHidden(colIndex, true);\r
33740             }\r
33741         }\r
33742         return Ext.grid.GroupingView.superclass.renderRows.apply(\r
33743                     this, arguments);\r
33744     },\r
33745 \r
33746     // private\r
33747     doRender : function(cs, rs, ds, startRow, colCount, stripe){\r
33748         if(rs.length < 1){\r
33749             return '';\r
33750         }\r
33751         var groupField = this.getGroupField();\r
33752         var colIndex = this.cm.findColumnIndex(groupField);\r
33753 \r
33754         this.enableGrouping = !!groupField;\r
33755 \r
33756         if(!this.enableGrouping || this.isUpdating){\r
33757             return Ext.grid.GroupingView.superclass.doRender.apply(\r
33758                     this, arguments);\r
33759         }\r
33760         var gstyle = 'width:'+this.getTotalWidth()+';';\r
33761 \r
33762         var gidPrefix = this.grid.getGridEl().id;\r
33763         var cfg = this.cm.config[colIndex];\r
33764         var groupRenderer = cfg.groupRenderer || cfg.renderer;\r
33765         var prefix = this.showGroupName ?\r
33766                      (cfg.groupName || cfg.header)+': ' : '';\r
33767 \r
33768         var groups = [], curGroup, i, len, gid;\r
33769         for(i = 0, len = rs.length; i < len; i++){\r
33770             var rowIndex = startRow + i;\r
33771             var r = rs[i],\r
33772                 gvalue = r.data[groupField],\r
33773                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);\r
33774             if(!curGroup || curGroup.group != g){\r
33775                 gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);\r
33776                 // if state is defined use it, however state is in terms of expanded\r
33777                                 // so negate it, otherwise use the default.\r
33778                                 var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;\r
33779                                 var gcls = isCollapsed ? 'x-grid-group-collapsed' : ''; \r
33780                 curGroup = {\r
33781                     group: g,\r
33782                     gvalue: gvalue,\r
33783                     text: prefix + g,\r
33784                     groupId: gid,\r
33785                     startRow: rowIndex,\r
33786                     rs: [r],\r
33787                     cls: gcls,\r
33788                     style: gstyle\r
33789                 };\r
33790                 groups.push(curGroup);\r
33791             }else{\r
33792                 curGroup.rs.push(r);\r
33793             }\r
33794             r._groupId = gid;\r
33795         }\r
33796 \r
33797         var buf = [];\r
33798         for(i = 0, len = groups.length; i < len; i++){\r
33799             var g = groups[i];\r
33800             this.doGroupStart(buf, g, cs, ds, colCount);\r
33801             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(\r
33802                     this, cs, g.rs, ds, g.startRow, colCount, stripe);\r
33803 \r
33804             this.doGroupEnd(buf, g, cs, ds, colCount);\r
33805         }\r
33806         return buf.join('');\r
33807     },\r
33808 \r
33809     \r
33810     getGroupId : function(value){\r
33811         var gidPrefix = this.grid.getGridEl().id;\r
33812         var groupField = this.getGroupField();\r
33813         var colIndex = this.cm.findColumnIndex(groupField);\r
33814         var cfg = this.cm.config[colIndex];\r
33815         var groupRenderer = cfg.groupRenderer || cfg.renderer;\r
33816         var gtext = this.getGroup(value, {data:{}}, groupRenderer, 0, colIndex, this.ds);\r
33817         return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);\r
33818     },\r
33819 \r
33820     // private\r
33821     doGroupStart : function(buf, g, cs, ds, colCount){\r
33822         buf[buf.length] = this.startGroup.apply(g);\r
33823     },\r
33824 \r
33825     // private\r
33826     doGroupEnd : function(buf, g, cs, ds, colCount){\r
33827         buf[buf.length] = this.endGroup;\r
33828     },\r
33829 \r
33830     // private\r
33831     getRows : function(){\r
33832         if(!this.enableGrouping){\r
33833             return Ext.grid.GroupingView.superclass.getRows.call(this);\r
33834         }\r
33835         var r = [];\r
33836         var g, gs = this.getGroups();\r
33837         for(var i = 0, len = gs.length; i < len; i++){\r
33838             g = gs[i].childNodes[1].childNodes;\r
33839             for(var j = 0, jlen = g.length; j < jlen; j++){\r
33840                 r[r.length] = g[j];\r
33841             }\r
33842         }\r
33843         return r;\r
33844     },\r
33845 \r
33846     // private\r
33847     updateGroupWidths : function(){\r
33848         if(!this.enableGrouping || !this.hasRows()){\r
33849             return;\r
33850         }\r
33851         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.scrollOffset) +'px';\r
33852         var gs = this.getGroups();\r
33853         for(var i = 0, len = gs.length; i < len; i++){\r
33854             gs[i].firstChild.style.width = tw;\r
33855         }\r
33856     },\r
33857 \r
33858     // private\r
33859     onColumnWidthUpdated : function(col, w, tw){\r
33860         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);\r
33861         this.updateGroupWidths();\r
33862     },\r
33863 \r
33864     // private\r
33865     onAllColumnWidthsUpdated : function(ws, tw){\r
33866         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);\r
33867         this.updateGroupWidths();\r
33868     },\r
33869 \r
33870     // private\r
33871     onColumnHiddenUpdated : function(col, hidden, tw){\r
33872         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);\r
33873         this.updateGroupWidths();\r
33874     },\r
33875 \r
33876     // private\r
33877     onLayout : function(){\r
33878         this.updateGroupWidths();\r
33879     },\r
33880 \r
33881     // private\r
33882     onBeforeRowSelect : function(sm, rowIndex){\r
33883         if(!this.enableGrouping){\r
33884             return;\r
33885         }\r
33886         var row = this.getRow(rowIndex);\r
33887         if(row && !row.offsetParent){\r
33888             var g = this.findGroup(row);\r
33889             this.toggleGroup(g, true);\r
33890         }\r
33891     },\r
33892 \r
33893     \r
33894     groupByText: 'Group By This Field',\r
33895     \r
33896     showGroupsText: 'Show in Groups'\r
33897 });\r
33898 // private\r
33899 Ext.grid.GroupingView.GROUP_ID = 1000;\r
33900 // private\r
33901 // This is a support class used internally by the Grid components\r
33902 Ext.grid.HeaderDragZone = function(grid, hd, hd2){\r
33903     this.grid = grid;\r
33904     this.view = grid.getView();\r
33905     this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
33906     Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);\r
33907     if(hd2){\r
33908         this.setHandleElId(Ext.id(hd));\r
33909         this.setOuterHandleElId(Ext.id(hd2));\r
33910     }\r
33911     this.scroll = false;\r
33912 };\r
33913 Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {\r
33914     maxDragWidth: 120,\r
33915     getDragData : function(e){\r
33916         var t = Ext.lib.Event.getTarget(e);\r
33917         var h = this.view.findHeaderCell(t);\r
33918         if(h){\r
33919             return {ddel: h.firstChild, header:h};\r
33920         }\r
33921         return false;\r
33922     },\r
33923 \r
33924     onInitDrag : function(e){\r
33925         this.view.headersDisabled = true;\r
33926         var clone = this.dragData.ddel.cloneNode(true);\r
33927         clone.id = Ext.id();\r
33928         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";\r
33929         this.proxy.update(clone);\r
33930         return true;\r
33931     },\r
33932 \r
33933     afterValidDrop : function(){\r
33934         var v = this.view;\r
33935         setTimeout(function(){\r
33936             v.headersDisabled = false;\r
33937         }, 50);\r
33938     },\r
33939 \r
33940     afterInvalidDrop : function(){\r
33941         var v = this.view;\r
33942         setTimeout(function(){\r
33943             v.headersDisabled = false;\r
33944         }, 50);\r
33945     }\r
33946 });\r
33947 \r
33948 // private\r
33949 // This is a support class used internally by the Grid components\r
33950 Ext.grid.HeaderDropZone = function(grid, hd, hd2){\r
33951     this.grid = grid;\r
33952     this.view = grid.getView();\r
33953     // split the proxies so they don't interfere with mouse events\r
33954     this.proxyTop = Ext.DomHelper.append(document.body, {\r
33955         cls:"col-move-top", html:"&#160;"\r
33956     }, true);\r
33957     this.proxyBottom = Ext.DomHelper.append(document.body, {\r
33958         cls:"col-move-bottom", html:"&#160;"\r
33959     }, true);\r
33960     this.proxyTop.hide = this.proxyBottom.hide = function(){\r
33961         this.setLeftTop(-100,-100);\r
33962         this.setStyle("visibility", "hidden");\r
33963     };\r
33964     this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
33965     // temporarily disabled\r
33966     //Ext.dd.ScrollManager.register(this.view.scroller.dom);\r
33967     Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);\r
33968 };\r
33969 Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {\r
33970     proxyOffsets : [-4, -9],\r
33971     fly: Ext.Element.fly,\r
33972 \r
33973     getTargetFromEvent : function(e){\r
33974         var t = Ext.lib.Event.getTarget(e);\r
33975         var cindex = this.view.findCellIndex(t);\r
33976         if(cindex !== false){\r
33977             return this.view.getHeaderCell(cindex);\r
33978         }\r
33979     },\r
33980 \r
33981     nextVisible : function(h){\r
33982         var v = this.view, cm = this.grid.colModel;\r
33983         h = h.nextSibling;\r
33984         while(h){\r
33985             if(!cm.isHidden(v.getCellIndex(h))){\r
33986                 return h;\r
33987             }\r
33988             h = h.nextSibling;\r
33989         }\r
33990         return null;\r
33991     },\r
33992 \r
33993     prevVisible : function(h){\r
33994         var v = this.view, cm = this.grid.colModel;\r
33995         h = h.prevSibling;\r
33996         while(h){\r
33997             if(!cm.isHidden(v.getCellIndex(h))){\r
33998                 return h;\r
33999             }\r
34000             h = h.prevSibling;\r
34001         }\r
34002         return null;\r
34003     },\r
34004 \r
34005     positionIndicator : function(h, n, e){\r
34006         var x = Ext.lib.Event.getPageX(e);\r
34007         var r = Ext.lib.Dom.getRegion(n.firstChild);\r
34008         var px, pt, py = r.top + this.proxyOffsets[1];\r
34009         if((r.right - x) <= (r.right-r.left)/2){\r
34010             px = r.right+this.view.borderWidth;\r
34011             pt = "after";\r
34012         }else{\r
34013             px = r.left;\r
34014             pt = "before";\r
34015         }\r
34016         var oldIndex = this.view.getCellIndex(h);\r
34017         var newIndex = this.view.getCellIndex(n);\r
34018 \r
34019         if(this.grid.colModel.isFixed(newIndex)){\r
34020             return false;\r
34021         }\r
34022 \r
34023         var locked = this.grid.colModel.isLocked(newIndex);\r
34024 \r
34025         if(pt == "after"){\r
34026             newIndex++;\r
34027         }\r
34028         if(oldIndex < newIndex){\r
34029             newIndex--;\r
34030         }\r
34031         if(oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))){\r
34032             return false;\r
34033         }\r
34034         px +=  this.proxyOffsets[0];\r
34035         this.proxyTop.setLeftTop(px, py);\r
34036         this.proxyTop.show();\r
34037         if(!this.bottomOffset){\r
34038             this.bottomOffset = this.view.mainHd.getHeight();\r
34039         }\r
34040         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);\r
34041         this.proxyBottom.show();\r
34042         return pt;\r
34043     },\r
34044 \r
34045     onNodeEnter : function(n, dd, e, data){\r
34046         if(data.header != n){\r
34047             this.positionIndicator(data.header, n, e);\r
34048         }\r
34049     },\r
34050 \r
34051     onNodeOver : function(n, dd, e, data){\r
34052         var result = false;\r
34053         if(data.header != n){\r
34054             result = this.positionIndicator(data.header, n, e);\r
34055         }\r
34056         if(!result){\r
34057             this.proxyTop.hide();\r
34058             this.proxyBottom.hide();\r
34059         }\r
34060         return result ? this.dropAllowed : this.dropNotAllowed;\r
34061     },\r
34062 \r
34063     onNodeOut : function(n, dd, e, data){\r
34064         this.proxyTop.hide();\r
34065         this.proxyBottom.hide();\r
34066     },\r
34067 \r
34068     onNodeDrop : function(n, dd, e, data){\r
34069         var h = data.header;\r
34070         if(h != n){\r
34071             var cm = this.grid.colModel;\r
34072             var x = Ext.lib.Event.getPageX(e);\r
34073             var r = Ext.lib.Dom.getRegion(n.firstChild);\r
34074             var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";\r
34075             var oldIndex = this.view.getCellIndex(h);\r
34076             var newIndex = this.view.getCellIndex(n);\r
34077             var locked = cm.isLocked(newIndex);\r
34078             if(pt == "after"){\r
34079                 newIndex++;\r
34080             }\r
34081             if(oldIndex < newIndex){\r
34082                 newIndex--;\r
34083             }\r
34084             if(oldIndex == newIndex && (locked == cm.isLocked(oldIndex))){\r
34085                 return false;\r
34086             }\r
34087             cm.setLocked(oldIndex, locked, true);\r
34088             cm.moveColumn(oldIndex, newIndex);\r
34089             this.grid.fireEvent("columnmove", oldIndex, newIndex);\r
34090             return true;\r
34091         }\r
34092         return false;\r
34093     }\r
34094 });\r
34095 \r
34096 \r
34097 Ext.grid.GridView.ColumnDragZone = function(grid, hd){\r
34098     Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);\r
34099     this.proxy.el.addClass('x-grid3-col-dd');\r
34100 };\r
34101 \r
34102 Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {\r
34103     handleMouseDown : function(e){\r
34104 \r
34105     },\r
34106 \r
34107     callHandleMouseDown : function(e){\r
34108         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);\r
34109     }\r
34110 });\r
34111 // private\r
34112 // This is a support class used internally by the Grid components\r
34113 Ext.grid.SplitDragZone = function(grid, hd, hd2){\r
34114     this.grid = grid;\r
34115     this.view = grid.getView();\r
34116     this.proxy = this.view.resizeProxy;\r
34117     Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,\r
34118         "gridSplitters" + this.grid.getGridEl().id, {\r
34119         dragElId : Ext.id(this.proxy.dom), resizeFrame:false\r
34120     });\r
34121     this.setHandleElId(Ext.id(hd));\r
34122     this.setOuterHandleElId(Ext.id(hd2));\r
34123     this.scroll = false;\r
34124 };\r
34125 Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {\r
34126     fly: Ext.Element.fly,\r
34127 \r
34128     b4StartDrag : function(x, y){\r
34129         this.view.headersDisabled = true;\r
34130         this.proxy.setHeight(this.view.mainWrap.getHeight());\r
34131         var w = this.cm.getColumnWidth(this.cellIndex);\r
34132         var minw = Math.max(w-this.grid.minColumnWidth, 0);\r
34133         this.resetConstraints();\r
34134         this.setXConstraint(minw, 1000);\r
34135         this.setYConstraint(0, 0);\r
34136         this.minX = x - minw;\r
34137         this.maxX = x + 1000;\r
34138         this.startPos = x;\r
34139         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);\r
34140     },\r
34141 \r
34142 \r
34143     handleMouseDown : function(e){\r
34144         ev = Ext.EventObject.setEvent(e);\r
34145         var t = this.fly(ev.getTarget());\r
34146         if(t.hasClass("x-grid-split")){\r
34147             this.cellIndex = this.view.getCellIndex(t.dom);\r
34148             this.split = t.dom;\r
34149             this.cm = this.grid.colModel;\r
34150             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){\r
34151                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);\r
34152             }\r
34153         }\r
34154     },\r
34155 \r
34156     endDrag : function(e){\r
34157         this.view.headersDisabled = false;\r
34158         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));\r
34159         var diff = endX - this.startPos;\r
34160         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);\r
34161     },\r
34162 \r
34163     autoOffset : function(){\r
34164         this.setDelta(0,0);\r
34165     }\r
34166 });\r
34167 \r
34168 Ext.grid.GridDragZone = function(grid, config){\r
34169     this.view = grid.getView();\r
34170     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);\r
34171     if(this.view.lockedBody){\r
34172         this.setHandleElId(Ext.id(this.view.mainBody.dom));\r
34173         this.setOuterHandleElId(Ext.id(this.view.lockedBody.dom));\r
34174     }\r
34175     this.scroll = false;\r
34176     this.grid = grid;\r
34177     this.ddel = document.createElement('div');\r
34178     this.ddel.className = 'x-grid-dd-wrap';\r
34179 };\r
34180 \r
34181 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {\r
34182     ddGroup : "GridDD",\r
34183 \r
34184     \r
34185     getDragData : function(e){\r
34186         var t = Ext.lib.Event.getTarget(e);\r
34187         var rowIndex = this.view.findRowIndex(t);\r
34188         if(rowIndex !== false){\r
34189             var sm = this.grid.selModel;\r
34190             if(!sm.isSelected(rowIndex) || e.hasModifier()){\r
34191                 sm.handleMouseDown(this.grid, rowIndex, e);\r
34192             }\r
34193             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};\r
34194         }\r
34195         return false;\r
34196     },\r
34197 \r
34198     \r
34199     onInitDrag : function(e){\r
34200         var data = this.dragData;\r
34201         this.ddel.innerHTML = this.grid.getDragDropText();\r
34202         this.proxy.update(this.ddel);\r
34203         // fire start drag?\r
34204     },\r
34205 \r
34206     \r
34207     afterRepair : function(){\r
34208         this.dragging = false;\r
34209     },\r
34210 \r
34211     \r
34212     getRepairXY : function(e, data){\r
34213         return false;\r
34214     },\r
34215 \r
34216     onEndDrag : function(data, e){\r
34217         // fire end drag?\r
34218     },\r
34219 \r
34220     onValidDrop : function(dd, e, id){\r
34221         // fire drag drop?\r
34222         this.hideProxy();\r
34223     },\r
34224 \r
34225     beforeInvalidDrop : function(e, id){\r
34226 \r
34227     }\r
34228 });\r
34229 \r
34230 \r
34231 Ext.grid.ColumnModel = function(config){\r
34232     \r
34233     this.defaultWidth = 100;\r
34234 \r
34235     \r
34236     this.defaultSortable = false;\r
34237 \r
34238     \r
34239     if(config.columns){\r
34240         Ext.apply(this, config);\r
34241         this.setConfig(config.columns, true);\r
34242     }else{\r
34243         this.setConfig(config, true);\r
34244     }\r
34245     this.addEvents(\r
34246         \r
34247         "widthchange",\r
34248         \r
34249         "headerchange",\r
34250         \r
34251         "hiddenchange",\r
34252         \r
34253         "columnmoved",\r
34254         // deprecated - to be removed\r
34255         "columnlockchange",\r
34256         \r
34257         "configchange"\r
34258     );\r
34259     Ext.grid.ColumnModel.superclass.constructor.call(this);\r
34260 };\r
34261 Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {\r
34262     \r
34263     \r
34264     \r
34265     \r
34266     \r
34267     \r
34268     \r
34269     \r
34270     \r
34271     \r
34272     \r
34273     \r
34274     \r
34275     \r
34276     \r
34277 \r
34278     \r
34279     getColumnId : function(index){\r
34280         return this.config[index].id;\r
34281     },\r
34282 \r
34283     \r
34284     setConfig : function(config, initial){\r
34285         if(!initial){ // cleanup\r
34286             delete this.totalWidth;\r
34287             for(var i = 0, len = this.config.length; i < len; i++){\r
34288                 var c = this.config[i];\r
34289                 if(c.editor){\r
34290                     c.editor.destroy();\r
34291                 }\r
34292             }\r
34293         }\r
34294         this.config = config;\r
34295         this.lookup = {};\r
34296         // if no id, create one\r
34297         for(var i = 0, len = config.length; i < len; i++){\r
34298             var c = config[i];\r
34299             if(typeof c.renderer == "string"){\r
34300                 c.renderer = Ext.util.Format[c.renderer];\r
34301             }\r
34302             if(typeof c.id == "undefined"){\r
34303                 c.id = i;\r
34304             }\r
34305             if(c.editor && c.editor.isFormField){\r
34306                 c.editor = new Ext.grid.GridEditor(c.editor);\r
34307             }\r
34308             this.lookup[c.id] = c;\r
34309         }\r
34310         if(!initial){\r
34311             this.fireEvent('configchange', this);\r
34312         }\r
34313     },\r
34314 \r
34315     \r
34316     getColumnById : function(id){\r
34317         return this.lookup[id];\r
34318     },\r
34319 \r
34320     \r
34321     getIndexById : function(id){\r
34322         for(var i = 0, len = this.config.length; i < len; i++){\r
34323             if(this.config[i].id == id){\r
34324                 return i;\r
34325             }\r
34326         }\r
34327         return -1;\r
34328     },\r
34329 \r
34330     \r
34331     moveColumn : function(oldIndex, newIndex){\r
34332         var c = this.config[oldIndex];\r
34333         this.config.splice(oldIndex, 1);\r
34334         this.config.splice(newIndex, 0, c);\r
34335         this.dataMap = null;\r
34336         this.fireEvent("columnmoved", this, oldIndex, newIndex);\r
34337     },\r
34338 \r
34339     // deprecated - to be removed\r
34340     isLocked : function(colIndex){\r
34341         return this.config[colIndex].locked === true;\r
34342     },\r
34343 \r
34344     // deprecated - to be removed\r
34345     setLocked : function(colIndex, value, suppressEvent){\r
34346         if(this.isLocked(colIndex) == value){\r
34347             return;\r
34348         }\r
34349         this.config[colIndex].locked = value;\r
34350         if(!suppressEvent){\r
34351             this.fireEvent("columnlockchange", this, colIndex, value);\r
34352         }\r
34353     },\r
34354 \r
34355     // deprecated - to be removed\r
34356     getTotalLockedWidth : function(){\r
34357         var totalWidth = 0;\r
34358         for(var i = 0; i < this.config.length; i++){\r
34359             if(this.isLocked(i) && !this.isHidden(i)){\r
34360                 this.totalWidth += this.getColumnWidth(i);\r
34361             }\r
34362         }\r
34363         return totalWidth;\r
34364     },\r
34365 \r
34366     // deprecated - to be removed\r
34367     getLockedCount : function(){\r
34368         for(var i = 0, len = this.config.length; i < len; i++){\r
34369             if(!this.isLocked(i)){\r
34370                 return i;\r
34371             }\r
34372         }\r
34373     },\r
34374 \r
34375     \r
34376     getColumnCount : function(visibleOnly){\r
34377         if(visibleOnly === true){\r
34378             var c = 0;\r
34379             for(var i = 0, len = this.config.length; i < len; i++){\r
34380                 if(!this.isHidden(i)){\r
34381                     c++;\r
34382                 }\r
34383             }\r
34384             return c;\r
34385         }\r
34386         return this.config.length;\r
34387     },\r
34388 \r
34389     \r
34390     getColumnsBy : function(fn, scope){\r
34391         var r = [];\r
34392         for(var i = 0, len = this.config.length; i < len; i++){\r
34393             var c = this.config[i];\r
34394             if(fn.call(scope||this, c, i) === true){\r
34395                 r[r.length] = c;\r
34396             }\r
34397         }\r
34398         return r;\r
34399     },\r
34400 \r
34401     \r
34402     isSortable : function(col){\r
34403         if(typeof this.config[col].sortable == "undefined"){\r
34404             return this.defaultSortable;\r
34405         }\r
34406         return this.config[col].sortable;\r
34407     },\r
34408 \r
34409     \r
34410     isMenuDisabled : function(col){\r
34411         return !!this.config[col].menuDisabled;\r
34412     },\r
34413 \r
34414     \r
34415     getRenderer : function(col){\r
34416         if(!this.config[col].renderer){\r
34417             return Ext.grid.ColumnModel.defaultRenderer;\r
34418         }\r
34419         return this.config[col].renderer;\r
34420     },\r
34421 \r
34422     \r
34423     setRenderer : function(col, fn){\r
34424         this.config[col].renderer = fn;\r
34425     },\r
34426 \r
34427     \r
34428     getColumnWidth : function(col){\r
34429         return this.config[col].width || this.defaultWidth;\r
34430     },\r
34431 \r
34432     \r
34433     setColumnWidth : function(col, width, suppressEvent){\r
34434         this.config[col].width = width;\r
34435         this.totalWidth = null;\r
34436         if(!suppressEvent){\r
34437              this.fireEvent("widthchange", this, col, width);\r
34438         }\r
34439     },\r
34440 \r
34441     \r
34442     getTotalWidth : function(includeHidden){\r
34443         if(!this.totalWidth){\r
34444             this.totalWidth = 0;\r
34445             for(var i = 0, len = this.config.length; i < len; i++){\r
34446                 if(includeHidden || !this.isHidden(i)){\r
34447                     this.totalWidth += this.getColumnWidth(i);\r
34448                 }\r
34449             }\r
34450         }\r
34451         return this.totalWidth;\r
34452     },\r
34453 \r
34454     \r
34455     getColumnHeader : function(col){\r
34456         return this.config[col].header;\r
34457     },\r
34458 \r
34459     \r
34460     setColumnHeader : function(col, header){\r
34461         this.config[col].header = header;\r
34462         this.fireEvent("headerchange", this, col, header);\r
34463     },\r
34464 \r
34465     \r
34466     getColumnTooltip : function(col){\r
34467             return this.config[col].tooltip;\r
34468     },\r
34469     \r
34470     setColumnTooltip : function(col, tooltip){\r
34471             this.config[col].tooltip = tooltip;\r
34472     },\r
34473 \r
34474     \r
34475     getDataIndex : function(col){\r
34476         return this.config[col].dataIndex;\r
34477     },\r
34478 \r
34479     \r
34480     setDataIndex : function(col, dataIndex){\r
34481         this.config[col].dataIndex = dataIndex;\r
34482     },\r
34483 \r
34484     \r
34485     findColumnIndex : function(dataIndex){\r
34486         var c = this.config;\r
34487         for(var i = 0, len = c.length; i < len; i++){\r
34488             if(c[i].dataIndex == dataIndex){\r
34489                 return i;\r
34490             }\r
34491         }\r
34492         return -1;\r
34493     },\r
34494 \r
34495     \r
34496     isCellEditable : function(colIndex, rowIndex){\r
34497         return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;\r
34498     },\r
34499 \r
34500     \r
34501     getCellEditor : function(colIndex, rowIndex){\r
34502         return this.config[colIndex].editor;\r
34503     },\r
34504 \r
34505     \r
34506     setEditable : function(col, editable){\r
34507         this.config[col].editable = editable;\r
34508     },\r
34509 \r
34510 \r
34511     \r
34512     isHidden : function(colIndex){\r
34513         return this.config[colIndex].hidden;\r
34514     },\r
34515 \r
34516 \r
34517     \r
34518     isFixed : function(colIndex){\r
34519         return this.config[colIndex].fixed;\r
34520     },\r
34521 \r
34522     \r
34523     isResizable : function(colIndex){\r
34524         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;\r
34525     },\r
34526     \r
34527     setHidden : function(colIndex, hidden){\r
34528         var c = this.config[colIndex];\r
34529         if(c.hidden !== hidden){\r
34530             c.hidden = hidden;\r
34531             this.totalWidth = null;\r
34532             this.fireEvent("hiddenchange", this, colIndex, hidden);\r
34533         }\r
34534     },\r
34535 \r
34536     \r
34537     setEditor : function(col, editor){\r
34538         this.config[col].editor = editor;\r
34539     }\r
34540 });\r
34541 \r
34542 // private\r
34543 Ext.grid.ColumnModel.defaultRenderer = function(value){\r
34544     if(typeof value == "string" && value.length < 1){\r
34545         return "&#160;";\r
34546     }\r
34547     return value;\r
34548 };\r
34549 \r
34550 // Alias for backwards compatibility\r
34551 Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;\r
34552 \r
34553 Ext.grid.AbstractSelectionModel = function(){\r
34554     this.locked = false;\r
34555     Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);\r
34556 };\r
34557 \r
34558 Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {\r
34559     \r
34560     init : function(grid){\r
34561         this.grid = grid;\r
34562         this.initEvents();\r
34563     },\r
34564 \r
34565     \r
34566     lock : function(){\r
34567         this.locked = true;\r
34568     },\r
34569 \r
34570     \r
34571     unlock : function(){\r
34572         this.locked = false;\r
34573     },\r
34574 \r
34575     \r
34576     isLocked : function(){\r
34577         return this.locked;\r
34578     }\r
34579 });\r
34580 \r
34581 Ext.grid.RowSelectionModel = function(config){\r
34582     Ext.apply(this, config);\r
34583     this.selections = new Ext.util.MixedCollection(false, function(o){\r
34584         return o.id;\r
34585     });\r
34586 \r
34587     this.last = false;\r
34588     this.lastActive = false;\r
34589 \r
34590     this.addEvents(\r
34591         \r
34592             "selectionchange",\r
34593         \r
34594             "beforerowselect",\r
34595         \r
34596             "rowselect",\r
34597         \r
34598             "rowdeselect"\r
34599     );\r
34600 \r
34601     Ext.grid.RowSelectionModel.superclass.constructor.call(this);\r
34602 };\r
34603 \r
34604 Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {\r
34605     \r
34606     singleSelect : false,\r
34607 \r
34608         \r
34609     // private\r
34610     initEvents : function(){\r
34611 \r
34612         if(!this.grid.enableDragDrop && !this.grid.enableDrag){\r
34613             this.grid.on("rowmousedown", this.handleMouseDown, this);\r
34614         }else{ // allow click to work like normal\r
34615             this.grid.on("rowclick", function(grid, rowIndex, e) {\r
34616                 if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {\r
34617                     this.selectRow(rowIndex, false);\r
34618                     grid.view.focusRow(rowIndex);\r
34619                 }\r
34620             }, this);\r
34621         }\r
34622 \r
34623         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {\r
34624             "up" : function(e){\r
34625                 if(!e.shiftKey || this.singleSelect){\r
34626                     this.selectPrevious(false);\r
34627                 }else if(this.last !== false && this.lastActive !== false){\r
34628                     var last = this.last;\r
34629                     this.selectRange(this.last,  this.lastActive-1);\r
34630                     this.grid.getView().focusRow(this.lastActive);\r
34631                     if(last !== false){\r
34632                         this.last = last;\r
34633                     }\r
34634                 }else{\r
34635                     this.selectFirstRow();\r
34636                 }\r
34637             },\r
34638             "down" : function(e){\r
34639                 if(!e.shiftKey || this.singleSelect){\r
34640                     this.selectNext(false);\r
34641                 }else if(this.last !== false && this.lastActive !== false){\r
34642                     var last = this.last;\r
34643                     this.selectRange(this.last,  this.lastActive+1);\r
34644                     this.grid.getView().focusRow(this.lastActive);\r
34645                     if(last !== false){\r
34646                         this.last = last;\r
34647                     }\r
34648                 }else{\r
34649                     this.selectFirstRow();\r
34650                 }\r
34651             },\r
34652             scope: this\r
34653         });\r
34654 \r
34655         var view = this.grid.view;\r
34656         view.on("refresh", this.onRefresh, this);\r
34657         view.on("rowupdated", this.onRowUpdated, this);\r
34658         view.on("rowremoved", this.onRemove, this);\r
34659     },\r
34660 \r
34661     // private\r
34662     onRefresh : function(){\r
34663         var ds = this.grid.store, index;\r
34664         var s = this.getSelections();\r
34665         this.clearSelections(true);\r
34666         for(var i = 0, len = s.length; i < len; i++){\r
34667             var r = s[i];\r
34668             if((index = ds.indexOfId(r.id)) != -1){\r
34669                 this.selectRow(index, true);\r
34670             }\r
34671         }\r
34672         if(s.length != this.selections.getCount()){\r
34673             this.fireEvent("selectionchange", this);\r
34674         }\r
34675     },\r
34676 \r
34677     // private\r
34678     onRemove : function(v, index, r){\r
34679         if(this.selections.remove(r) !== false){\r
34680             this.fireEvent('selectionchange', this);\r
34681         }\r
34682     },\r
34683 \r
34684     // private\r
34685     onRowUpdated : function(v, index, r){\r
34686         if(this.isSelected(r)){\r
34687             v.onRowSelect(index);\r
34688         }\r
34689     },\r
34690 \r
34691     \r
34692     selectRecords : function(records, keepExisting){\r
34693         if(!keepExisting){\r
34694             this.clearSelections();\r
34695         }\r
34696         var ds = this.grid.store;\r
34697         for(var i = 0, len = records.length; i < len; i++){\r
34698             this.selectRow(ds.indexOf(records[i]), true);\r
34699         }\r
34700     },\r
34701 \r
34702     \r
34703     getCount : function(){\r
34704         return this.selections.length;\r
34705     },\r
34706 \r
34707     \r
34708     selectFirstRow : function(){\r
34709         this.selectRow(0);\r
34710     },\r
34711 \r
34712     \r
34713     selectLastRow : function(keepExisting){\r
34714         this.selectRow(this.grid.store.getCount() - 1, keepExisting);\r
34715     },\r
34716 \r
34717     \r
34718     selectNext : function(keepExisting){\r
34719         if(this.hasNext()){\r
34720             this.selectRow(this.last+1, keepExisting);\r
34721             this.grid.getView().focusRow(this.last);\r
34722                         return true;\r
34723         }\r
34724                 return false;\r
34725     },\r
34726 \r
34727     \r
34728     selectPrevious : function(keepExisting){\r
34729         if(this.hasPrevious()){\r
34730             this.selectRow(this.last-1, keepExisting);\r
34731             this.grid.getView().focusRow(this.last);\r
34732                         return true;\r
34733         }\r
34734                 return false;\r
34735     },\r
34736 \r
34737     \r
34738     hasNext : function(){\r
34739         return this.last !== false && (this.last+1) < this.grid.store.getCount();\r
34740     },\r
34741 \r
34742     \r
34743     hasPrevious : function(){\r
34744         return !!this.last;\r
34745     },\r
34746 \r
34747 \r
34748     \r
34749     getSelections : function(){\r
34750         return [].concat(this.selections.items);\r
34751     },\r
34752 \r
34753     \r
34754     getSelected : function(){\r
34755         return this.selections.itemAt(0);\r
34756     },\r
34757 \r
34758     \r
34759     each : function(fn, scope){\r
34760         var s = this.getSelections();\r
34761         for(var i = 0, len = s.length; i < len; i++){\r
34762             if(fn.call(scope || this, s[i], i) === false){\r
34763                 return false;\r
34764             }\r
34765         }\r
34766         return true;\r
34767     },\r
34768 \r
34769     \r
34770     clearSelections : function(fast){\r
34771         if(this.isLocked()) return;\r
34772         if(fast !== true){\r
34773             var ds = this.grid.store;\r
34774             var s = this.selections;\r
34775             s.each(function(r){\r
34776                 this.deselectRow(ds.indexOfId(r.id));\r
34777             }, this);\r
34778             s.clear();\r
34779         }else{\r
34780             this.selections.clear();\r
34781         }\r
34782         this.last = false;\r
34783     },\r
34784 \r
34785 \r
34786     \r
34787     selectAll : function(){\r
34788         if(this.isLocked()) return;\r
34789         this.selections.clear();\r
34790         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){\r
34791             this.selectRow(i, true);\r
34792         }\r
34793     },\r
34794 \r
34795     \r
34796     hasSelection : function(){\r
34797         return this.selections.length > 0;\r
34798     },\r
34799 \r
34800     \r
34801     isSelected : function(index){\r
34802         var r = typeof index == "number" ? this.grid.store.getAt(index) : index;\r
34803         return (r && this.selections.key(r.id) ? true : false);\r
34804     },\r
34805 \r
34806     \r
34807     isIdSelected : function(id){\r
34808         return (this.selections.key(id) ? true : false);\r
34809     },\r
34810 \r
34811     // private\r
34812     handleMouseDown : function(g, rowIndex, e){\r
34813         if(e.button !== 0 || this.isLocked()){\r
34814             return;\r
34815         };\r
34816         var view = this.grid.getView();\r
34817         if(e.shiftKey && !this.singleSelect && this.last !== false){\r
34818             var last = this.last;\r
34819             this.selectRange(last, rowIndex, e.ctrlKey);\r
34820             this.last = last; // reset the last\r
34821             view.focusRow(rowIndex);\r
34822         }else{\r
34823             var isSelected = this.isSelected(rowIndex);\r
34824             if(e.ctrlKey && isSelected){\r
34825                 this.deselectRow(rowIndex);\r
34826             }else if(!isSelected || this.getCount() > 1){\r
34827                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);\r
34828                 view.focusRow(rowIndex);\r
34829             }\r
34830         }\r
34831     },\r
34832 \r
34833     \r
34834     selectRows : function(rows, keepExisting){\r
34835         if(!keepExisting){\r
34836             this.clearSelections();\r
34837         }\r
34838         for(var i = 0, len = rows.length; i < len; i++){\r
34839             this.selectRow(rows[i], true);\r
34840         }\r
34841     },\r
34842 \r
34843     \r
34844     selectRange : function(startRow, endRow, keepExisting){\r
34845         if(this.isLocked()) return;\r
34846         if(!keepExisting){\r
34847             this.clearSelections();\r
34848         }\r
34849         if(startRow <= endRow){\r
34850             for(var i = startRow; i <= endRow; i++){\r
34851                 this.selectRow(i, true);\r
34852             }\r
34853         }else{\r
34854             for(var i = startRow; i >= endRow; i--){\r
34855                 this.selectRow(i, true);\r
34856             }\r
34857         }\r
34858     },\r
34859 \r
34860     \r
34861     deselectRange : function(startRow, endRow, preventViewNotify){\r
34862         if(this.isLocked()) return;\r
34863         for(var i = startRow; i <= endRow; i++){\r
34864             this.deselectRow(i, preventViewNotify);\r
34865         }\r
34866     },\r
34867 \r
34868     \r
34869     selectRow : function(index, keepExisting, preventViewNotify){\r
34870         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || this.isSelected(index)) return;\r
34871         var r = this.grid.store.getAt(index);\r
34872         if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){\r
34873             if(!keepExisting || this.singleSelect){\r
34874                 this.clearSelections();\r
34875             }\r
34876             this.selections.add(r);\r
34877             this.last = this.lastActive = index;\r
34878             if(!preventViewNotify){\r
34879                 this.grid.getView().onRowSelect(index);\r
34880             }\r
34881             this.fireEvent("rowselect", this, index, r);\r
34882             this.fireEvent("selectionchange", this);\r
34883         }\r
34884     },\r
34885 \r
34886     \r
34887     deselectRow : function(index, preventViewNotify){\r
34888         if(this.isLocked()) return;\r
34889         if(this.last == index){\r
34890             this.last = false;\r
34891         }\r
34892         if(this.lastActive == index){\r
34893             this.lastActive = false;\r
34894         }\r
34895         var r = this.grid.store.getAt(index);\r
34896         if(r){\r
34897             this.selections.remove(r);\r
34898             if(!preventViewNotify){\r
34899                 this.grid.getView().onRowDeselect(index);\r
34900             }\r
34901             this.fireEvent("rowdeselect", this, index, r);\r
34902             this.fireEvent("selectionchange", this);\r
34903         }\r
34904     },\r
34905 \r
34906     // private\r
34907     restoreLast : function(){\r
34908         if(this._last){\r
34909             this.last = this._last;\r
34910         }\r
34911     },\r
34912 \r
34913     // private\r
34914     acceptsNav : function(row, col, cm){\r
34915         return !cm.isHidden(col) && cm.isCellEditable(col, row);\r
34916     },\r
34917 \r
34918     // private\r
34919     onEditorKey : function(field, e){\r
34920         var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;\r
34921         var shift = e.shiftKey;\r
34922         if(k == e.TAB){\r
34923             e.stopEvent();\r
34924             ed.completeEdit();\r
34925             if(shift){\r
34926                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);\r
34927             }else{\r
34928                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);\r
34929             }\r
34930         }else if(k == e.ENTER){\r
34931             e.stopEvent();\r
34932             ed.completeEdit();\r
34933                         if(this.moveEditorOnEnter !== false){\r
34934                                 if(shift){\r
34935                                         newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);\r
34936                                 }else{\r
34937                                         newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);\r
34938                                 }\r
34939                         }\r
34940         }else if(k == e.ESC){\r
34941             ed.cancelEdit();\r
34942         }\r
34943         if(newCell){\r
34944             g.startEditing(newCell[0], newCell[1]);\r
34945         }\r
34946     }\r
34947 });\r
34948 \r
34949 Ext.grid.CellSelectionModel = function(config){\r
34950     Ext.apply(this, config);\r
34951 \r
34952     this.selection = null;\r
34953 \r
34954     this.addEvents(\r
34955         \r
34956             "beforecellselect",\r
34957         \r
34958             "cellselect",\r
34959         \r
34960             "selectionchange"\r
34961     );\r
34962 \r
34963     Ext.grid.CellSelectionModel.superclass.constructor.call(this);\r
34964 };\r
34965 \r
34966 Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel,  {\r
34967 \r
34968     \r
34969     initEvents : function(){\r
34970         this.grid.on("cellmousedown", this.handleMouseDown, this);\r
34971         this.grid.getGridEl().on(Ext.isIE || Ext.isSafari3 ? "keydown" : "keypress", this.handleKeyDown, this);\r
34972         var view = this.grid.view;\r
34973         view.on("refresh", this.onViewChange, this);\r
34974         view.on("rowupdated", this.onRowUpdated, this);\r
34975         view.on("beforerowremoved", this.clearSelections, this);\r
34976         view.on("beforerowsinserted", this.clearSelections, this);\r
34977         if(this.grid.isEditor){\r
34978             this.grid.on("beforeedit", this.beforeEdit,  this);\r
34979         }\r
34980     },\r
34981 \r
34982         //private\r
34983     beforeEdit : function(e){\r
34984         this.select(e.row, e.column, false, true, e.record);\r
34985     },\r
34986 \r
34987         //private\r
34988     onRowUpdated : function(v, index, r){\r
34989         if(this.selection && this.selection.record == r){\r
34990             v.onCellSelect(index, this.selection.cell[1]);\r
34991         }\r
34992     },\r
34993 \r
34994         //private\r
34995     onViewChange : function(){\r
34996         this.clearSelections(true);\r
34997     },\r
34998 \r
34999         \r
35000     getSelectedCell : function(){\r
35001         return this.selection ? this.selection.cell : null;\r
35002     },\r
35003 \r
35004     \r
35005     clearSelections : function(preventNotify){\r
35006         var s = this.selection;\r
35007         if(s){\r
35008             if(preventNotify !== true){\r
35009                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);\r
35010             }\r
35011             this.selection = null;\r
35012             this.fireEvent("selectionchange", this, null);\r
35013         }\r
35014     },\r
35015 \r
35016     \r
35017     hasSelection : function(){\r
35018         return this.selection ? true : false;\r
35019     },\r
35020 \r
35021     \r
35022     handleMouseDown : function(g, row, cell, e){\r
35023         if(e.button !== 0 || this.isLocked()){\r
35024             return;\r
35025         };\r
35026         this.select(row, cell);\r
35027     },\r
35028 \r
35029     \r
35030     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){\r
35031         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){\r
35032             this.clearSelections();\r
35033             r = r || this.grid.store.getAt(rowIndex);\r
35034             this.selection = {\r
35035                 record : r,\r
35036                 cell : [rowIndex, colIndex]\r
35037             };\r
35038             if(!preventViewNotify){\r
35039                 var v = this.grid.getView();\r
35040                 v.onCellSelect(rowIndex, colIndex);\r
35041                 if(preventFocus !== true){\r
35042                     v.focusCell(rowIndex, colIndex);\r
35043                 }\r
35044             }\r
35045             this.fireEvent("cellselect", this, rowIndex, colIndex);\r
35046             this.fireEvent("selectionchange", this, this.selection);\r
35047         }\r
35048     },\r
35049 \r
35050         //private\r
35051     isSelectable : function(rowIndex, colIndex, cm){\r
35052         return !cm.isHidden(colIndex);\r
35053     },\r
35054 \r
35055     \r
35056     handleKeyDown : function(e){\r
35057         if(!e.isNavKeyPress()){\r
35058             return;\r
35059         }\r
35060         var g = this.grid, s = this.selection;\r
35061         if(!s){\r
35062             e.stopEvent();\r
35063             var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);\r
35064             if(cell){\r
35065                 this.select(cell[0], cell[1]);\r
35066             }\r
35067             return;\r
35068         }\r
35069         var sm = this;\r
35070         var walk = function(row, col, step){\r
35071             return g.walkCells(row, col, step, sm.isSelectable,  sm);\r
35072         };\r
35073         var k = e.getKey(), r = s.cell[0], c = s.cell[1];\r
35074         var newCell;\r
35075 \r
35076         switch(k){\r
35077              case e.TAB:\r
35078                  if(e.shiftKey){\r
35079                      newCell = walk(r, c-1, -1);\r
35080                  }else{\r
35081                      newCell = walk(r, c+1, 1);\r
35082                  }\r
35083              break;\r
35084              case e.DOWN:\r
35085                  newCell = walk(r+1, c, 1);\r
35086              break;\r
35087              case e.UP:\r
35088                  newCell = walk(r-1, c, -1);\r
35089              break;\r
35090              case e.RIGHT:\r
35091                  newCell = walk(r, c+1, 1);\r
35092              break;\r
35093              case e.LEFT:\r
35094                  newCell = walk(r, c-1, -1);\r
35095              break;\r
35096              case e.ENTER:\r
35097                  if(g.isEditor && !g.editing){\r
35098                     g.startEditing(r, c);\r
35099                     e.stopEvent();\r
35100                     return;\r
35101                 }\r
35102              break;\r
35103         };\r
35104         if(newCell){\r
35105             this.select(newCell[0], newCell[1]);\r
35106             e.stopEvent();\r
35107         }\r
35108     },\r
35109 \r
35110     acceptsNav : function(row, col, cm){\r
35111         return !cm.isHidden(col) && cm.isCellEditable(col, row);\r
35112     },\r
35113 \r
35114     onEditorKey : function(field, e){\r
35115         var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;\r
35116         if(k == e.TAB){\r
35117             if(e.shiftKey){\r
35118                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);\r
35119             }else{\r
35120                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);\r
35121             }\r
35122             e.stopEvent();\r
35123         }else if(k == e.ENTER){\r
35124             ed.completeEdit();\r
35125             e.stopEvent();\r
35126         }else if(k == e.ESC){\r
35127                 e.stopEvent();\r
35128             ed.cancelEdit();\r
35129         }\r
35130         if(newCell){\r
35131             g.startEditing(newCell[0], newCell[1]);\r
35132         }\r
35133     }\r
35134 });\r
35135 \r
35136 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {\r
35137     \r
35138     clicksToEdit: 2,\r
35139 \r
35140     // private\r
35141     isEditor : true,\r
35142     // private\r
35143     detectEdit: false,\r
35144 \r
35145         \r
35146         autoEncode : false,\r
35147 \r
35148         \r
35149     // private\r
35150     trackMouseOver: false, // causes very odd FF errors\r
35151 \r
35152     // private\r
35153     initComponent : function(){\r
35154         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);\r
35155 \r
35156         if(!this.selModel){\r
35157             \r
35158             this.selModel = new Ext.grid.CellSelectionModel();\r
35159         }\r
35160 \r
35161         this.activeEditor = null;\r
35162 \r
35163             this.addEvents(\r
35164             \r
35165             "beforeedit",\r
35166             \r
35167             "afteredit",\r
35168             \r
35169             "validateedit"\r
35170         );\r
35171     },\r
35172 \r
35173     // private\r
35174     initEvents : function(){\r
35175         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);\r
35176 \r
35177         this.on("bodyscroll", this.stopEditing, this, [true]);\r
35178         this.on("columnresize", this.stopEditing, this, [true]);\r
35179 \r
35180         if(this.clicksToEdit == 1){\r
35181             this.on("cellclick", this.onCellDblClick, this);\r
35182         }else {\r
35183             if(this.clicksToEdit == 'auto' && this.view.mainBody){\r
35184                 this.view.mainBody.on("mousedown", this.onAutoEditClick, this);\r
35185             }\r
35186             this.on("celldblclick", this.onCellDblClick, this);\r
35187         }\r
35188     },\r
35189 \r
35190     // private\r
35191     onCellDblClick : function(g, row, col){\r
35192         this.startEditing(row, col);\r
35193     },\r
35194 \r
35195     // private\r
35196     onAutoEditClick : function(e, t){\r
35197         if(e.button !== 0){\r
35198             return;\r
35199         }\r
35200         var row = this.view.findRowIndex(t);\r
35201         var col = this.view.findCellIndex(t);\r
35202         if(row !== false && col !== false){\r
35203             this.stopEditing();\r
35204             if(this.selModel.getSelectedCell){ // cell sm\r
35205                 var sc = this.selModel.getSelectedCell();\r
35206                 if(sc && sc.cell[0] === row && sc.cell[1] === col){\r
35207                     this.startEditing(row, col);\r
35208                 }\r
35209             }else{\r
35210                 if(this.selModel.isSelected(row)){\r
35211                     this.startEditing(row, col);\r
35212                 }\r
35213             }\r
35214         }\r
35215     },\r
35216 \r
35217     // private\r
35218     onEditComplete : function(ed, value, startValue){\r
35219         this.editing = false;\r
35220         this.activeEditor = null;\r
35221         ed.un("specialkey", this.selModel.onEditorKey, this.selModel);\r
35222                 var r = ed.record;\r
35223         var field = this.colModel.getDataIndex(ed.col);\r
35224         value = this.postEditValue(value, startValue, r, field);\r
35225         if(String(value) !== String(startValue)){\r
35226             var e = {\r
35227                 grid: this,\r
35228                 record: r,\r
35229                 field: field,\r
35230                 originalValue: startValue,\r
35231                 value: value,\r
35232                 row: ed.row,\r
35233                 column: ed.col,\r
35234                 cancel:false\r
35235             };\r
35236             if(this.fireEvent("validateedit", e) !== false && !e.cancel){\r
35237                 r.set(field, e.value);\r
35238                 delete e.cancel;\r
35239                 this.fireEvent("afteredit", e);\r
35240             }\r
35241         }\r
35242         this.view.focusCell(ed.row, ed.col);\r
35243     },\r
35244 \r
35245     \r
35246     startEditing : function(row, col){\r
35247         this.stopEditing();\r
35248         if(this.colModel.isCellEditable(col, row)){\r
35249             this.view.ensureVisible(row, col, true);\r
35250             var r = this.store.getAt(row);\r
35251             var field = this.colModel.getDataIndex(col);\r
35252             var e = {\r
35253                 grid: this,\r
35254                 record: r,\r
35255                 field: field,\r
35256                 value: r.data[field],\r
35257                 row: row,\r
35258                 column: col,\r
35259                 cancel:false\r
35260             };\r
35261             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){\r
35262                 this.editing = true;\r
35263                 var ed = this.colModel.getCellEditor(col, row);\r
35264                 if(!ed.rendered){\r
35265                     ed.render(this.view.getEditorParent(ed));\r
35266                 }\r
35267                 (function(){ // complex but required for focus issues in safari, ie and opera\r
35268                     ed.row = row;\r
35269                     ed.col = col;\r
35270                     ed.record = r;\r
35271                     ed.on("complete", this.onEditComplete, this, {single: true});\r
35272                     ed.on("specialkey", this.selModel.onEditorKey, this.selModel);\r
35273                     \r
35274                     this.activeEditor = ed;\r
35275                     var v = this.preEditValue(r, field);\r
35276                     ed.startEdit(this.view.getCell(row, col).firstChild, v === undefined ? '' : v);\r
35277                 }).defer(50, this);\r
35278             }\r
35279         }\r
35280     },\r
35281 \r
35282     // private\r
35283         preEditValue : function(r, field){\r
35284         var value = r.data[field];\r
35285                 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlDecode(value) : value;\r
35286         },\r
35287 \r
35288     // private\r
35289         postEditValue : function(value, originalValue, r, field){\r
35290                 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;\r
35291         },\r
35292 \r
35293     \r
35294     stopEditing : function(cancel){\r
35295         if(this.activeEditor){\r
35296             this.activeEditor[cancel === true ? 'cancelEdit' : 'completeEdit']();\r
35297         }\r
35298         this.activeEditor = null;\r
35299     },\r
35300 \r
35301     // private\r
35302     onDestroy: function() {\r
35303         if(this.rendered){\r
35304             var cols = this.colModel.config;\r
35305             for(var i = 0, len = cols.length; i < len; i++){\r
35306                 var c = cols[i];\r
35307                 Ext.destroy(c.editor);\r
35308             }\r
35309         }\r
35310         Ext.grid.EditorGridPanel.superclass.onDestroy.call(this);\r
35311     }\r
35312 });\r
35313 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);\r
35314 // private\r
35315 // This is a support class used internally by the Grid components\r
35316 Ext.grid.GridEditor = function(field, config){\r
35317     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);\r
35318     field.monitorTab = false;\r
35319 };\r
35320 \r
35321 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {\r
35322     alignment: "tl-tl",\r
35323     autoSize: "width",\r
35324     hideEl : false,\r
35325     cls: "x-small-editor x-grid-editor",\r
35326     shim:false,\r
35327     shadow:false\r
35328 });\r
35329 \r
35330 Ext.grid.PropertyRecord = Ext.data.Record.create([\r
35331     {name:'name',type:'string'}, 'value'\r
35332 ]);\r
35333 \r
35334 \r
35335 Ext.grid.PropertyStore = function(grid, source){\r
35336     this.grid = grid;\r
35337     this.store = new Ext.data.Store({\r
35338         recordType : Ext.grid.PropertyRecord\r
35339     });\r
35340     this.store.on('update', this.onUpdate,  this);\r
35341     if(source){\r
35342         this.setSource(source);\r
35343     }\r
35344     Ext.grid.PropertyStore.superclass.constructor.call(this);\r
35345 };\r
35346 Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {\r
35347     // protected - should only be called by the grid.  Use grid.setSource instead.\r
35348     setSource : function(o){\r
35349         this.source = o;\r
35350         this.store.removeAll();\r
35351         var data = [];\r
35352         for(var k in o){\r
35353             if(this.isEditableValue(o[k])){\r
35354                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));\r
35355             }\r
35356         }\r
35357         this.store.loadRecords({records: data}, {}, true);\r
35358     },\r
35359 \r
35360     // private\r
35361     onUpdate : function(ds, record, type){\r
35362         if(type == Ext.data.Record.EDIT){\r
35363             var v = record.data['value'];\r
35364             var oldValue = record.modified['value'];\r
35365             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){\r
35366                 this.source[record.id] = v;\r
35367                 record.commit();\r
35368                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);\r
35369             }else{\r
35370                 record.reject();\r
35371             }\r
35372         }\r
35373     },\r
35374 \r
35375     // private\r
35376     getProperty : function(row){\r
35377        return this.store.getAt(row);\r
35378     },\r
35379 \r
35380     // private\r
35381     isEditableValue: function(val){\r
35382         if(Ext.isDate(val)){\r
35383             return true;\r
35384         }else if(typeof val == 'object' || typeof val == 'function'){\r
35385             return false;\r
35386         }\r
35387         return true;\r
35388     },\r
35389 \r
35390     // private\r
35391     setValue : function(prop, value){\r
35392         this.source[prop] = value;\r
35393         this.store.getById(prop).set('value', value);\r
35394     },\r
35395 \r
35396     // protected - should only be called by the grid.  Use grid.getSource instead.\r
35397     getSource : function(){\r
35398         return this.source;\r
35399     }\r
35400 });\r
35401 \r
35402 \r
35403 Ext.grid.PropertyColumnModel = function(grid, store){\r
35404     this.grid = grid;\r
35405     var g = Ext.grid;\r
35406     g.PropertyColumnModel.superclass.constructor.call(this, [\r
35407         {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},\r
35408         {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}\r
35409     ]);\r
35410     this.store = store;\r
35411     this.bselect = Ext.DomHelper.append(document.body, {\r
35412         tag: 'select', cls: 'x-grid-editor x-hide-display', children: [\r
35413             {tag: 'option', value: 'true', html: 'true'},\r
35414             {tag: 'option', value: 'false', html: 'false'}\r
35415         ]\r
35416     });\r
35417     var f = Ext.form;\r
35418 \r
35419     var bfield = new f.Field({\r
35420         el:this.bselect,\r
35421         bselect : this.bselect,\r
35422         autoShow: true,\r
35423         getValue : function(){\r
35424             return this.bselect.value == 'true';\r
35425         }\r
35426     });\r
35427     this.editors = {\r
35428         'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),\r
35429         'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),\r
35430         'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),\r
35431         'boolean' : new g.GridEditor(bfield)\r
35432     };\r
35433     this.renderCellDelegate = this.renderCell.createDelegate(this);\r
35434     this.renderPropDelegate = this.renderProp.createDelegate(this);\r
35435 };\r
35436 \r
35437 Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {\r
35438     // private - strings used for locale support\r
35439     nameText : 'Name',\r
35440     valueText : 'Value',\r
35441     dateFormat : 'm/j/Y',\r
35442 \r
35443     // private\r
35444     renderDate : function(dateVal){\r
35445         return dateVal.dateFormat(this.dateFormat);\r
35446     },\r
35447 \r
35448     // private\r
35449     renderBool : function(bVal){\r
35450         return bVal ? 'true' : 'false';\r
35451     },\r
35452 \r
35453     // private\r
35454     isCellEditable : function(colIndex, rowIndex){\r
35455         return colIndex == 1;\r
35456     },\r
35457 \r
35458     // private\r
35459     getRenderer : function(col){\r
35460         return col == 1 ?\r
35461             this.renderCellDelegate : this.renderPropDelegate;\r
35462     },\r
35463 \r
35464     // private\r
35465     renderProp : function(v){\r
35466         return this.getPropertyName(v);\r
35467     },\r
35468 \r
35469     // private\r
35470     renderCell : function(val){\r
35471         var rv = val;\r
35472         if(Ext.isDate(val)){\r
35473             rv = this.renderDate(val);\r
35474         }else if(typeof val == 'boolean'){\r
35475             rv = this.renderBool(val);\r
35476         }\r
35477         return Ext.util.Format.htmlEncode(rv);\r
35478     },\r
35479 \r
35480     // private\r
35481     getPropertyName : function(name){\r
35482         var pn = this.grid.propertyNames;\r
35483         return pn && pn[name] ? pn[name] : name;\r
35484     },\r
35485 \r
35486     // private\r
35487     getCellEditor : function(colIndex, rowIndex){\r
35488         var p = this.store.getProperty(rowIndex);\r
35489         var n = p.data['name'], val = p.data['value'];\r
35490         if(this.grid.customEditors[n]){\r
35491             return this.grid.customEditors[n];\r
35492         }\r
35493         if(Ext.isDate(val)){\r
35494             return this.editors['date'];\r
35495         }else if(typeof val == 'number'){\r
35496             return this.editors['number'];\r
35497         }else if(typeof val == 'boolean'){\r
35498             return this.editors['boolean'];\r
35499         }else{\r
35500             return this.editors['string'];\r
35501         }\r
35502     }\r
35503 });\r
35504 \r
35505 \r
35506 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {\r
35507     \r
35508     \r
35509     \r
35510 \r
35511     // private config overrides\r
35512     enableColumnMove:false,\r
35513     stripeRows:false,\r
35514     trackMouseOver: false,\r
35515     clicksToEdit:1,\r
35516     enableHdMenu : false,\r
35517     viewConfig : {\r
35518         forceFit:true\r
35519     },\r
35520 \r
35521     // private\r
35522     initComponent : function(){\r
35523         this.customEditors = this.customEditors || {};\r
35524         this.lastEditRow = null;\r
35525         var store = new Ext.grid.PropertyStore(this);\r
35526         this.propStore = store;\r
35527         var cm = new Ext.grid.PropertyColumnModel(this, store);\r
35528         store.store.sort('name', 'ASC');\r
35529         this.addEvents(\r
35530             \r
35531             'beforepropertychange',\r
35532             \r
35533             'propertychange'\r
35534         );\r
35535         this.cm = cm;\r
35536         this.ds = store.store;\r
35537         Ext.grid.PropertyGrid.superclass.initComponent.call(this);\r
35538 \r
35539         this.selModel.on('beforecellselect', function(sm, rowIndex, colIndex){\r
35540             if(colIndex === 0){\r
35541                 this.startEditing.defer(200, this, [rowIndex, 1]);\r
35542                 return false;\r
35543             }\r
35544         }, this);\r
35545     },\r
35546 \r
35547     // private\r
35548     onRender : function(){\r
35549         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);\r
35550 \r
35551         this.getGridEl().addClass('x-props-grid');\r
35552     },\r
35553 \r
35554     // private\r
35555     afterRender: function(){\r
35556         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);\r
35557         if(this.source){\r
35558             this.setSource(this.source);\r
35559         }\r
35560     },\r
35561 \r
35562     \r
35563     setSource : function(source){\r
35564         this.propStore.setSource(source);\r
35565     },\r
35566 \r
35567     \r
35568     getSource : function(){\r
35569         return this.propStore.getSource();\r
35570     }\r
35571 });\r
35572 Ext.reg("propertygrid", Ext.grid.PropertyGrid);\r
35573 \r
35574 \r
35575 Ext.grid.RowNumberer = function(config){\r
35576     Ext.apply(this, config);\r
35577     if(this.rowspan){\r
35578         this.renderer = this.renderer.createDelegate(this);\r
35579     }\r
35580 };\r
35581 \r
35582 Ext.grid.RowNumberer.prototype = {\r
35583     \r
35584     header: "",\r
35585     \r
35586     width: 23,\r
35587     \r
35588     sortable: false,\r
35589 \r
35590     // private\r
35591     fixed:true,\r
35592     menuDisabled:true,\r
35593     dataIndex: '',\r
35594     id: 'numberer',\r
35595     rowspan: undefined,\r
35596 \r
35597     // private\r
35598     renderer : function(v, p, record, rowIndex){\r
35599         if(this.rowspan){\r
35600             p.cellAttr = 'rowspan="'+this.rowspan+'"';\r
35601         }\r
35602         return rowIndex+1;\r
35603     }\r
35604 };\r
35605 \r
35606 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {\r
35607     \r
35608     header: '<div class="x-grid3-hd-checker">&#160;</div>',\r
35609     \r
35610     width: 20,\r
35611     \r
35612     sortable: false,\r
35613 \r
35614     // private\r
35615     menuDisabled:true,\r
35616     fixed:true,\r
35617     dataIndex: '',\r
35618     id: 'checker',\r
35619 \r
35620     // private\r
35621     initEvents : function(){\r
35622         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);\r
35623         this.grid.on('render', function(){\r
35624             var view = this.grid.getView();\r
35625             view.mainBody.on('mousedown', this.onMouseDown, this);\r
35626             Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);\r
35627 \r
35628         }, this);\r
35629     },\r
35630 \r
35631     // private\r
35632     onMouseDown : function(e, t){\r
35633         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ // Only fire if left-click\r
35634             e.stopEvent();\r
35635             var row = e.getTarget('.x-grid3-row');\r
35636             if(row){\r
35637                 var index = row.rowIndex;\r
35638                 if(this.isSelected(index)){\r
35639                     this.deselectRow(index);\r
35640                 }else{\r
35641                     this.selectRow(index, true);\r
35642                 }\r
35643             }\r
35644         }\r
35645     },\r
35646 \r
35647     // private\r
35648     onHdMouseDown : function(e, t){\r
35649         if(t.className == 'x-grid3-hd-checker'){\r
35650             e.stopEvent();\r
35651             var hd = Ext.fly(t.parentNode);\r
35652             var isChecked = hd.hasClass('x-grid3-hd-checker-on');\r
35653             if(isChecked){\r
35654                 hd.removeClass('x-grid3-hd-checker-on');\r
35655                 this.clearSelections();\r
35656             }else{\r
35657                 hd.addClass('x-grid3-hd-checker-on');\r
35658                 this.selectAll();\r
35659             }\r
35660         }\r
35661     },\r
35662 \r
35663     // private\r
35664     renderer : function(v, p, record){\r
35665         return '<div class="x-grid3-row-checker">&#160;</div>';\r
35666     }\r
35667 });\r
35668 \r
35669 Ext.LoadMask = function(el, config){\r
35670     this.el = Ext.get(el);\r
35671     Ext.apply(this, config);\r
35672     if(this.store){\r
35673         this.store.on('beforeload', this.onBeforeLoad, this);\r
35674         this.store.on('load', this.onLoad, this);\r
35675         this.store.on('loadexception', this.onLoad, this);\r
35676         this.removeMask = Ext.value(this.removeMask, false);\r
35677     }else{\r
35678         var um = this.el.getUpdater();\r
35679         um.showLoadIndicator = false; // disable the default indicator\r
35680         um.on('beforeupdate', this.onBeforeLoad, this);\r
35681         um.on('update', this.onLoad, this);\r
35682         um.on('failure', this.onLoad, this);\r
35683         this.removeMask = Ext.value(this.removeMask, true);\r
35684     }\r
35685 };\r
35686 \r
35687 Ext.LoadMask.prototype = {\r
35688     \r
35689     \r
35690     \r
35691     msg : 'Loading...',\r
35692     \r
35693     msgCls : 'x-mask-loading',\r
35694 \r
35695     \r
35696     disabled: false,\r
35697 \r
35698     \r
35699     disable : function(){\r
35700        this.disabled = true;\r
35701     },\r
35702 \r
35703     \r
35704     enable : function(){\r
35705         this.disabled = false;\r
35706     },\r
35707 \r
35708     // private\r
35709     onLoad : function(){\r
35710         this.el.unmask(this.removeMask);\r
35711     },\r
35712 \r
35713     // private\r
35714     onBeforeLoad : function(){\r
35715         if(!this.disabled){\r
35716             this.el.mask(this.msg, this.msgCls);\r
35717         }\r
35718     },\r
35719 \r
35720     \r
35721     show: function(){\r
35722         this.onBeforeLoad();\r
35723     },\r
35724 \r
35725     \r
35726     hide: function(){\r
35727         this.onLoad();    \r
35728     },\r
35729 \r
35730     // private\r
35731     destroy : function(){\r
35732         if(this.store){\r
35733             this.store.un('beforeload', this.onBeforeLoad, this);\r
35734             this.store.un('load', this.onLoad, this);\r
35735             this.store.un('loadexception', this.onLoad, this);\r
35736         }else{\r
35737             var um = this.el.getUpdater();\r
35738             um.un('beforeupdate', this.onBeforeLoad, this);\r
35739             um.un('update', this.onLoad, this);\r
35740             um.un('failure', this.onLoad, this);\r
35741         }\r
35742     }\r
35743 };\r
35744 \r
35745 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
35746    \r
35747     baseCls : 'x-progress',\r
35748     \r
35749     \r
35750     animate : false,\r
35751 \r
35752     // private\r
35753     waitTimer : null,\r
35754 \r
35755     // private\r
35756     initComponent : function(){\r
35757         Ext.ProgressBar.superclass.initComponent.call(this);\r
35758         this.addEvents(\r
35759             \r
35760             "update"\r
35761         );\r
35762     },\r
35763 \r
35764     // private\r
35765     onRender : function(ct, position){\r
35766         Ext.ProgressBar.superclass.onRender.call(this, ct, position);\r
35767 \r
35768         var tpl = new Ext.Template(\r
35769             '<div class="{cls}-wrap">',\r
35770                 '<div class="{cls}-inner">',\r
35771                     '<div class="{cls}-bar">',\r
35772                         '<div class="{cls}-text">',\r
35773                             '<div>&#160;</div>',\r
35774                         '</div>',\r
35775                     '</div>',\r
35776                     '<div class="{cls}-text {cls}-text-back">',\r
35777                         '<div>&#160;</div>',\r
35778                     '</div>',\r
35779                 '</div>',\r
35780             '</div>'\r
35781         );\r
35782 \r
35783         if(position){\r
35784             this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);\r
35785         }else{\r
35786             this.el = tpl.append(ct, {cls: this.baseCls}, true);\r
35787         }\r
35788         if(this.id){\r
35789             this.el.dom.id = this.id;\r
35790         }\r
35791         var inner = this.el.dom.firstChild;\r
35792         this.progressBar = Ext.get(inner.firstChild);\r
35793 \r
35794         if(this.textEl){\r
35795             //use an external text el\r
35796             this.textEl = Ext.get(this.textEl);\r
35797             delete this.textTopEl;\r
35798         }else{\r
35799             //setup our internal layered text els\r
35800             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
35801             var textBackEl = Ext.get(inner.childNodes[1]);\r
35802             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
35803             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
35804             this.textEl.setWidth(inner.offsetWidth);\r
35805         }\r
35806         this.progressBar.setHeight(inner.offsetHeight);\r
35807     },\r
35808     \r
35809     // private\r
35810         afterRender : function(){\r
35811                 Ext.ProgressBar.superclass.afterRender.call(this);\r
35812                 if(this.value){\r
35813                         this.updateProgress(this.value, this.text);\r
35814                 }else{\r
35815                         this.updateText(this.text);\r
35816                 }\r
35817         },\r
35818 \r
35819     \r
35820     updateProgress : function(value, text, animate){\r
35821         this.value = value || 0;\r
35822         if(text){\r
35823             this.updateText(text);\r
35824         }\r
35825         if(this.rendered){\r
35826                 var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
35827                 this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
35828                 if(this.textTopEl){\r
35829                     //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
35830                     this.textTopEl.removeClass('x-hidden').setWidth(w);\r
35831                 }\r
35832         }\r
35833         this.fireEvent('update', this, value, text);\r
35834         return this;\r
35835     },\r
35836 \r
35837     \r
35838     wait : function(o){\r
35839         if(!this.waitTimer){\r
35840             var scope = this;\r
35841             o = o || {};\r
35842             this.updateText(o.text);\r
35843             this.waitTimer = Ext.TaskMgr.start({\r
35844                 run: function(i){\r
35845                     var inc = o.increment || 10;\r
35846                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*.01, null, o.animate);\r
35847                 },\r
35848                 interval: o.interval || 1000,\r
35849                 duration: o.duration,\r
35850                 onStop: function(){\r
35851                     if(o.fn){\r
35852                         o.fn.apply(o.scope || this);\r
35853                     }\r
35854                     this.reset();\r
35855                 },\r
35856                 scope: scope\r
35857             });\r
35858         }\r
35859         return this;\r
35860     },\r
35861 \r
35862     \r
35863     isWaiting : function(){\r
35864         return this.waitTimer != null;\r
35865     },\r
35866 \r
35867     \r
35868     updateText : function(text){\r
35869         this.text = text || '&#160;';\r
35870         if(this.rendered){\r
35871             this.textEl.update(this.text);\r
35872         }\r
35873         return this;\r
35874     },\r
35875     \r
35876     \r
35877     syncProgressBar : function(){\r
35878         if(this.value){\r
35879             this.updateProgress(this.value, this.text);\r
35880         }\r
35881         return this;\r
35882     },\r
35883 \r
35884     \r
35885     setSize : function(w, h){\r
35886         Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
35887         if(this.textTopEl){\r
35888             var inner = this.el.dom.firstChild;\r
35889             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
35890         }\r
35891         this.syncProgressBar();\r
35892         return this;\r
35893     },\r
35894 \r
35895     \r
35896     reset : function(hide){\r
35897         this.updateProgress(0);\r
35898         if(this.textTopEl){\r
35899             this.textTopEl.addClass('x-hidden');\r
35900         }\r
35901         if(this.waitTimer){\r
35902             this.waitTimer.onStop = null; //prevent recursion\r
35903             Ext.TaskMgr.stop(this.waitTimer);\r
35904             this.waitTimer = null;\r
35905         }\r
35906         if(hide === true){\r
35907             this.hide();\r
35908         }\r
35909         return this;\r
35910     }\r
35911 });\r
35912 Ext.reg('progress', Ext.ProgressBar);\r
35913 \r
35914 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
35915         \r
35916         \r
35917     vertical: false,\r
35918         \r
35919     minValue: 0,\r
35920                 \r
35921     maxValue: 100,\r
35922         \r
35923     keyIncrement: 1,\r
35924         \r
35925     increment: 0,\r
35926         // private\r
35927     clickRange: [5,15],\r
35928         \r
35929     clickToChange : true,\r
35930         \r
35931     animate: true,\r
35932 \r
35933     \r
35934     dragging: false,\r
35935 \r
35936     // private override\r
35937     initComponent : function(){\r
35938         if(this.value === undefined){\r
35939             this.value = this.minValue;\r
35940         }\r
35941         Ext.Slider.superclass.initComponent.call(this);\r
35942         this.keyIncrement = Math.max(this.increment, this.keyIncrement); \r
35943         this.addEvents(\r
35944                         \r
35945                         'beforechange', \r
35946                         \r
35947                         'change',\r
35948                         \r
35949                         'changecomplete',\r
35950                         \r
35951                         'dragstart', \r
35952                         \r
35953                         'drag', \r
35954                         \r
35955                         'dragend'\r
35956                 );\r
35957 \r
35958         if(this.vertical){\r
35959             Ext.apply(this, Ext.Slider.Vertical);\r
35960         }\r
35961     },\r
35962 \r
35963         // private override\r
35964     onRender : function(){\r
35965         this.autoEl = {\r
35966             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
35967             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}\r
35968         };\r
35969         Ext.Slider.superclass.onRender.apply(this, arguments);\r
35970         this.endEl = this.el.first();\r
35971         this.innerEl = this.endEl.first();\r
35972         this.thumb = this.innerEl.first();\r
35973         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
35974         this.focusEl = this.thumb.next();\r
35975         this.initEvents();\r
35976     },\r
35977 \r
35978         // private override\r
35979     initEvents : function(){\r
35980         this.thumb.addClassOnOver('x-slider-thumb-over');\r
35981         this.mon(this.el, 'mousedown', this.onMouseDown, this);\r
35982         this.mon(this.el, 'keydown', this.onKeyDown, this);\r
35983 \r
35984         this.focusEl.swallowEvent("click", true);\r
35985 \r
35986         this.tracker = new Ext.dd.DragTracker({\r
35987             onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
35988             onStart: this.onDragStart.createDelegate(this),\r
35989             onDrag: this.onDrag.createDelegate(this),\r
35990             onEnd: this.onDragEnd.createDelegate(this),\r
35991             tolerance: 3,\r
35992             autoStart: 300\r
35993         });\r
35994         this.tracker.initEl(this.thumb);\r
35995         this.on('beforedestroy', this.tracker.destroy, this.tracker);\r
35996     },\r
35997 \r
35998         // private override\r
35999     onMouseDown : function(e){\r
36000         if(this.disabled) {return;}\r
36001         if(this.clickToChange && e.target != this.thumb.dom){\r
36002             var local = this.innerEl.translatePoints(e.getXY());\r
36003             this.onClickChange(local);\r
36004         }\r
36005         this.focus();\r
36006     },\r
36007 \r
36008         // private\r
36009     onClickChange : function(local){\r
36010         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
36011             this.setValue(Math.round(this.reverseValue(local.left)), undefined, true);\r
36012         }\r
36013     },\r
36014         \r
36015         // private\r
36016     onKeyDown : function(e){\r
36017         if(this.disabled){e.preventDefault();return;}\r
36018         var k = e.getKey();\r
36019         switch(k){\r
36020             case e.UP:\r
36021             case e.RIGHT:\r
36022                 e.stopEvent();\r
36023                 if(e.ctrlKey){\r
36024                     this.setValue(this.maxValue, undefined, true);\r
36025                 }else{\r
36026                     this.setValue(this.value+this.keyIncrement, undefined, true);\r
36027                 }\r
36028             break;\r
36029             case e.DOWN:\r
36030             case e.LEFT:\r
36031                 e.stopEvent();\r
36032                 if(e.ctrlKey){\r
36033                     this.setValue(this.minValue, undefined, true);\r
36034                 }else{\r
36035                     this.setValue(this.value-this.keyIncrement, undefined, true);\r
36036                 }\r
36037             break;\r
36038             default:\r
36039                 e.preventDefault();\r
36040         }\r
36041     },\r
36042         \r
36043         // private\r
36044     doSnap : function(value){\r
36045         if(!this.increment || this.increment == 1 || !value) {\r
36046             return value;\r
36047         }\r
36048         var newValue = value, inc = this.increment;\r
36049         var m = value % inc;\r
36050         if(m > 0){\r
36051             if(m > (inc/2)){\r
36052                 newValue = value + (inc-m);\r
36053             }else{\r
36054                 newValue = value - m;\r
36055             }\r
36056         }\r
36057         return newValue.constrain(this.minValue,  this.maxValue);\r
36058     },\r
36059         \r
36060         // private\r
36061     afterRender : function(){\r
36062         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
36063         if(this.value !== undefined){\r
36064             var v = this.normalizeValue(this.value);\r
36065             if(v !== this.value){\r
36066                 delete this.value;\r
36067                 this.setValue(v, false);\r
36068             }else{\r
36069                 this.moveThumb(this.translateValue(v), false);\r
36070             }\r
36071         }\r
36072     },\r
36073 \r
36074         // private\r
36075     getRatio : function(){\r
36076         var w = this.innerEl.getWidth();\r
36077         var v = this.maxValue - this.minValue;\r
36078         return v == 0 ? w : (w/v);\r
36079     },\r
36080 \r
36081         // private\r
36082     normalizeValue : function(v){\r
36083        if(typeof v != 'number'){\r
36084             v = parseInt(v);\r
36085         }\r
36086         v = Math.round(v);\r
36087         v = this.doSnap(v);\r
36088         v = v.constrain(this.minValue, this.maxValue);\r
36089         return v;\r
36090     },\r
36091 \r
36092         \r
36093     setValue : function(v, animate, changeComplete){\r
36094         v = this.normalizeValue(v);\r
36095         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
36096             this.value = v;\r
36097             this.moveThumb(this.translateValue(v), animate !== false);\r
36098             this.fireEvent('change', this, v);\r
36099             if(changeComplete){\r
36100                 this.fireEvent('changecomplete', this, v);\r
36101             }\r
36102         }\r
36103     },\r
36104 \r
36105         // private\r
36106     translateValue : function(v){\r
36107         var ratio = this.getRatio();\r
36108         return (v * ratio)-(this.minValue * ratio)-this.halfThumb;\r
36109     },\r
36110 \r
36111         reverseValue : function(pos){\r
36112         var ratio = this.getRatio();\r
36113         return (pos+this.halfThumb+(this.minValue * ratio))/ratio;\r
36114     },\r
36115 \r
36116         // private\r
36117     moveThumb: function(v, animate){\r
36118         if(!animate || this.animate === false){\r
36119             this.thumb.setLeft(v);\r
36120         }else{\r
36121             this.thumb.shift({left: v, stopFx: true, duration:.35});\r
36122         }\r
36123     },\r
36124 \r
36125         // private\r
36126     focus : function(){\r
36127         this.focusEl.focus(10);\r
36128     },\r
36129 \r
36130         // private\r
36131     onBeforeDragStart : function(e){\r
36132         return !this.disabled;\r
36133     },\r
36134 \r
36135         // private\r
36136     onDragStart: function(e){\r
36137         this.thumb.addClass('x-slider-thumb-drag');\r
36138         this.dragging = true;\r
36139         this.dragStartValue = this.value;\r
36140         this.fireEvent('dragstart', this, e);\r
36141     },\r
36142 \r
36143         // private\r
36144     onDrag: function(e){\r
36145         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
36146         this.setValue(Math.round(this.reverseValue(pos.left)), false);\r
36147         this.fireEvent('drag', this, e);\r
36148     },\r
36149         \r
36150         // private\r
36151     onDragEnd: function(e){\r
36152         this.thumb.removeClass('x-slider-thumb-drag');\r
36153         this.dragging = false;\r
36154         this.fireEvent('dragend', this, e);\r
36155         if(this.dragStartValue != this.value){\r
36156             this.fireEvent('changecomplete', this, this.value);\r
36157         }\r
36158     },\r
36159     \r
36160     //private\r
36161     onDisable: function(){\r
36162         Ext.Slider.superclass.onDisable.call(this);\r
36163         this.thumb.addClass(this.disabledClass);\r
36164         if(Ext.isIE){\r
36165             //IE breaks when using overflow visible and opacity other than 1.\r
36166             //Create a place holder for the thumb and display it.\r
36167             var xy = this.thumb.getXY();\r
36168             this.thumb.hide();\r
36169             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
36170             if (!this.thumbHolder){\r
36171                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    \r
36172             }\r
36173             this.thumbHolder.show().setXY(xy);\r
36174         }\r
36175     },\r
36176     \r
36177     //private\r
36178     onEnable: function(){\r
36179         Ext.Slider.superclass.onEnable.call(this);\r
36180         this.thumb.removeClass(this.disabledClass);\r
36181         if(Ext.isIE){\r
36182             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
36183             if (this.thumbHolder){\r
36184                 this.thumbHolder.hide();\r
36185             }\r
36186             this.thumb.show();\r
36187             this.syncThumb();\r
36188         }\r
36189     },\r
36190 \r
36191     // private\r
36192     onResize : function(w, h){\r
36193         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
36194         this.syncThumb();\r
36195     },\r
36196     \r
36197     \r
36198     syncThumb : function(){\r
36199         if(this.rendered){\r
36200             this.moveThumb(this.translateValue(this.value));\r
36201         }\r
36202     },\r
36203         \r
36204         \r
36205     getValue : function(){\r
36206         return this.value;\r
36207     }\r
36208 });\r
36209 Ext.reg('slider', Ext.Slider);\r
36210 \r
36211 // private class to support vertical sliders\r
36212 Ext.Slider.Vertical = {\r
36213     onResize : function(w, h){\r
36214         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
36215         this.syncThumb();\r
36216     },\r
36217 \r
36218     getRatio : function(){\r
36219         var h = this.innerEl.getHeight();\r
36220         var v = this.maxValue - this.minValue;\r
36221         return h/v;\r
36222     },\r
36223 \r
36224     moveThumb: function(v, animate){\r
36225         if(!animate || this.animate === false){\r
36226             this.thumb.setBottom(v);\r
36227         }else{\r
36228             this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
36229         }\r
36230     },\r
36231 \r
36232     onDrag: function(e){\r
36233         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
36234         var bottom = this.innerEl.getHeight()-pos.top;\r
36235         this.setValue(this.minValue + Math.round(bottom/this.getRatio()), false);\r
36236         this.fireEvent('drag', this, e);\r
36237     },\r
36238 \r
36239     onClickChange : function(local){\r
36240         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
36241             var bottom = this.innerEl.getHeight()-local.top;\r
36242             this.setValue(this.minValue + Math.round(bottom/this.getRatio()), undefined, true);\r
36243         }\r
36244     }\r
36245 };\r
36246 \r
36247 Ext.StatusBar = Ext.extend(Ext.Toolbar, {\r
36248     \r
36249     \r
36250     \r
36251     \r
36252     \r
36253     \r
36254     \r
36255     cls : 'x-statusbar',\r
36256     \r
36257     busyIconCls : 'x-status-busy',\r
36258     \r
36259     busyText : 'Loading...',\r
36260     \r
36261     autoClear : 5000,\r
36262     \r
36263     // private\r
36264     activeThreadId : 0,\r
36265     \r
36266     // private\r
36267     initComponent : function(){\r
36268         if(this.statusAlign=='right'){\r
36269             this.cls += ' x-status-right';\r
36270         }\r
36271         Ext.StatusBar.superclass.initComponent.call(this);\r
36272     },\r
36273     \r
36274     // private\r
36275     afterRender : function(){\r
36276         Ext.StatusBar.superclass.afterRender.call(this);\r
36277         \r
36278         var right = this.statusAlign=='right',\r
36279             td = Ext.get(this.nextBlock());\r
36280         \r
36281         if(right){\r
36282             this.tr.appendChild(td.dom);\r
36283         }else{\r
36284             td.insertBefore(this.tr.firstChild);\r
36285         }\r
36286         \r
36287         this.statusEl = td.createChild({\r
36288             cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''),\r
36289             html: this.text || this.defaultText || ''\r
36290         });\r
36291         this.statusEl.unselectable();\r
36292         \r
36293         this.spacerEl = td.insertSibling({\r
36294             tag: 'td',\r
36295             style: 'width:100%',\r
36296             cn: [{cls:'ytb-spacer'}]\r
36297         }, right ? 'before' : 'after');\r
36298     },\r
36299 \r
36300     \r
36301     setStatus : function(o){\r
36302         o = o || {};\r
36303         \r
36304         if(typeof o == 'string'){\r
36305             o = {text:o};\r
36306         }\r
36307         if(o.text !== undefined){\r
36308             this.setText(o.text);\r
36309         }\r
36310         if(o.iconCls !== undefined){\r
36311             this.setIcon(o.iconCls);\r
36312         }\r
36313         \r
36314         if(o.clear){\r
36315             var c = o.clear,\r
36316                 wait = this.autoClear,\r
36317                 defaults = {useDefaults: true, anim: true};\r
36318             \r
36319             if(typeof c == 'object'){\r
36320                 c = Ext.applyIf(c, defaults);\r
36321                 if(c.wait){\r
36322                     wait = c.wait;\r
36323                 }\r
36324             }else if(typeof c == 'number'){\r
36325                 wait = c;\r
36326                 c = defaults;\r
36327             }else if(typeof c == 'boolean'){\r
36328                 c = defaults;\r
36329             }\r
36330             \r
36331             c.threadId = this.activeThreadId;\r
36332             this.clearStatus.defer(wait, this, [c]);\r
36333         }\r
36334         return this;\r
36335     },\r
36336      \r
36337     \r
36338     clearStatus : function(o){\r
36339         o = o || {};\r
36340         \r
36341         if(o.threadId && o.threadId !== this.activeThreadId){\r
36342             // this means the current call was made internally, but a newer\r
36343             // thread has set a message since this call was deferred.  Since\r
36344             // we don't want to overwrite a newer message just ignore.\r
36345             return this;\r
36346         }\r
36347         \r
36348         var text = o.useDefaults ? this.defaultText : '',\r
36349             iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';\r
36350             \r
36351         if(o.anim){\r
36352             this.statusEl.fadeOut({\r
36353                 remove: false,\r
36354                 useDisplay: true,\r
36355                 scope: this,\r
36356                 callback: function(){\r
36357                     this.setStatus({\r
36358                             text: text, \r
36359                             iconCls: iconCls\r
36360                         });\r
36361                     this.statusEl.show();\r
36362                 }\r
36363             });\r
36364         }else{\r
36365             // hide/show the el to avoid jumpy text or icon\r
36366             this.statusEl.hide();\r
36367                 this.setStatus({\r
36368                     text: text,\r
36369                     iconCls: iconCls\r
36370                 });\r
36371             this.statusEl.show();\r
36372         }\r
36373         return this;\r
36374     },\r
36375     \r
36376     \r
36377     setText : function(text){\r
36378         this.activeThreadId++;\r
36379         this.text = text || '';\r
36380         if(this.rendered){\r
36381             this.statusEl.update(this.text);\r
36382         }\r
36383         return this;\r
36384     },\r
36385     \r
36386     \r
36387     getText : function(){\r
36388         return this.text;\r
36389     },\r
36390 \r
36391     \r
36392     setIcon : function(cls){\r
36393         this.activeThreadId++;\r
36394         cls = cls || '';\r
36395         \r
36396         if(this.rendered){\r
36397                 if(this.currIconCls){\r
36398                     this.statusEl.removeClass(this.currIconCls);\r
36399                     this.currIconCls = null;\r
36400                 }\r
36401                 if(cls.length > 0){\r
36402                     this.statusEl.addClass(cls);\r
36403                     this.currIconCls = cls;\r
36404                 }\r
36405         }else{\r
36406             this.currIconCls = cls;\r
36407         }\r
36408         return this;\r
36409     },\r
36410     \r
36411     \r
36412     showBusy : function(o){\r
36413         if(typeof o == 'string'){\r
36414             o = {text:o};\r
36415         }\r
36416         o = Ext.applyIf(o || {}, {\r
36417             text: this.busyText,\r
36418             iconCls: this.busyIconCls\r
36419         });\r
36420         return this.setStatus(o);\r
36421     }\r
36422 });\r
36423 Ext.reg('statusbar', Ext.StatusBar);\r
36424 \r
36425 \r
36426 Ext.History = (function () {\r
36427     var iframe, hiddenField;\r
36428     var ready = false;\r
36429     var currentToken;\r
36430 \r
36431     function getHash() {\r
36432         var href = top.location.href, i = href.indexOf("#");\r
36433         return i >= 0 ? href.substr(i + 1) : null;\r
36434     }\r
36435 \r
36436     function doSave() {\r
36437         hiddenField.value = currentToken;\r
36438     }\r
36439 \r
36440     function handleStateChange(token) {\r
36441         currentToken = token;\r
36442         Ext.History.fireEvent('change', token);\r
36443     }\r
36444 \r
36445     function updateIFrame (token) {\r
36446         var html = ['<html><body><div id="state">',token,'</div></body></html>'].join('');\r
36447         try {\r
36448             var doc = iframe.contentWindow.document;\r
36449             doc.open();\r
36450             doc.write(html);\r
36451             doc.close();\r
36452             return true;\r
36453         } catch (e) {\r
36454             return false;\r
36455         }\r
36456     }\r
36457 \r
36458     function checkIFrame() {\r
36459         if (!iframe.contentWindow || !iframe.contentWindow.document) {\r
36460             setTimeout(checkIFrame, 10);\r
36461             return;\r
36462         }\r
36463 \r
36464         var doc = iframe.contentWindow.document;\r
36465         var elem = doc.getElementById("state");\r
36466         var token = elem ? elem.innerText : null;\r
36467 \r
36468         var hash = getHash();\r
36469 \r
36470         setInterval(function () {\r
36471 \r
36472             doc = iframe.contentWindow.document;\r
36473             elem = doc.getElementById("state");\r
36474 \r
36475             var newtoken = elem ? elem.innerText : null;\r
36476 \r
36477             var newHash = getHash();\r
36478 \r
36479             if (newtoken !== token) {\r
36480                 token = newtoken;\r
36481                 handleStateChange(token);\r
36482                 top.location.hash = token;\r
36483                 hash = token;\r
36484                 doSave();\r
36485             } else if (newHash !== hash) {\r
36486                 hash = newHash;\r
36487                 updateIFrame(newHash);\r
36488             }\r
36489 \r
36490         }, 50);\r
36491 \r
36492         ready = true;\r
36493 \r
36494         Ext.History.fireEvent('ready', Ext.History);\r
36495     }\r
36496 \r
36497     function startUp() {\r
36498         currentToken = hiddenField.value ? hiddenField.value : getHash();\r
36499         \r
36500         if (Ext.isIE) {\r
36501             checkIFrame();\r
36502         } else {\r
36503             var hash = getHash();\r
36504             setInterval(function () {\r
36505                 var newHash = getHash();\r
36506                 if (newHash !== hash) {\r
36507                     hash = newHash;\r
36508                     handleStateChange(hash);\r
36509                     doSave();\r
36510                 }\r
36511             }, 50);\r
36512             ready = true;\r
36513             Ext.History.fireEvent('ready', Ext.History);\r
36514         }\r
36515     }\r
36516 \r
36517     return {\r
36518         \r
36519         fieldId: 'x-history-field',\r
36520         \r
36521         iframeId: 'x-history-frame',\r
36522         \r
36523         events:{},\r
36524 \r
36525         \r
36526         init: function (onReady, scope) {\r
36527             if(ready) {\r
36528                 Ext.callback(onReady, scope, [this]);\r
36529                 return;\r
36530             }\r
36531             if(!Ext.isReady){\r
36532                 Ext.onReady(function(){\r
36533                     Ext.History.init(onReady, scope);\r
36534                 });\r
36535                 return;\r
36536             }\r
36537             hiddenField = Ext.getDom(Ext.History.fieldId);\r
36538                         if (Ext.isIE) {\r
36539                 iframe = Ext.getDom(Ext.History.iframeId);\r
36540             }\r
36541             this.addEvents('ready', 'change');\r
36542             if(onReady){\r
36543                 this.on('ready', onReady, scope, {single:true});\r
36544             }\r
36545             startUp();\r
36546         },\r
36547 \r
36548         \r
36549         add: function (token, preventDup) {\r
36550             if(preventDup !== false){\r
36551                 if(this.getToken() == token){\r
36552                     return true;\r
36553                 }\r
36554             }\r
36555             if (Ext.isIE) {\r
36556                 return updateIFrame(token);\r
36557             } else {\r
36558                 top.location.hash = token;\r
36559                 return true;\r
36560             }\r
36561         },\r
36562 \r
36563         \r
36564         back: function(){\r
36565             history.go(-1);\r
36566         },\r
36567 \r
36568         \r
36569         forward: function(){\r
36570             history.go(1);\r
36571         },\r
36572 \r
36573         \r
36574         getToken: function() {\r
36575             return ready ? currentToken : getHash();\r
36576         }\r
36577     };\r
36578 })();\r
36579 Ext.apply(Ext.History, new Ext.util.Observable());\r
36580 Ext.debug = {};\r
36581 \r
36582 (function(){\r
36583 \r
36584 var cp;\r
36585 \r
36586 function createConsole(){\r
36587 \r
36588     var scriptPanel = new Ext.debug.ScriptsPanel();\r
36589     var logView = new Ext.debug.LogPanel();\r
36590     var tree = new Ext.debug.DomTree();\r
36591 \r
36592     var tabs = new Ext.TabPanel({\r
36593         activeTab: 0,\r
36594         border: false,\r
36595         tabPosition: 'bottom',\r
36596         items: [{\r
36597             title: 'Debug Console',\r
36598             layout:'border',\r
36599             items: [logView, scriptPanel]\r
36600         },{\r
36601             title: 'DOM Inspector',\r
36602             layout:'border',\r
36603             items: [tree]\r
36604         }]\r
36605     });\r
36606 \r
36607     cp = new Ext.Panel({\r
36608         id: 'x-debug-browser',\r
36609         title: 'Console',\r
36610         collapsible: true,\r
36611         animCollapse: false,\r
36612         style: 'position:absolute;left:0;bottom:0;',\r
36613         height:200,\r
36614         logView: logView,\r
36615         layout: 'fit',\r
36616         \r
36617         tools:[{\r
36618             id: 'close',\r
36619             handler: function(){\r
36620                 cp.destroy();\r
36621                 cp = null;\r
36622                 Ext.EventManager.removeResizeListener(handleResize);\r
36623             }\r
36624         }],\r
36625 \r
36626         items: tabs\r
36627     });\r
36628 \r
36629     cp.render(document.body);\r
36630 \r
36631     cp.resizer = new Ext.Resizable(cp.el, {\r
36632         minHeight:50,\r
36633         handles: "n",\r
36634         pinned: true,\r
36635         transparent:true,\r
36636         resizeElement : function(){\r
36637             var box = this.proxy.getBox();\r
36638             this.proxy.hide();\r
36639             cp.setHeight(box.height);\r
36640             return box;\r
36641         }\r
36642     });\r
36643 \r
36644     function handleResize(){\r
36645         cp.setWidth(Ext.getBody().getViewSize().width);\r
36646     }\r
36647     Ext.EventManager.onWindowResize(handleResize);\r
36648 \r
36649     handleResize();\r
36650 }\r
36651 \r
36652 \r
36653 Ext.apply(Ext, {\r
36654     log : function(){\r
36655         if(!cp){\r
36656             createConsole();\r
36657         }\r
36658         cp.logView.log.apply(cp.logView, arguments);\r
36659     },\r
36660 \r
36661     logf : function(format, arg1, arg2, etc){\r
36662         Ext.log(String.format.apply(String, arguments));\r
36663     },\r
36664 \r
36665     dump : function(o){\r
36666         if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){\r
36667             Ext.log(o);\r
36668         }else if(!o){\r
36669             Ext.log("null");\r
36670         }else if(typeof o != "object"){\r
36671             Ext.log('Unknown return type');\r
36672         }else if(Ext.isArray(o)){\r
36673             Ext.log('['+o.join(',')+']');\r
36674         }else{\r
36675             var b = ["{\n"];\r
36676             for(var key in o){\r
36677                 var to = typeof o[key];\r
36678                 if(to != "function" && to != "object"){\r
36679                     b.push(String.format("  {0}: {1},\n", key, o[key]));\r
36680                 }\r
36681             }\r
36682             var s = b.join("");\r
36683             if(s.length > 3){\r
36684                 s = s.substr(0, s.length-2);\r
36685             }\r
36686             Ext.log(s + "\n}");\r
36687         }\r
36688     },\r
36689 \r
36690     _timers : {},\r
36691 \r
36692     time : function(name){\r
36693         name = name || "def";\r
36694         Ext._timers[name] = new Date().getTime();\r
36695     },\r
36696 \r
36697     timeEnd : function(name, printResults){\r
36698         var t = new Date().getTime();\r
36699         name = name || "def";\r
36700         var v = String.format("{0} ms", t-Ext._timers[name]);\r
36701         Ext._timers[name] = new Date().getTime();\r
36702         if(printResults !== false){\r
36703             Ext.log('Timer ' + (name == "def" ? v : name + ": " + v));\r
36704         }\r
36705         return v;\r
36706     }\r
36707 });\r
36708 \r
36709 })();\r
36710 \r
36711 \r
36712 Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {\r
36713     id:'x-debug-scripts',\r
36714     region: 'east',\r
36715     minWidth: 200,\r
36716     split: true,\r
36717     width: 350,\r
36718     border: false,\r
36719     layout:'anchor',\r
36720     style:'border-width:0 0 0 1px;',\r
36721 \r
36722     initComponent : function(){\r
36723 \r
36724         this.scriptField = new Ext.form.TextArea({\r
36725             anchor: '100% -26',\r
36726             style:'border-width:0;'\r
36727         });\r
36728 \r
36729         this.trapBox = new Ext.form.Checkbox({\r
36730             id: 'console-trap',\r
36731             boxLabel: 'Trap Errors',\r
36732             checked: true\r
36733         });\r
36734 \r
36735         this.toolbar = new Ext.Toolbar([{\r
36736                 text: 'Run',\r
36737                 scope: this,\r
36738                 handler: this.evalScript\r
36739             },{\r
36740                 text: 'Clear',\r
36741                 scope: this,\r
36742                 handler: this.clear\r
36743             },\r
36744             '->',\r
36745             this.trapBox,\r
36746             ' ', ' '\r
36747         ]);\r
36748 \r
36749         this.items = [this.toolbar, this.scriptField];\r
36750 \r
36751         Ext.debug.ScriptsPanel.superclass.initComponent.call(this);\r
36752     },\r
36753 \r
36754     evalScript : function(){\r
36755         var s = this.scriptField.getValue();\r
36756         if(this.trapBox.getValue()){\r
36757             try{\r
36758                 var rt = eval(s);\r
36759                 Ext.dump(rt === undefined? '(no return)' : rt);\r
36760             }catch(e){\r
36761                 Ext.log(e.message || e.descript);\r
36762             }\r
36763         }else{\r
36764             var rt = eval(s);\r
36765             Ext.dump(rt === undefined? '(no return)' : rt);\r
36766         }\r
36767     },\r
36768 \r
36769     clear : function(){\r
36770         this.scriptField.setValue('');\r
36771         this.scriptField.focus();\r
36772     }\r
36773 \r
36774 });\r
36775 \r
36776 Ext.debug.LogPanel = Ext.extend(Ext.Panel, {\r
36777     autoScroll: true,\r
36778     region: 'center',\r
36779     border: false,\r
36780     style:'border-width:0 1px 0 0',\r
36781 \r
36782     log : function(){\r
36783         var markup = [  '<div style="padding:5px !important;border-bottom:1px solid #ccc;">',\r
36784                     Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/\n/g, '<br />').replace(/\s/g, '&#160;'),\r
36785                     '</div>'].join('');\r
36786 \r
36787         this.body.insertHtml('beforeend', markup);\r
36788         this.body.scrollTo('top', 100000);\r
36789     },\r
36790 \r
36791     clear : function(){\r
36792         this.body.update('');\r
36793         this.body.dom.scrollTop = 0;\r
36794     }\r
36795 });\r
36796 \r
36797 Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {\r
36798     enableDD:false ,\r
36799     lines:false,\r
36800     rootVisible:false,\r
36801     animate:false,\r
36802     hlColor:'ffff9c',\r
36803     autoScroll: true,\r
36804     region:'center',\r
36805     border:false,\r
36806 \r
36807     initComponent : function(){\r
36808 \r
36809 \r
36810         Ext.debug.DomTree.superclass.initComponent.call(this);\r
36811         \r
36812         // tree related stuff\r
36813         var styles = false, hnode;\r
36814         var nonSpace = /^\s*$/;\r
36815         var html = Ext.util.Format.htmlEncode;\r
36816         var ellipsis = Ext.util.Format.ellipsis;\r
36817         var styleRe = /\s?([a-z\-]*)\:([^;]*)(?:[;\s\n\r]*)/gi;\r
36818 \r
36819         function findNode(n){\r
36820             if(!n || n.nodeType != 1 || n == document.body || n == document){\r
36821                 return false;\r
36822             }\r
36823             var pn = [n], p = n;\r
36824             while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){\r
36825                 pn.unshift(p);\r
36826             }\r
36827             var cn = hnode;\r
36828             for(var i = 0, len = pn.length; i < len; i++){\r
36829                 cn.expand();\r
36830                 cn = cn.findChild('htmlNode', pn[i]);\r
36831                 if(!cn){ // in this dialog?\r
36832                     return false;\r
36833                 }\r
36834             }\r
36835             cn.select();\r
36836             var a = cn.ui.anchor;\r
36837             treeEl.dom.scrollTop = Math.max(0 ,a.offsetTop-10);\r
36838             //treeEl.dom.scrollLeft = Math.max(0 ,a.offsetLeft-10); no likey\r
36839             cn.highlight();\r
36840             return true;\r
36841         }\r
36842 \r
36843         function nodeTitle(n){\r
36844             var s = n.tagName;\r
36845             if(n.id){\r
36846                 s += '#'+n.id;\r
36847             }else if(n.className){\r
36848                 s += '.'+n.className;\r
36849             }\r
36850             return s;\r
36851         }\r
36852 \r
36853         function onNodeSelect(t, n, last){\r
36854             return;\r
36855             if(last && last.unframe){\r
36856                 last.unframe();\r
36857             }\r
36858             var props = {};\r
36859             if(n && n.htmlNode){\r
36860                 if(frameEl.pressed){\r
36861                     n.frame();\r
36862                 }\r
36863                 if(inspecting){\r
36864                     return;\r
36865                 }\r
36866                 addStyle.enable();\r
36867                 reload.setDisabled(n.leaf);\r
36868                 var dom = n.htmlNode;\r
36869                 stylePanel.setTitle(nodeTitle(dom));\r
36870                 if(styles && !showAll.pressed){\r
36871                     var s = dom.style ? dom.style.cssText : '';\r
36872                     if(s){\r
36873                         var m;\r
36874                         while ((m = styleRe.exec(s)) != null){\r
36875                             props[m[1].toLowerCase()] = m[2];\r
36876                         }\r
36877                     }\r
36878                 }else if(styles){\r
36879                     var cl = Ext.debug.cssList;\r
36880                     var s = dom.style, fly = Ext.fly(dom);\r
36881                     if(s){\r
36882                         for(var i = 0, len = cl.length; i<len; i++){\r
36883                             var st = cl[i];\r
36884                             var v = s[st] || fly.getStyle(st);\r
36885                             if(v != undefined && v !== null && v !== ''){\r
36886                                 props[st] = v;\r
36887                             }\r
36888                         }\r
36889                     }\r
36890                 }else{\r
36891                     for(var a in dom){\r
36892                         var v = dom[a];\r
36893                         if((isNaN(a+10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())){\r
36894                             props[a] = v;\r
36895                         }\r
36896                     }\r
36897                 }\r
36898             }else{\r
36899                 if(inspecting){\r
36900                     return;\r
36901                 }\r
36902                 addStyle.disable();\r
36903                 reload.disabled();\r
36904             }\r
36905             stylesGrid.setSource(props);\r
36906             stylesGrid.treeNode = n;\r
36907             stylesGrid.view.fitColumns();\r
36908         }\r
36909 \r
36910         this.loader = new Ext.tree.TreeLoader();\r
36911         this.loader.load = function(n, cb){\r
36912             var isBody = n.htmlNode == document.body;\r
36913             var cn = n.htmlNode.childNodes;\r
36914             for(var i = 0, c; c = cn[i]; i++){\r
36915                 if(isBody && c.id == 'x-debug-browser'){\r
36916                     continue;\r
36917                 }\r
36918                 if(c.nodeType == 1){\r
36919                     n.appendChild(new Ext.debug.HtmlNode(c));\r
36920                 }else if(c.nodeType == 3 && !nonSpace.test(c.nodeValue)){\r
36921                     n.appendChild(new Ext.tree.TreeNode({\r
36922                         text:'<em>' + ellipsis(html(String(c.nodeValue)), 35) + '</em>',\r
36923                         cls: 'x-tree-noicon'\r
36924                     }));\r
36925                 }\r
36926             }\r
36927             cb();\r
36928         };\r
36929 \r
36930         //tree.getSelectionModel().on('selectionchange', onNodeSelect, null, {buffer:250});\r
36931 \r
36932         this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));\r
36933 \r
36934         hnode = this.root.appendChild(new Ext.debug.HtmlNode(\r
36935                 document.getElementsByTagName('html')[0]\r
36936         ));\r
36937 \r
36938     }\r
36939 });\r
36940 \r
36941 \r
36942 // highly unusual class declaration\r
36943 Ext.debug.HtmlNode = function(){\r
36944     var html = Ext.util.Format.htmlEncode;\r
36945     var ellipsis = Ext.util.Format.ellipsis;\r
36946     var nonSpace = /^\s*$/;\r
36947 \r
36948     var attrs = [\r
36949         {n: 'id', v: 'id'},\r
36950         {n: 'className', v: 'class'},\r
36951         {n: 'name', v: 'name'},\r
36952         {n: 'type', v: 'type'},\r
36953         {n: 'src', v: 'src'},\r
36954         {n: 'href', v: 'href'}\r
36955     ];\r
36956 \r
36957     function hasChild(n){\r
36958         for(var i = 0, c; c = n.childNodes[i]; i++){\r
36959             if(c.nodeType == 1){\r
36960                 return true;\r
36961             }\r
36962         }\r
36963         return false;\r
36964     }\r
36965 \r
36966     function renderNode(n, leaf){\r
36967         var tag = n.tagName.toLowerCase();\r
36968         var s = '&lt;' + tag;\r
36969         for(var i = 0, len = attrs.length; i < len; i++){\r
36970             var a = attrs[i];\r
36971             var v = n[a.n];\r
36972             if(v && !nonSpace.test(v)){\r
36973                 s += ' ' + a.v + '=&quot;<i>' + html(v) +'</i>&quot;';\r
36974             }\r
36975         }\r
36976         var style = n.style ? n.style.cssText : '';\r
36977         if(style){\r
36978             s += ' style=&quot;<i>' + html(style.toLowerCase()) +'</i>&quot;';\r
36979         }\r
36980         if(leaf && n.childNodes.length > 0){\r
36981             s+='&gt;<em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em>&lt;/'+tag+'&gt;';\r
36982         }else if(leaf){\r
36983             s += ' /&gt;';\r
36984         }else{\r
36985             s += '&gt;';\r
36986         }\r
36987         return s;\r
36988     }\r
36989 \r
36990     var HtmlNode = function(n){\r
36991         var leaf = !hasChild(n);\r
36992         this.htmlNode = n;\r
36993         this.tagName = n.tagName.toLowerCase();\r
36994         var attr = {\r
36995             text : renderNode(n, leaf),\r
36996             leaf : leaf,\r
36997             cls: 'x-tree-noicon'\r
36998         };\r
36999         HtmlNode.superclass.constructor.call(this, attr);\r
37000         this.attributes.htmlNode = n; // for searching\r
37001         if(!leaf){\r
37002             this.on('expand', this.onExpand,  this);\r
37003             this.on('collapse', this.onCollapse,  this);\r
37004         }\r
37005     };\r
37006 \r
37007 \r
37008     Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {\r
37009         cls: 'x-tree-noicon',\r
37010         preventHScroll: true,\r
37011         refresh : function(highlight){\r
37012             var leaf = !hasChild(this.htmlNode);\r
37013             this.setText(renderNode(this.htmlNode, leaf));\r
37014             if(highlight){\r
37015                 Ext.fly(this.ui.textNode).highlight();\r
37016             }\r
37017         },\r
37018 \r
37019         onExpand : function(){\r
37020             if(!this.closeNode && this.parentNode){\r
37021                 this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({\r
37022                     text:'&lt;/' + this.tagName + '&gt;',\r
37023                     cls: 'x-tree-noicon'\r
37024                 }), this.nextSibling);\r
37025             }else if(this.closeNode){\r
37026                 this.closeNode.ui.show();\r
37027             }\r
37028         },\r
37029 \r
37030         onCollapse : function(){\r
37031             if(this.closeNode){\r
37032                 this.closeNode.ui.hide();\r
37033             }\r
37034         },\r
37035 \r
37036         render : function(bulkRender){\r
37037             HtmlNode.superclass.render.call(this, bulkRender);\r
37038         },\r
37039 \r
37040         highlightNode : function(){\r
37041             //Ext.fly(this.htmlNode).highlight();\r
37042         },\r
37043 \r
37044         highlight : function(){\r
37045             //Ext.fly(this.ui.textNode).highlight();\r
37046         },\r
37047 \r
37048         frame : function(){\r
37049             this.htmlNode.style.border = '1px solid #0000ff';\r
37050             //this.highlightNode();\r
37051         },\r
37052 \r
37053         unframe : function(){\r
37054             //Ext.fly(this.htmlNode).removeClass('x-debug-frame');\r
37055             this.htmlNode.style.border = '';\r
37056         }\r
37057     });\r
37058 \r
37059     return HtmlNode;\r
37060 }();\r
37061 \r
37062 \r
37063 \r