2 * Ext JS Library 2.2.1
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\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
15 // build as innerHTML where available
\r
16 var createHtml = function(o){
\r
17 if(typeof o == 'string'){
\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
32 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
\r
33 if(attr == "style"){
\r
35 if(typeof s == "function"){
\r
38 if(typeof s == "string"){
\r
39 b += ' style="' + s + '"';
\r
40 }else if(typeof s == "object"){
\r
43 if(typeof s[key] != "function"){
\r
44 b += key + ":" + s[key] + ";";
\r
51 b += ' class="' + o["cls"] + '"';
\r
52 }else if(attr == "htmlFor"){
\r
53 b += ' for="' + o["htmlFor"] + '"';
\r
55 b += " " + attr + '="' + o[attr] + '"';
\r
59 if(emptyTags.test(o.tag)){
\r
63 var cn = o.children || o.cn;
\r
65 b += createHtml(cn);
\r
69 b += "</" + o.tag + ">";
\r
76 var createDom = function(o, parentNode){
\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
83 } else if (typeof o == "string") { // Allow a string as a child spec.
\r
84 el = document.createTextNode(o);
\r
86 el = document.createElement(o.tag||'div');
\r
87 var useSet = !!el.setAttribute; // In IE some elements don't have setAttribute
\r
89 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
\r
91 el.className = o["cls"];
\r
93 if(useSet) el.setAttribute(attr, o[attr]);
\r
94 else el[attr] = o[attr];
\r
97 Ext.DomHelper.applyStyles(el, o.style);
\r
98 var cn = o.children || o.cn;
\r
102 el.innerHTML = o.html;
\r
106 parentNode.appendChild(el);
\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
120 // kill repeat to save bytes
\r
121 var ts = '<table>',
\r
123 tbs = ts+'<tbody>',
\r
124 tbe = '</tbody>'+te,
\r
125 trs = tbs + '<tr>',
\r
129 var insertIntoTable = function(tag, where, el, html){
\r
131 tempTableEl = document.createElement('div');
\r
136 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
\r
139 if(where == 'beforebegin'){
\r
141 el = el.parentNode;
\r
143 before = el.nextSibling;
\r
144 el = el.parentNode;
\r
146 node = ieTable(4, trs, html, tre);
\r
148 else if(tag == 'tr'){
\r
149 if(where == 'beforebegin'){
\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
161 node = ieTable(4, trs, html, tre);
\r
163 } else if(tag == 'tbody'){
\r
164 if(where == 'beforebegin'){
\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
173 if(where == 'afterbegin'){
\r
174 before = el.firstChild;
\r
176 node = ieTable(3, tbs, html, tbe);
\r
179 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
\r
182 if(where == 'afterbegin'){
\r
183 before = el.firstChild;
\r
185 node = ieTable(2, ts, html, te);
\r
187 el.insertBefore(node, before);
\r
197 markup : function(o){
\r
198 return createHtml(o);
\r
202 applyStyles : function(el, styles){
\r
205 if(typeof styles == "string"){
\r
206 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
\r
208 while ((matches = re.exec(styles)) != null){
\r
209 el.setStyle(matches[1], matches[2]);
\r
211 }else if (typeof styles == "object"){
\r
212 for (var style in styles){
\r
213 el.setStyle(style, styles[style]);
\r
215 }else if (typeof styles == "function"){
\r
216 Ext.DomHelper.applyStyles(el, styles.call());
\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
227 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
\r
232 case "beforebegin":
\r
233 el.insertAdjacentHTML('BeforeBegin', html);
\r
234 return el.previousSibling;
\r
236 el.insertAdjacentHTML('AfterBegin', html);
\r
237 return el.firstChild;
\r
239 el.insertAdjacentHTML('BeforeEnd', html);
\r
240 return el.lastChild;
\r
242 el.insertAdjacentHTML('AfterEnd', html);
\r
243 return el.nextSibling;
\r
245 throw 'Illegal insertion point -> "' + where + '"';
\r
247 var range = el.ownerDocument.createRange();
\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
257 range.setStartBefore(el.firstChild);
\r
258 frag = range.createContextualFragment(html);
\r
259 el.insertBefore(frag, el.firstChild);
\r
260 return el.firstChild;
\r
262 el.innerHTML = html;
\r
263 return el.firstChild;
\r
267 range.setStartAfter(el.lastChild);
\r
268 frag = range.createContextualFragment(html);
\r
269 el.appendChild(frag);
\r
270 return el.lastChild;
\r
272 el.innerHTML = html;
\r
273 return el.lastChild;
\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
281 throw 'Illegal insertion point -> "' + where + '"';
\r
285 insertBefore : function(el, o, returnElement){
\r
286 return this.doInsert(el, o, returnElement, "beforeBegin");
\r
290 insertAfter : function(el, o, returnElement){
\r
291 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
\r
295 insertFirst : function(el, o, returnElement){
\r
296 return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
\r
300 doInsert : function(el, o, returnElement, pos, sibling){
\r
301 el = Ext.getDom(el);
\r
304 newNode = createDom(o, null);
\r
305 (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
\r
307 var html = createHtml(o);
\r
308 newNode = this.insertHtml(pos, el, html);
\r
310 return returnElement ? Ext.get(newNode, true) : newNode;
\r
314 append : function(el, o, returnElement){
\r
315 el = Ext.getDom(el);
\r
318 newNode = createDom(o, null);
\r
319 el.appendChild(newNode);
\r
321 var html = createHtml(o);
\r
322 newNode = this.insertHtml("beforeEnd", el, html);
\r
324 return returnElement ? Ext.get(newNode, true) : newNode;
\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
335 createTemplate : function(o){
\r
336 var html = createHtml(o);
\r
337 return new Ext.Template(html);
\r
343 Ext.Template = function(html){
\r
345 if(Ext.isArray(html)){
\r
346 html = html.join("");
\r
347 }else if(a.length > 1){
\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
353 buf[buf.length] = a[i];
\r
356 html = buf.join('');
\r
364 Ext.Template.prototype = {
\r
366 applyTemplate : function(values){
\r
368 return this.compiled(values);
\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
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
386 args = [values[name]].concat(args);
\r
388 args = [values[name]];
\r
390 return fm[format].apply(fm, args);
\r
393 return values[name] !== undefined ? values[name] : "";
\r
396 return this.html.replace(this.re, fn);
\r
400 set : function(html, compile){
\r
402 this.compiled = null;
\r
410 disableFormats : false,
\r
413 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
\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
426 format = 'this.call("'+ format.substr(5) + '", ';
\r
430 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
\r
432 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
\r
435 // branched to use + in gecko and [].join() in others
\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
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
450 // private function used to call members
\r
451 call : function(fnName, value, allValues){
\r
452 return this[fnName](value, allValues);
\r
456 insertFirst: function(el, values, returnElement){
\r
457 return this.doInsert('afterBegin', el, values, returnElement);
\r
461 insertBefore: function(el, values, returnElement){
\r
462 return this.doInsert('beforeBegin', el, values, returnElement);
\r
466 insertAfter : function(el, values, returnElement){
\r
467 return this.doInsert('afterEnd', el, values, returnElement);
\r
471 append : function(el, values, returnElement){
\r
472 return this.doInsert('beforeEnd', el, values, returnElement);
\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
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
489 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
\r
491 // backwards compat
\r
492 Ext.DomHelper.Template = Ext.Template;
\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
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
510 function child(p, index){
\r
512 var n = p.firstChild;
\r
514 if(n.nodeType == 1){
\r
525 while((n = n.nextSibling) && n.nodeType != 1);
\r
530 while((n = n.previousSibling) && n.nodeType != 1);
\r
534 function children(d){
\r
535 var n = d.firstChild, ni = -1;
\r
537 var nx = n.nextSibling;
\r
538 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
\r
541 n.nodeIndex = ++ni;
\r
548 function byClassName(c, a, v){
\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
561 function attrValue(n, attr){
\r
562 if(!n.tagName && typeof n.length != "undefined"){
\r
571 if(attr == "class" || attr == "className"){
\r
572 return n.className;
\r
574 return n.getAttribute(attr) || n[attr];
\r
578 function getNodes(ns, mode, tagName){
\r
579 var result = [], ri = -1, cs;
\r
583 tagName = tagName || "*";
\r
584 if(typeof ns.getElementsByTagName != "undefined"){
\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
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
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
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
623 function concat(a, b){
\r
625 return a.concat(b);
\r
627 for(var i = 0, l = b.length; i < l; i++){
\r
628 a[a.length] = b[i];
\r
633 function byTag(cs, tagName){
\r
634 if(cs.tagName || cs == document){
\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
650 function byId(cs, attr, id){
\r
651 if(cs.tagName || cs == document){
\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
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
673 a = Ext.DomQuery.getStyle(ci, attr);
\r
675 else if(attr == "class" || attr == "className"){
\r
677 }else if(attr == "for"){
\r
679 }else if(attr == "href"){
\r
680 a = ci.getAttribute("href", 2);
\r
682 a = ci.getAttribute(attr);
\r
684 if((f && f(a, value)) || (!f && a)){
\r
691 function byPseudo(cs, name, value){
\r
692 return Ext.DomQuery.pseudos[name](cs, value);
\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
700 // this eval is stop the compressor from
\r
701 // renaming the variable to something shorter
\r
702 eval("var batch = 30803;");
\r
706 function nodupIEXml(cs){
\r
708 cs[0].setAttribute("_nodup", d);
\r
710 for(var i = 1, len = cs.length; i < len; i++){
\r
712 if(!c.getAttribute("_nodup") != d){
\r
713 c.setAttribute("_nodup", d);
\r
717 for(var i = 0, len = cs.length; i < len; i++){
\r
718 cs[i].removeAttribute("_nodup");
\r
723 function nodup(cs){
\r
727 var len = cs.length, c, i, r = cs, cj, ri = -1;
\r
728 if(!len || typeof cs.nodeType != "undefined" || len == 1){
\r
731 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
\r
732 return nodupIEXml(cs);
\r
736 for(i = 1; c = cs[i]; i++){
\r
741 for(var j = 0; j < i; j++){
\r
744 for(j = i+1; cj = cs[j]; j++){
\r
745 if(cj._nodup != d){
\r
756 function quickDiffIEXml(c1, c2){
\r
758 for(var i = 0, len = c1.length; i < len; i++){
\r
759 c1[i].setAttribute("_qdiff", d);
\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
767 for(var i = 0, len = c1.length; i < len; i++){
\r
768 c1[i].removeAttribute("_qdiff");
\r
773 function quickDiff(c1, c2){
\r
774 var len1 = c1.length;
\r
778 if(isIE && c1[0].selectSingleNode){
\r
779 return quickDiffIEXml(c1, c2);
\r
782 for(var i = 0; i < len1; i++){
\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
794 function quickId(ns, mode, root, id){
\r
796 var d = root.ownerDocument || root;
\r
797 return d.getElementById(id);
\r
799 ns = getNodes(ns, mode, "*");
\r
800 return byId(ns, null, id);
\r
804 getStyle : function(el, name){
\r
805 return Ext.fly(el).getStyle(name);
\r
808 compile : function(path, type){
\r
809 type = type || "select";
\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
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
823 // strip leading slashes
\r
824 while(path.substr(0, 1)=="/"){
\r
825 path = path.substr(1);
\r
828 while(q && lq != q){
\r
830 var tm = q.match(tagTokenRe);
\r
831 if(type == "select"){
\r
834 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
\r
836 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
\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
845 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
\r
847 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
\r
849 q = q.replace(tm[0], "");
\r
852 while(!(mm = q.match(modeRe))){
\r
853 var matched = false;
\r
854 for(var j = 0; j < tklen; j++){
\r
856 var m = q.match(t.re);
\r
858 fn[fn.length] = t.select.replace(tplRe, function(x, i){
\r
861 q = q.replace(m[0], "");
\r
866 // prevent infinite loop on bad selector
\r
868 throw 'Error parsing selector, parsing failed at "' + q + '"';
\r
872 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
\r
873 q = q.replace(mm[1], "");
\r
876 fn[fn.length] = "return nodup(n);\n}";
\r
882 select : function(path, root, type){
\r
883 if(!root || root == document){
\r
886 if(typeof root == "string"){
\r
887 root = document.getElementById(root);
\r
889 var paths = path.split(",");
\r
891 for(var i = 0, len = paths.length; i < len; i++){
\r
892 var p = paths[i].replace(trimRe, "");
\r
894 cache[p] = Ext.DomQuery.compile(p);
\r
896 throw p + " is not a valid selector";
\r
899 var result = cache[p](root);
\r
900 if(result && result != document){
\r
901 results = results.concat(result);
\r
904 if(paths.length > 1){
\r
905 return nodup(results);
\r
911 selectNode : function(path, root){
\r
912 return Ext.DomQuery.select(path, root)[0];
\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
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
928 selectNumber : function(path, root, defaultValue){
\r
929 var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
\r
930 return parseFloat(v);
\r
934 is : function(el, ss){
\r
935 if(typeof el == "string"){
\r
936 el = document.getElementById(el);
\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
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
949 var result = simpleCache[ss](els);
\r
950 return nonMatches ? quickDiff(result, els) : result;
\r
956 select: 'n = byClassName(n, null, " {1} ");'
\r
958 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
\r
959 select: 'n = byPseudo(n, "{1}", "{2}");'
\r
961 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
\r
962 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
\r
965 select: 'n = byId(n, null, "{1}");'
\r
968 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
\r
974 "=" : function(a, v){
\r
977 "!=" : function(a, v){
\r
980 "^=" : function(a, v){
\r
981 return a && a.substr(0, v.length) == v;
\r
983 "$=" : function(a, v){
\r
984 return a && a.substr(a.length-v.length) == v;
\r
986 "*=" : function(a, v){
\r
987 return a && a.indexOf(v) !== -1;
\r
989 "%=" : function(a, v){
\r
990 return (a % v) == 0;
\r
992 "|=" : function(a, v){
\r
993 return a && (a == v || a.substr(0, v.length+1) == v+'-');
\r
995 "~=" : function(a, v){
\r
996 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
\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
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
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
1032 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
\r
1033 if(cn.nodeType == 1){
\r
1034 cn.nodeIndex = ++j;
\r
1037 pn._batch = batch;
\r
1040 if (l == 0 || n.nodeIndex == l){
\r
1043 } else if ((n.nodeIndex + l) % f == 0){
\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
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
1067 if(cn.nodeType == 1 || cn.nodeType == 3){
\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
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
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
1109 "not" : function(c, ss){
\r
1110 return Ext.DomQuery.filter(c, ss, true);
\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
1127 "odd" : function(c){
\r
1128 return this["nth-child"](c, "odd");
\r
1131 "even" : function(c){
\r
1132 return this["nth-child"](c, "even");
\r
1135 "nth" : function(c, a){
\r
1136 return c[a-1] || [];
\r
1139 "first" : function(c){
\r
1140 return c[0] || [];
\r
1143 "last" : function(c){
\r
1144 return c[c.length-1] || [];
\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
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
1163 if(n && is(n, ss)){
\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
1175 if(n && is(n, ss)){
\r
1186 Ext.query = Ext.DomQuery.select;
\r
1189 Ext.util.Observable = function(){
\r
1191 if(this.listeners){
\r
1192 this.on(this.listeners);
\r
1193 delete this.listeners;
\r
1196 Ext.util.Observable.prototype = {
\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
1209 filterOptRe : /^(?:scope|delay|buffer|single)$/,
\r
1212 addListener : function(eventName, fn, scope, o){
\r
1213 if(typeof eventName == "object"){
\r
1216 if(this.filterOptRe.test(e)){
\r
1219 if(typeof o[e] == "function"){
\r
1221 this.addListener(e, o[e], o.scope, o);
\r
1223 // individual options
\r
1224 this.addListener(e, o[e].fn, o[e].scope, o[e]);
\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
1236 ce.addListener(fn, scope, o);
\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
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
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
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
1271 addEvents : function(o){
\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
1282 Ext.applyIf(this.events, o);
\r
1287 hasListener : function(eventName){
\r
1288 var e = this.events[eventName];
\r
1289 return typeof e == "object" && e.listeners.length > 0;
\r
1293 suspendEvents : function(){
\r
1294 this.eventsSuspended = true;
\r
1298 resumeEvents : function(){
\r
1299 this.eventsSuspended = false;
\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
1305 getMethodEvent : function(method){
\r
1306 if(!this.methodEvents){
\r
1307 this.methodEvents = {};
\r
1309 var e = this.methodEvents[method];
\r
1312 this.methodEvents[method] = e;
\r
1314 e.originalFn = this[method];
\r
1315 e.methodName = method;
\r
1320 var returnValue, v, cancel;
\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
1331 if(v.cancel === true){
\r
1334 }else if(v === false){
\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
1348 return returnValue;
\r
1352 if((v = e.originalFn.apply(obj, args)) !== undefined){
\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
1359 return returnValue;
\r
1362 return returnValue;
\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
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
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
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
1397 Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;
\r
1399 Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;
\r
1402 Ext.util.Observable.capture = function(o, fn, scope){
\r
1403 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
\r
1407 Ext.util.Observable.releaseCapture = function(o){
\r
1408 o.fireEvent = Ext.util.Observable.prototype.fireEvent;
\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
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
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
1436 Ext.util.Event = function(obj, name){
\r
1439 this.listeners = [];
\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
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
1456 createListener : function(fn, scope, o){
\r
1458 scope = scope || this.obj;
\r
1459 var l = {fn: fn, scope: scope, options: o};
\r
1462 h = createDelayed(h, o, scope);
\r
1465 h = createSingle(h, this, fn, scope);
\r
1468 h = createBuffered(h, o, scope);
\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
1479 if(l.fn == fn && l.scope == scope){
\r
1486 isListening : function(fn, scope){
\r
1487 return this.findListener(fn, scope) != -1;
\r
1490 removeListener : function(fn, scope){
\r
1492 if((index = this.findListener(fn, scope)) != -1){
\r
1494 this.listeners.splice(index, 1);
\r
1496 this.listeners = this.listeners.slice(0);
\r
1497 this.listeners.splice(index, 1);
\r
1504 clearListeners : function(){
\r
1505 this.listeners = [];
\r
1508 fire : function(){
\r
1509 var ls = this.listeners, scope, len = ls.length;
\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
1515 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
\r
1516 this.firing = false;
\r
1520 this.firing = false;
\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
1537 var addListener = function(el, ename, fn, wrap, scope){
\r
1538 var id = Ext.id(el);
\r
1542 var es = elHash[id];
\r
1546 var ls = es[ename];
\r
1555 E.on(el, ename, wrap);
\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
1563 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
\r
1564 Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
\r
1568 var removeListener = function(el, ename, fn, scope){
\r
1569 el = Ext.getDom(el);
\r
1571 var id = Ext.id(el), es = elHash[id], wrap;
\r
1573 var ls = es[ename], l;
\r
1575 for(var i = 0, len = ls.length; i < len; i++){
\r
1577 if(l.fn == fn && (!scope || l.scope == scope)){
\r
1579 E.un(el, ename, wrap);
\r
1586 if(ename == "mousewheel" && el.addEventListener && wrap){
\r
1587 el.removeEventListener("DOMMouseScroll", wrap, false);
\r
1589 if(ename == "mousedown" && el == document && wrap){ // fix stopped mousedowns on the document
\r
1590 Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
\r
1594 var removeAll = function(el){
\r
1595 el = Ext.getDom(el);
\r
1596 var id = Ext.id(el), es = elHash[id], ls;
\r
1598 for(var ename in es){
\r
1599 if(es.hasOwnProperty(ename)){
\r
1601 for(var i = 0, len = ls.length; i < len; i++){
\r
1602 E.un(el, ename, ls[i].wrap);
\r
1608 delete elHash[id];
\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
1620 if(Ext.isGecko || Ext.isOpera) {
\r
1621 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
\r
1624 var defer = document.getElementById("ie-deferred-loader");
\r
1626 defer.onreadystatechange = null;
\r
1627 defer.parentNode.removeChild(defer);
\r
1630 if(docReadyEvent){
\r
1631 docReadyEvent.fire();
\r
1632 docReadyEvent.clearListeners();
\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
1649 }else if(Ext.isSafari){
\r
1650 docReadyProcId = setInterval(function(){
\r
1651 var rs = document.readyState;
\r
1652 if(rs == "complete") {
\r
1657 // no matter what, make sure it fires on load
\r
1658 E.on(window, "load", fireDocReady);
\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
1670 var createSingle = function(h, el, ename, fn, scope){
\r
1671 return function(e){
\r
1672 Ext.EventManager.removeListener(el, ename, fn, scope);
\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
1683 }, o.delay || 10);
\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
1692 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
\r
1694 var h = function(e){
\r
1695 // prevent errors while unload occurring
\r
1696 if(!window[xname]){
\r
1699 e = Ext.EventObject.setEvent(e);
\r
1702 t = e.getTarget(o.delegate, el);
\r
1709 if(o.stopEvent === true){
\r
1712 if(o.preventDefault === true){
\r
1713 e.preventDefault();
\r
1715 if(o.stopPropagation === true){
\r
1716 e.stopPropagation();
\r
1719 if(o.normalized === false){
\r
1720 e = e.browserEvent;
\r
1723 fn.call(scope || el, e, t, o);
\r
1726 h = createDelayed(h, o);
\r
1729 h = createSingle(h, el, ename, fn, scope);
\r
1732 h = createBuffered(h, o);
\r
1735 addListener(el, ename, fn, h, scope);
\r
1739 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
\r
1743 addListener : function(element, eventName, fn, scope, options){
\r
1744 if(typeof eventName == "object"){
\r
1745 var o = eventName;
\r
1747 if(propRe.test(e)){
\r
1750 if(typeof o[e] == "function"){
\r
1752 listen(element, e, o, o[e], o.scope);
\r
1754 // individual options
\r
1755 listen(element, e, o[e]);
\r
1760 return listen(element, eventName, options, fn, scope);
\r
1764 removeListener : function(element, eventName, fn, scope){
\r
1765 return removeListener(element, eventName, fn, scope);
\r
1769 removeAll : function(element){
\r
1770 return removeAll(element);
\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
1781 if(!docReadyEvent){
\r
1784 options = options || {};
\r
1785 if(!options.delay){
\r
1786 options.delay = 1;
\r
1788 docReadyEvent.addListener(fn, scope, options);
\r
1792 doResizeEvent: function(){
\r
1793 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
\r
1797 onWindowResize : function(fn, scope, options){
\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
1803 resizeEvent.addListener(fn, scope, options);
\r
1806 // exposed only to allow manual firing
\r
1807 fireWindowResize : function(){
\r
1809 if((Ext.isIE||Ext.isAir) && resizeTask){
\r
1810 resizeTask.delay(50);
\r
1812 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
\r
1818 onTextResize : function(fn, scope, options){
\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
1830 }, this.textResizeInterval);
\r
1832 textEvent.addListener(fn, scope, options);
\r
1836 removeResizeListener : function(fn, scope){
\r
1838 resizeEvent.removeListener(fn, scope);
\r
1843 fireResize : function(){
\r
1845 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
\r
1849 ieDeferSrc : false,
\r
1851 textResizeInterval : 50
\r
1854 pub.on = pub.addListener;
\r
1856 pub.un = pub.removeListener;
\r
1858 pub.stoppedMouseDownEvent = new Ext.util.Event();
\r
1862 Ext.onReady = Ext.EventManager.onDocumentReady;
\r
1865 // Initialize doc classes
\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
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
1879 cls.push("ext-mac");
\r
1882 cls.push("ext-linux");
\r
1884 if(Ext.isBorderBox){
\r
1885 cls.push('ext-border-box');
\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
1890 p.className += ' ext-strict';
\r
1893 bd.className += cls.join(' ');
\r
1897 if(!initExtCss()){
\r
1898 Ext.onReady(initExtCss);
\r
1903 Ext.EventObject = function(){
\r
1905 var E = Ext.lib.Event;
\r
1907 // safari keypress events for special keys return bad keycodes
\r
1908 var safariKeys = {
\r
1910 63234 : 37, // left
\r
1911 63235 : 39, // right
\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
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
1925 Ext.EventObjectImpl = function(e){
\r
1927 this.setEvent(e.browserEvent || e);
\r
1931 Ext.EventObjectImpl.prototype = {
\r
1933 browserEvent : null,
\r
1957 CONTROL : 17, // legacy
\r
1970 PAGEUP : 33, // legacy
\r
1973 PAGEDOWN : 34, // legacy
\r
2087 NUM_MULTIPLY: 106,
\r
2095 NUM_DIVISION: 111,
\r
2122 setEvent : function(e){
\r
2123 if(e == this || (e && e.browserEvent)){ // already wrapped
\r
2126 this.browserEvent = 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
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
2144 this.xy = E.getXY(e);
\r
2147 this.shiftKey = false;
\r
2148 this.ctrlKey = false;
\r
2149 this.altKey = false;
\r
2151 this.charCode = 0;
\r
2152 this.target = null;
\r
2159 stopEvent : function(){
\r
2160 if(this.browserEvent){
\r
2161 if(this.browserEvent.type == 'mousedown'){
\r
2162 Ext.EventManager.stoppedMouseDownEvent.fire(this);
\r
2164 E.stopEvent(this.browserEvent);
\r
2169 preventDefault : function(){
\r
2170 if(this.browserEvent){
\r
2171 E.preventDefault(this.browserEvent);
\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
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
2193 stopPropagation : function(){
\r
2194 if(this.browserEvent){
\r
2195 if(this.browserEvent.type == 'mousedown'){
\r
2196 Ext.EventManager.stoppedMouseDownEvent.fire(this);
\r
2198 E.stopPropagation(this.browserEvent);
\r
2203 getCharCode : function(){
\r
2204 return this.charCode || this.keyCode;
\r
2208 getKey : function(){
\r
2209 var k = this.keyCode || this.charCode;
\r
2210 return Ext.isSafari ? (safariKeys[k] || k) : k;
\r
2214 getPageX : function(){
\r
2215 return this.xy[0];
\r
2219 getPageY : function(){
\r
2220 return this.xy[1];
\r
2224 getTime : function(){
\r
2225 if(this.browserEvent){
\r
2226 return E.getTime(this.browserEvent);
\r
2232 getXY : function(){
\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
2242 getRelatedTarget : function(){
\r
2243 if(this.browserEvent){
\r
2244 return E.getRelatedTarget(this.browserEvent);
\r
2250 getWheelDelta : function(){
\r
2251 var e = this.browserEvent;
\r
2253 if(e.wheelDelta){
\r
2254 delta = e.wheelDelta/120;
\r
2255 }else if(e.detail){
\r
2256 delta = -e.detail/3;
\r
2262 hasModifier : function(){
\r
2263 return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true : false;
\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
2272 getPoint : function(){
\r
2273 return new Ext.lib.Point(this.xy[0], this.xy[1]);
\r
2277 return new Ext.EventObjectImpl();
\r
2281 var D = Ext.lib.Dom;
\r
2282 var E = Ext.lib.Event;
\r
2283 var A = Ext.lib.Anim;
\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
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
2298 if(forceNew !== true && id && Ext.Element.cache[id]){ // element object already exists
\r
2299 return Ext.Element.cache[id];
\r
2306 this.id = id || Ext.id(dom);
\r
2309 var El = Ext.Element;
\r
2313 originalDisplay : "",
\r
2315 visibilityMode : 1,
\r
2317 defaultUnit : "px",
\r
2319 setVisibilityMode : function(visMode){
\r
2320 this.visibilityMode = visMode;
\r
2324 enableDisplayMode : function(display){
\r
2325 this.setVisibilityMode(El.DISPLAY);
\r
2326 if(typeof display != "undefined") this.originalDisplay = display;
\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
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
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
2356 up : function(simpleSelector, maxDepth){
\r
2357 return this.findParentNode(simpleSelector, maxDepth, true);
\r
2363 is : function(simpleSelector){
\r
2364 return Ext.DomQuery.is(this.dom, simpleSelector);
\r
2368 animate : function(args, duration, onComplete, easing, animType){
\r
2369 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
\r
2374 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
\r
2375 animType = animType || 'run';
\r
2377 var anim = Ext.lib.Anim[animType](
\r
2379 (opt.duration || defaultDur) || .35,
\r
2380 (opt.easing || defaultEase) || 'easeOut',
\r
2382 Ext.callback(cb, this);
\r
2383 Ext.callback(opt.callback, opt.scope || this, [this, opt]);
\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
2397 clean : function(forceReclean){
\r
2398 if(this.isCleaned && forceReclean !== true){
\r
2402 var d = this.dom, n = d.firstChild, ni = -1;
\r
2404 var nx = n.nextSibling;
\r
2405 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
\r
2408 n.nodeIndex = ++ni;
\r
2412 this.isCleaned = true;
\r
2417 scrollIntoView : function(container, hscroll){
\r
2418 var c = Ext.getDom(container) || Ext.getBody().dom;
\r
2419 var el = this.dom;
\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
2427 var ch = c.clientHeight;
\r
2428 var ct = parseInt(c.scrollTop, 10);
\r
2429 var cl = parseInt(c.scrollLeft, 10);
\r
2431 var cr = cl + c.clientWidth;
\r
2433 if(el.offsetHeight > ch || t < ct){
\r
2436 c.scrollTop = b-ch;
\r
2438 c.scrollTop = c.scrollTop; // corrects IE, other browsers will ignore
\r
2440 if(hscroll !== false){
\r
2441 if(el.offsetWidth > c.clientWidth || l < cl){
\r
2444 c.scrollLeft = r-c.clientWidth;
\r
2446 c.scrollLeft = c.scrollLeft;
\r
2452 scrollChildIntoView : function(child, hscroll){
\r
2453 Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
\r
2457 autoHeight : function(animate, duration, onComplete, easing){
\r
2458 var oldHeight = this.getHeight();
\r
2460 this.setHeight(1); // force clipping
\r
2461 setTimeout(function(){
\r
2462 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
\r
2464 this.setHeight(height);
\r
2466 if(typeof onComplete == "function"){
\r
2470 this.setHeight(oldHeight); // restore original height
\r
2471 this.setHeight(height, animate, duration, function(){
\r
2473 if(typeof onComplete == "function") onComplete();
\r
2474 }.createDelegate(this), easing);
\r
2476 }.createDelegate(this), 0);
\r
2481 contains : function(el){
\r
2482 if(!el){return false;}
\r
2483 return D.isAncestor(this.dom, el.dom ? el.dom : el);
\r
2487 isVisible : function(deep) {
\r
2488 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
\r
2489 if(deep !== true || !vis){
\r
2492 var p = this.dom.parentNode;
\r
2493 while(p && p.tagName.toLowerCase() != "body"){
\r
2494 if(!Ext.fly(p, '_isVisible').isVisible()){
\r
2503 select : function(selector, unique){
\r
2504 return El.select(selector, unique, this.dom);
\r
2508 query : function(selector){
\r
2509 return Ext.DomQuery.select(selector, this.dom);
\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
2519 down : function(selector, returnDom){
\r
2520 var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
\r
2521 return returnDom ? n : Ext.get(n);
\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
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
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
2543 setVisible : function(visible, animate){
\r
2544 if(!animate || !A){
\r
2545 if(this.visibilityMode == El.DISPLAY){
\r
2546 this.setDisplayed(visible);
\r
2548 this.fixDisplay();
\r
2549 this.dom.style.visibility = visible ? "visible" : "hidden";
\r
2552 // closure for composites
\r
2553 var dom = this.dom;
\r
2554 var visMode = this.visibilityMode;
\r
2556 this.setOpacity(.01);
\r
2557 this.setVisible(true);
\r
2559 this.anim({opacity: { to: (visible?1:0) }},
\r
2560 this.preanim(arguments, 1),
\r
2561 null, .35, 'easeIn', function(){
\r
2563 if(visMode == El.DISPLAY){
\r
2564 dom.style.display = "none";
\r
2566 dom.style.visibility = "hidden";
\r
2568 Ext.get(dom).setOpacity(1);
\r
2576 isDisplayed : function() {
\r
2577 return this.getStyle("display") != "none";
\r
2581 toggle : function(animate){
\r
2582 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
\r
2587 setDisplayed : function(value) {
\r
2588 if(typeof value == "boolean"){
\r
2589 value = value ? this.originalDisplay : "none";
\r
2591 this.setStyle("display", value);
\r
2596 focus : function() {
\r
2604 blur : function() {
\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
2618 if(className && !this.hasClass(className)){
\r
2619 this.dom.className = this.dom.className + " " + className;
\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
2634 this.addClass(className);
\r
2639 removeClass : function(className){
\r
2640 if(!className || !this.dom.className){
\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
2648 if(this.hasClass(className)){
\r
2649 var re = this.classReCache[className];
\r
2651 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
\r
2652 this.classReCache[className] = re;
\r
2654 this.dom.className =
\r
2655 this.dom.className.replace(re, " ");
\r
2665 toggleClass : function(className){
\r
2666 if(this.hasClass(className)){
\r
2667 this.removeClass(className);
\r
2669 this.addClass(className);
\r
2675 hasClass : function(className){
\r
2676 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
\r
2680 replaceClass : function(oldClassName, newClassName){
\r
2681 this.removeClass(oldClassName);
\r
2682 this.addClass(newClassName);
\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
2696 getStyle : function(){
\r
2697 return view && view.getComputedStyle ?
\r
2699 var el = this.dom, v, cs, camel;
\r
2700 if(prop == 'float'){
\r
2701 prop = "cssFloat";
\r
2703 if(v = el.style[prop]){
\r
2706 if(cs = view.getComputedStyle(el, "")){
\r
2707 if(!(camel = propCache[prop])){
\r
2708 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\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
2720 var fv = parseFloat(m[1]);
\r
2722 return fv ? fv / 100 : 0;
\r
2727 }else if(prop == 'float'){
\r
2728 prop = "styleFloat";
\r
2730 if(!(camel = propCache[prop])){
\r
2731 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\r
2733 if(v = el.style[camel]){
\r
2736 if(cs = el.currentStyle){
\r
2744 setStyle : function(prop, value){
\r
2745 if(typeof prop == "string"){
\r
2747 if(!(camel = propCache[prop])){
\r
2748 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\r
2750 if(camel == 'opacity') {
\r
2751 this.setOpacity(value);
\r
2753 this.dom.style[camel] = value;
\r
2756 for(var style in prop){
\r
2757 if(typeof prop[style] != "function"){
\r
2758 this.setStyle(style, prop[style]);
\r
2766 applyStyles : function(style){
\r
2767 Ext.DomHelper.applyStyles(this.dom, style);
\r
2772 getX : function(){
\r
2773 return D.getX(this.dom);
\r
2777 getY : function(){
\r
2778 return D.getY(this.dom);
\r
2782 getXY : function(){
\r
2783 return D.getXY(this.dom);
\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
2794 setX : function(x, animate){
\r
2795 if(!animate || !A){
\r
2796 D.setX(this.dom, x);
\r
2798 this.setXY([x, this.getY()], this.preanim(arguments, 1));
\r
2804 setY : function(y, animate){
\r
2805 if(!animate || !A){
\r
2806 D.setY(this.dom, y);
\r
2808 this.setXY([this.getX(), y], this.preanim(arguments, 1));
\r
2814 setLeft : function(left){
\r
2815 this.setStyle("left", this.addUnits(left));
\r
2820 setTop : function(top){
\r
2821 this.setStyle("top", this.addUnits(top));
\r
2826 setRight : function(right){
\r
2827 this.setStyle("right", this.addUnits(right));
\r
2832 setBottom : function(bottom){
\r
2833 this.setStyle("bottom", this.addUnits(bottom));
\r
2838 setXY : function(pos, animate){
\r
2839 if(!animate || !A){
\r
2840 D.setXY(this.dom, pos);
\r
2842 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
\r
2848 setLocation : function(x, y, animate){
\r
2849 this.setXY([x, y], this.preanim(arguments, 2));
\r
2854 moveTo : function(x, y, animate){
\r
2855 this.setXY([x, y], this.preanim(arguments, 2));
\r
2860 getRegion : function(){
\r
2861 return D.getRegion(this.dom);
\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
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
2879 getComputedHeight : function(){
\r
2880 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
\r
2882 h = parseInt(this.getStyle('height'), 10) || 0;
\r
2883 if(!this.isBorderBox()){
\r
2884 h += this.getFrameWidth('tb');
\r
2891 getComputedWidth : function(){
\r
2892 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
\r
2894 w = parseInt(this.getStyle('width'), 10) || 0;
\r
2895 if(!this.isBorderBox()){
\r
2896 w += this.getFrameWidth('lr');
\r
2903 getSize : function(contentSize){
\r
2904 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
\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
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
2921 return {width: w || this.getWidth(true), height: h || this.getHeight(true)};
\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
2932 width : d.clientWidth,
\r
2933 height: d.clientHeight
\r
2939 getValue : function(asNumber){
\r
2940 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
\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
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
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
2975 this.anim({width: {to: width}}, this.preanim(arguments, 1));
\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
2986 this.anim({height: {to: height}}, this.preanim(arguments, 1));
\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
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
3001 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
\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
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
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
3026 addListener : function(eventName, fn, scope, options){
\r
3027 Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
\r
3031 removeListener : function(eventName, fn, scope){
\r
3032 Ext.EventManager.removeListener(this.dom, eventName, fn, scope || this);
\r
3037 removeAllListeners : function(){
\r
3038 Ext.EventManager.removeAll(this.dom);
\r
3043 relayEvent : function(eventName, observable){
\r
3044 this.on(eventName, function(e){
\r
3045 observable.fireEvent(eventName, e);
\r
3050 setOpacity : function(opacity, animate){
\r
3051 if(!animate || !A){
\r
3052 var s = this.dom.style;
\r
3055 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
\r
3056 (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");
\r
3058 s.opacity = opacity;
\r
3061 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
\r
3067 getLeft : function(local){
\r
3069 return this.getX();
\r
3071 return parseInt(this.getStyle("left"), 10) || 0;
\r
3076 getRight : function(local){
\r
3078 return this.getX() + this.getWidth();
\r
3080 return (this.getLeft(true) + this.getWidth()) || 0;
\r
3085 getTop : function(local) {
\r
3087 return this.getY();
\r
3089 return parseInt(this.getStyle("top"), 10) || 0;
\r
3094 getBottom : function(local){
\r
3096 return this.getY() + this.getHeight();
\r
3098 return (this.getTop(true) + this.getHeight()) || 0;
\r
3103 position : function(pos, zIndex, x, y){
\r
3105 if(this.getStyle('position') == 'static'){
\r
3106 this.setStyle('position', 'relative');
\r
3109 this.setStyle("position", pos);
\r
3112 this.setStyle("z-index", zIndex);
\r
3114 if(x !== undefined && y !== undefined){
\r
3115 this.setXY([x, y]);
\r
3116 }else if(x !== undefined){
\r
3118 }else if(y !== undefined){
\r
3124 clearPositioning : function(value){
\r
3125 value = value ||'';
\r
3132 "position" : "static"
\r
3138 getPositioning : function(){
\r
3139 var l = this.getStyle("left");
\r
3140 var t = this.getStyle("top");
\r
3142 "position" : this.getStyle("position"),
\r
3144 "right" : l ? "" : this.getStyle("right"),
\r
3146 "bottom" : t ? "" : this.getStyle("bottom"),
\r
3147 "z-index" : this.getStyle("z-index")
\r
3152 getBorderWidth : function(side){
\r
3153 return this.addStyles(side, El.borders);
\r
3157 getPadding : function(side){
\r
3158 return this.addStyles(side, El.paddings);
\r
3162 setPositioning : function(pc){
\r
3163 this.applyStyles(pc);
\r
3164 if(pc.right == "auto"){
\r
3165 this.dom.style.right = "";
\r
3167 if(pc.bottom == "auto"){
\r
3168 this.dom.style.bottom = "";
\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
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
3190 this.dom.style.overflow = v;
\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
3202 move : function(direction, distance, animate){
\r
3203 var xy = this.getXY();
\r
3204 direction = direction.toLowerCase();
\r
3205 switch(direction){
\r
3208 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
\r
3212 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
\r
3217 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
\r
3222 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
\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
3237 this.setStyle("overflow", "hidden");
\r
3238 this.setStyle("overflow-x", "hidden");
\r
3239 this.setStyle("overflow-y", "hidden");
\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
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
3262 var w, h, vp = false;
\r
3265 if(d == document.body || d == document){
\r
3267 w = D.getViewWidth(); h = D.getViewHeight();
\r
3269 w = this.getWidth(); h = this.getHeight();
\r
3272 w = s.width; h = s.height;
\r
3274 var x = 0, y = 0, r = Math.round;
\r
3275 switch((anchor || "tl").toLowerCase()){
\r
3313 if(local === true){
\r
3317 var sc = this.getScroll();
\r
3318 return [x + sc.left, y + sc.top];
\r
3320 //Add the element's offset xy
\r
3321 var o = this.getXY();
\r
3322 return [x+o[0], y+o[1]];
\r
3326 getAlignToXY : function(el, p, o){
\r
3328 if(!el || !el.dom){
\r
3329 throw "Element.alignToXY with an element that doesn't exist";
\r
3332 var c = false; //constrain to viewport
\r
3333 var p1 = "", p2 = "";
\r
3338 }else if(p == "?"){
\r
3340 }else if(p.indexOf("-") == -1){
\r
3343 p = p.toLowerCase();
\r
3344 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
\r
3346 throw "Element.alignTo with an invalid alignment " + p;
\r
3348 p1 = m[1]; p2 = m[2]; c = !!m[3];
\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
3355 var x = a2[0] - a1[0] + o[0];
\r
3356 var y = a2[1] - a1[1] + o[1];
\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
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
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
3376 if((x+w) > dw + scrollX){
\r
3377 x = swapX ? r.left-w : dw+scrollX-w;
\r
3380 x = swapX ? r.right : scrollX;
\r
3382 if((y+h) > dh + scrollY){
\r
3383 y = swapY ? r.top-h : dh+scrollY-h;
\r
3386 y = swapY ? r.bottom : scrollY;
\r
3393 getConstrainToXY : function(){
\r
3394 var os = {top:0, left:0, bottom:0, right: 0};
\r
3396 return function(el, local, offsets, proposedXY){
\r
3398 offsets = offsets ? Ext.applyIf(offsets, os) : os;
\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
3405 vw = el.dom.clientWidth;
\r
3406 vh = el.dom.clientHeight;
\r
3408 var vxy = el.getXY();
\r
3414 var s = el.getScroll();
\r
3416 vx += offsets.left + s.left;
\r
3417 vy += offsets.top + s.top;
\r
3419 vw -= offsets.right;
\r
3420 vh -= offsets.bottom;
\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
3429 // only move it if it needs it
\r
3430 var moved = false;
\r
3432 // first validate right/bottom
\r
3441 // then make sure top/left isn't negative
\r
3450 return moved ? [x, y] : false;
\r
3455 adjustForConstraints : function(xy, parent, offsets){
\r
3456 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
\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
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
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
3478 action.call(this); // align immediately
\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
3488 this.dom.style.opacity = "";
\r
3489 this.dom.style["-moz-opacity"] = "";
\r
3490 this.dom.style["-khtml-opacity"] = "";
\r
3496 hide : function(animate){
\r
3497 this.setVisible(false, this.preanim(arguments, 0));
\r
3502 show : function(animate){
\r
3503 this.setVisible(true, this.preanim(arguments, 0));
\r
3508 addUnits : function(size){
\r
3509 return Ext.Element.addUnits(size, this.defaultUnit);
\r
3513 update : function(html, loadScripts, callback){
\r
3514 if(typeof html == "undefined"){
\r
3517 if(loadScripts !== true){
\r
3518 this.dom.innerHTML = html;
\r
3519 if(typeof callback == "function"){
\r
3524 var id = Ext.id();
\r
3525 var dom = this.dom;
\r
3527 html += '<span id="' + id + '"></span>';
\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
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
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
3551 window.eval(match[2]);
\r
3555 var el = document.getElementById(id);
\r
3556 if(el){Ext.removeNode(el);}
\r
3557 if(typeof callback == "function"){
\r
3561 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
\r
3566 load : function(){
\r
3567 var um = this.getUpdater();
\r
3568 um.update.apply(um, arguments);
\r
3573 getUpdater : function(){
\r
3574 if(!this.updateManager){
\r
3575 this.updateManager = new Ext.Updater(this);
\r
3577 return this.updateManager;
\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
3590 getCenterXY : function(){
\r
3591 return this.getAlignToXY(document, 'c-c');
\r
3595 center : function(centerIn){
\r
3596 this.alignTo(centerIn || document, 'c-c');
\r
3601 isBorderBox : function(){
\r
3602 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
\r
3606 getBox : function(contentBox, local){
\r
3609 xy = this.getXY();
\r
3611 var left = parseInt(this.getStyle("left"), 10) || 0;
\r
3612 var top = parseInt(this.getStyle("top"), 10) || 0;
\r
3615 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
\r
3617 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
\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
3625 bx.right = bx.x + bx.width;
\r
3626 bx.bottom = bx.y + bx.height;
\r
3631 getFrameWidth : function(sides, onlyContentBox){
\r
3632 return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
\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
3642 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
\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
3657 getMargins : function(side){
\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
3666 return this.addStyles(side, El.margins);
\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
3676 w = parseInt(v, 10);
\r
3677 if(w){ val += (w >= 0 ? w : -1 * w); }
\r
3684 createProxy : function(config, renderTo, matchBox){
\r
3685 config = typeof config == "object" ?
\r
3686 config : {tag : "div", cls: config};
\r
3690 proxy = Ext.DomHelper.append(renderTo, config, true);
\r
3692 proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
\r
3695 proxy.setBox(this.getBox());
\r
3701 mask : function(msg, msgCls){
\r
3702 if(this.getStyle("position") == "static"){
\r
3703 this.addClass("x-masked-relative");
\r
3705 if(this._maskMsg){
\r
3706 this._maskMsg.remove();
\r
3709 this._mask.remove();
\r
3712 this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);
\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
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
3727 return this._mask;
\r
3731 unmask : function(){
\r
3733 if(this._maskMsg){
\r
3734 this._maskMsg.remove();
\r
3735 delete this._maskMsg;
\r
3737 this._mask.remove();
\r
3738 delete this._mask;
\r
3740 this.removeClass(["x-masked", "x-masked-relative"]);
\r
3744 isMasked : function(){
\r
3745 return this._mask && this._mask.isVisible();
\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
3756 var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
\r
3757 shim.autoBoxAdjust = false;
\r
3762 remove : function(){
\r
3763 Ext.removeNode(this.dom);
\r
3764 delete El.cache[this.dom.id];
\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
3774 var preOutFn = function(e){
\r
3775 if(!e.within(this, true)){
\r
3776 outFn.apply(scope || this, arguments);
\r
3779 this.on("mouseover", preOverFn, this.dom);
\r
3780 this.on("mouseout", preOutFn, this.dom);
\r
3785 addClassOnOver : function(className){
\r
3788 Ext.fly(this, '_internal').addClass(className);
\r
3791 Ext.fly(this, '_internal').removeClass(className);
\r
3798 addClassOnFocus : function(className){
\r
3799 this.on("focus", function(){
\r
3800 Ext.fly(this, '_internal').addClass(className);
\r
3802 this.on("blur", function(){
\r
3803 Ext.fly(this, '_internal').removeClass(className);
\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
3817 d.on("mouseup", fn);
\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
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
3836 this.on(eventName, fn);
\r
3841 parent : function(selector, returnDom){
\r
3842 return this.matchNode('parentNode', 'parentNode', selector, returnDom);
\r
3846 next : function(selector, returnDom){
\r
3847 return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
\r
3851 prev : function(selector, returnDom){
\r
3852 return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
\r
3857 first : function(selector, returnDom){
\r
3858 return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
\r
3862 last : function(selector, returnDom){
\r
3863 return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
\r
3866 matchNode : function(dir, start, selector, returnDom){
\r
3867 var n = this.dom[start];
\r
3869 if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){
\r
3870 return !returnDom ? Ext.get(n) : n;
\r
3878 appendChild: function(el){
\r
3880 el.appendTo(this);
\r
3885 createChild: function(config, insertBefore, returnDom){
\r
3886 config = config || {tag:'div'};
\r
3888 return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
\r
3890 return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
\r
3894 appendTo: function(el){
\r
3895 el = Ext.getDom(el);
\r
3896 el.appendChild(this.dom);
\r
3901 insertBefore: function(el){
\r
3902 el = Ext.getDom(el);
\r
3903 el.parentNode.insertBefore(this.dom, el);
\r
3908 insertAfter: function(el){
\r
3909 el = Ext.getDom(el);
\r
3910 el.parentNode.insertBefore(this.dom, el.nextSibling);
\r
3915 insertFirst: function(el, returnDom){
\r
3917 if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
\r
3918 return this.createChild(el, this.dom.firstChild, returnDom);
\r
3920 el = Ext.getDom(el);
\r
3921 this.dom.insertBefore(el, this.dom.firstChild);
\r
3922 return !returnDom ? Ext.get(el) : el;
\r
3927 insertSibling: function(el, where, returnDom){
\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
3935 where = where ? where.toLowerCase() : 'before';
\r
3937 var refNode = where == 'before' ? this.dom : this.dom.nextSibling;
\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
3943 rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
\r
3947 rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
\r
3956 wrap: function(config, returnDom){
\r
3958 config = {tag: "div"};
\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
3966 replace: function(el){
\r
3968 this.insertBefore(el);
\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
3978 el = Ext.getDom(el);
\r
3979 this.dom.parentNode.insertBefore(el, this.dom);
\r
3981 El.uncache(this.id);
\r
3982 Ext.removeNode(this.dom);
\r
3984 this.id = Ext.id(el);
\r
3985 El.cache[this.id] = this;
\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
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
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
4009 Ext.DomHelper.applyStyles(el, o.style);
\r
4015 addKeyListener : function(key, fn, scope){
\r
4017 if(typeof key != "object" || Ext.isArray(key)){
\r
4026 shift : key.shift,
\r
4033 return new Ext.KeyMap(this, config);
\r
4037 addKeyMap : function(config){
\r
4038 return new Ext.KeyMap(this, config);
\r
4042 isScrollable : function(){
\r
4043 var dom = this.dom;
\r
4044 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
\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
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
4060 scroll : function(direction, distance, animate){
\r
4061 if(!this.isScrollable()){
\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
4075 var v = Math.min(l + distance, w-cw);
\r
4076 this.scrollTo("left", v, a);
\r
4083 var v = Math.max(l - distance, 0);
\r
4084 this.scrollTo("left", v, a);
\r
4092 var v = Math.max(t - distance, 0);
\r
4093 this.scrollTo("top", v, a);
\r
4101 var v = Math.min(t + distance, h-ch);
\r
4102 this.scrollTo("top", v, a);
\r
4111 translatePoints : function(x, y){
\r
4112 if(typeof x == 'object' || Ext.isArray(x)){
\r
4113 y = x[1]; x = x[0];
\r
4115 var p = this.getStyle('position');
\r
4116 var o = this.getXY();
\r
4118 var l = parseInt(this.getStyle('left'), 10);
\r
4119 var t = parseInt(this.getStyle('top'), 10);
\r
4122 l = (p == "relative") ? 0 : this.dom.offsetLeft;
\r
4125 t = (p == "relative") ? 0 : this.dom.offsetTop;
\r
4128 return {left: (x - o[0] + l), top: (y - o[1] + t)};
\r
4132 getScroll : function(){
\r
4133 var d = this.dom, doc = document;
\r
4134 if(d == doc || d == doc.body){
\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
4140 l = window.pageXOffset || (doc.body.scrollLeft || 0);
\r
4141 t = window.pageYOffset || (doc.body.scrollTop || 0);
\r
4143 return {left: l, top: t};
\r
4145 return {left: d.scrollLeft, top: d.scrollTop};
\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
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
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
4173 }else if(v.length == 7){
\r
4174 color += v.substr(1);
\r
4178 return(color.length > 5 ? color.toLowerCase() : defaultValue);
\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
4190 getAttributeNS : Ext.isIE ? function(ns, name){
\r
4192 var type = typeof d[ns+":"+name];
\r
4193 if(type != 'undefined' && type != 'unknown'){
\r
4194 return d[ns+":"+name];
\r
4197 } : function(ns, name){
\r
4199 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
\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
4208 var ep = El.prototype;
\r
4211 ep.on = ep.addListener;
\r
4212 // backwards compat
\r
4213 ep.mon = ep.addListener;
\r
4215 ep.getUpdateManager = ep.getUpdater;
\r
4218 ep.un = ep.removeListener;
\r
4221 ep.autoBoxAdjust = true;
\r
4224 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
\r
4227 El.addUnits = function(v, defaultUnit){
\r
4228 if(v === "" || v == "auto"){
\r
4231 if(v === undefined){
\r
4234 if(typeof v == "number" || !El.unitPattern.test(v)){
\r
4235 return v + (defaultUnit || 'px');
\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
4243 El.VISIBILITY = 1;
\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
4259 El.get = function(el){
\r
4261 if(!el){ return null; }
\r
4262 if(typeof el == "string"){ // element id
\r
4263 if(!(elm = document.getElementById(el))){
\r
4266 if(ex = El.cache[el]){
\r
4269 ex = El.cache[el] = new El(elm);
\r
4272 }else if(el.tagName){ // dom element
\r
4273 if(!(id = el.id)){
\r
4276 if(ex = El.cache[id]){
\r
4279 ex = El.cache[id] = new El(el);
\r
4282 }else if(el instanceof El){
\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
4289 }else if(el.isComposite){
\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
4296 var f = function(){};
\r
4297 f.prototype = El.prototype;
\r
4299 docEl.dom = document;
\r
4307 El.uncache = function(el){
\r
4308 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
\r
4310 delete El.cache[a[i].id || a[i]];
\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
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
4329 // dom node is null, definitely garbage
\r
4330 // -------------------------------------------------------
\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
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
4350 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
\r
4352 var flyFn = function(){};
\r
4353 flyFn.prototype = El.prototype;
\r
4354 var _cls = new flyFn();
\r
4356 // dom is optional
\r
4357 El.Flyweight = function(dom){
\r
4361 El.Flyweight.prototype = _cls;
\r
4362 El.Flyweight.prototype.isFlyweight = true;
\r
4364 El._flyweights = {};
\r
4366 El.fly = function(el, named){
\r
4367 named = named || '_global';
\r
4368 el = Ext.getDom(el);
\r
4372 if(!El._flyweights[named]){
\r
4373 El._flyweights[named] = new El.Flyweight();
\r
4375 El._flyweights[named].dom = el;
\r
4376 return El._flyweights[named];
\r
4384 // speedy lookup for elements never to box adjust
\r
4385 var noBoxAdjust = Ext.isStrict ? {
\r
4388 input:1, select:1, textarea:1
\r
4390 if(Ext.isIE || Ext.isGecko){
\r
4391 noBoxAdjust['button'] = 1;
\r
4395 Ext.EventManager.on(window, 'unload', function(){
\r
4397 delete El._flyweights;
\r
4401 //Notifies Element that fx methods are available
\r
4402 Ext.enableFx = true;
\r
4407 slideIn : function(anchor, o){
\r
4408 var el = this.getFxEl();
\r
4411 el.queueFx(o, function(){
\r
4413 anchor = anchor || "t";
\r
4415 // fix display to visibility
\r
4416 this.fixDisplay();
\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
4425 var wrap = this.fxWrap(r.pos, o, "hidden");
\r
4427 var st = this.dom.style;
\r
4428 st.visibility = "visible";
\r
4429 st.position = "absolute";
\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
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
4441 switch(anchor.toLowerCase()){
\r
4443 wrap.setSize(b.width, 0);
\r
4444 st.left = st.bottom = "0";
\r
4448 wrap.setSize(0, b.height);
\r
4449 st.right = st.top = "0";
\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
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
4465 wrap.setSize(0, 0);
\r
4466 st.right = st.bottom = "0";
\r
4467 a = {width: bw, height: bh};
\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
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
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
4488 this.dom.style.visibility = "visible";
\r
4491 arguments.callee.anim = wrap.fxanim(a,
\r
4495 'easeOut', after);
\r
4501 slideOut : function(anchor, o){
\r
4502 var el = this.getFxEl();
\r
4505 el.queueFx(o, function(){
\r
4507 anchor = anchor || "t";
\r
4509 // restore values after effect
\r
4510 var r = this.getFxRestore();
\r
4512 var b = this.getBox();
\r
4513 // fixed size for slide
\r
4517 var wrap = this.fxWrap(r.pos, o, "visible");
\r
4519 var st = this.dom.style;
\r
4520 st.visibility = "visible";
\r
4521 st.position = "absolute";
\r
4525 var after = function(){
\r
4527 el.setDisplayed(false);
\r
4532 el.fxUnwrap(wrap, r.pos, o);
\r
4534 st.width = r.width;
\r
4535 st.height = r.height;
\r
4540 var a, zero = {to: 0};
\r
4541 switch(anchor.toLowerCase()){
\r
4543 st.left = st.bottom = "0";
\r
4544 a = {height: zero};
\r
4547 st.right = st.top = "0";
\r
4548 a = {width: zero};
\r
4551 st.left = st.top = "0";
\r
4552 a = {width: zero, points: {to:[b.right, b.y]}};
\r
4555 st.left = st.top = "0";
\r
4556 a = {height: zero, points: {to:[b.x, b.bottom]}};
\r
4559 st.right = st.bottom = "0";
\r
4560 a = {width: zero, height: zero};
\r
4563 st.right = st.top = "0";
\r
4564 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
\r
4567 st.left = st.top = "0";
\r
4568 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
\r
4571 st.left = st.bottom = "0";
\r
4572 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
\r
4576 arguments.callee.anim = wrap.fxanim(a,
\r
4580 "easeOut", after);
\r
4586 puff : function(o){
\r
4587 var el = this.getFxEl();
\r
4590 el.queueFx(o, function(){
\r
4591 this.clearOpacity();
\r
4594 // restore values after effect
\r
4595 var r = this.getFxRestore();
\r
4596 var st = this.dom.style;
\r
4598 var after = function(){
\r
4600 el.setDisplayed(false);
\r
4605 el.clearOpacity();
\r
4607 el.setPositioning(r.pos);
\r
4608 st.width = r.width;
\r
4609 st.height = r.height;
\r
4614 var width = this.getWidth();
\r
4615 var height = this.getHeight();
\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
4627 "easeOut", after);
\r
4633 switchOff : function(o){
\r
4634 var el = this.getFxEl();
\r
4637 el.queueFx(o, function(){
\r
4638 this.clearOpacity();
\r
4641 // restore values after effect
\r
4642 var r = this.getFxRestore();
\r
4643 var st = this.dom.style;
\r
4645 var after = function(){
\r
4647 el.setDisplayed(false);
\r
4652 el.clearOpacity();
\r
4653 el.setPositioning(r.pos);
\r
4654 st.width = r.width;
\r
4655 st.height = r.height;
\r
4660 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
\r
4661 this.clearOpacity();
\r
4665 points:{by:[0, this.getHeight() * .5]}
\r
4666 }, o, 'motion', 0.3, 'easeIn', after);
\r
4667 }).defer(100, this);
\r
4674 highlight : function(color, o){
\r
4675 var el = this.getFxEl();
\r
4678 el.queueFx(o, function(){
\r
4679 color = color || "ffff9c";
\r
4680 var attr = o.attr || "backgroundColor";
\r
4682 this.clearOpacity();
\r
4685 var origColor = this.getColor(attr);
\r
4686 var restoreColor = this.dom.style[attr];
\r
4687 var endColor = (o.endColor || origColor) || "ffffff";
\r
4689 var after = function(){
\r
4690 el.dom.style[attr] = restoreColor;
\r
4695 a[attr] = {from: color, to: endColor};
\r
4696 arguments.callee.anim = this.fxanim(a,
\r
4706 frame : function(color, count, o){
\r
4707 var el = this.getFxEl();
\r
4710 el.queueFx(o, function(){
\r
4711 color = color || "#C3DAF9";
\r
4712 if(color.length == 6){
\r
4713 color = "#" + color;
\r
4715 count = count || 1;
\r
4716 var duration = o.duration || 1;
\r
4719 var b = this.getBox();
\r
4720 var animFn = function(){
\r
4721 var proxy = Ext.getBody().createChild({
\r
4723 visbility:"hidden",
\r
4724 position:"absolute",
\r
4725 "z-index":"35000", // yee haw
\r
4726 border:"0px solid " + color
\r
4729 var scale = Ext.isBorderBox ? 2 : 1;
\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
4746 animFn.call(this);
\r
4752 pause : function(seconds){
\r
4753 var el = this.getFxEl();
\r
4756 el.queueFx(o, function(){
\r
4757 setTimeout(function(){
\r
4759 }, seconds * 1000);
\r
4765 fadeIn : function(o){
\r
4766 var el = this.getFxEl();
\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
4776 this.clearOpacity();
\r
4785 fadeOut : function(o){
\r
4786 var el = this.getFxEl();
\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
4793 if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){
\r
4794 this.dom.style.display = "none";
\r
4796 this.dom.style.visibility = "hidden";
\r
4798 this.clearOpacity();
\r
4807 scale : function(w, h, o){
\r
4808 this.shift(Ext.apply({}, o, {
\r
4816 shift : function(o){
\r
4817 var el = this.getFxEl();
\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
4824 if(h !== undefined){
\r
4825 a.height = {to: this.adjustHeight(h)};
\r
4827 if(o.left !== undefined){
\r
4828 a.left = {to: o.left};
\r
4830 if(o.top !== undefined){
\r
4831 a.top = {to: o.top};
\r
4833 if(o.right !== undefined){
\r
4834 a.right = {to: o.right};
\r
4836 if(o.bottom !== undefined){
\r
4837 a.bottom = {to: o.bottom};
\r
4839 if(x !== undefined || y !== undefined){
\r
4841 x !== undefined ? x : this.getX(),
\r
4842 y !== undefined ? y : this.getY()
\r
4845 if(op !== undefined){
\r
4846 a.opacity = {to: op};
\r
4848 if(o.xy !== undefined){
\r
4849 a.points = {to: o.xy};
\r
4851 arguments.callee.anim = this.fxanim(a,
\r
4852 o, 'motion', .35, "easeOut", function(){
\r
4860 ghost : function(anchor, o){
\r
4861 var el = this.getFxEl();
\r
4864 el.queueFx(o, function(){
\r
4865 anchor = anchor || "b";
\r
4867 // restore values after effect
\r
4868 var r = this.getFxRestore();
\r
4869 var w = this.getWidth(),
\r
4870 h = this.getHeight();
\r
4872 var st = this.dom.style;
\r
4874 var after = function(){
\r
4876 el.setDisplayed(false);
\r
4881 el.clearOpacity();
\r
4882 el.setPositioning(r.pos);
\r
4883 st.width = r.width;
\r
4884 st.height = r.height;
\r
4889 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
\r
4890 switch(anchor.toLowerCase()){
\r
4917 arguments.callee.anim = this.fxanim(a,
\r
4921 "easeOut", after);
\r
4927 syncFx : function(){
\r
4928 this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
\r
4930 concurrent : true,
\r
4937 sequenceFx : function(){
\r
4938 this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
\r
4940 concurrent : false,
\r
4947 nextFx : function(){
\r
4948 var ef = this.fxQueue[0];
\r
4955 hasActiveFx : function(){
\r
4956 return this.fxQueue && this.fxQueue[0];
\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
4972 beforeFx : function(o){
\r
4973 if(this.hasActiveFx() && !o.concurrent){
\r
4984 hasFxBlock : function(){
\r
4985 var q = this.fxQueue;
\r
4986 return q && q[0] && q[0].block;
\r
4990 queueFx : function(o, fn){
\r
4991 if(!this.fxQueue){
\r
4992 this.fxQueue = [];
\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
5011 fxWrap : function(pos, o, vis){
\r
5013 if(!o.wrap || !(wrap = Ext.get(o.wrap))){
\r
5015 if(o.fixPosition){
\r
5016 wrapXY = this.getXY();
\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
5025 this.clearPositioning('auto');
\r
5027 wrap.dom.appendChild(this.dom);
\r
5029 wrap.setXY(wrapXY);
\r
5036 fxUnwrap : function(wrap, pos, o){
\r
5037 this.clearPositioning();
\r
5038 this.setPositioning(pos);
\r
5040 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
\r
5046 getFxRestore : function(){
\r
5047 var st = this.dom.style;
\r
5048 return {pos: this.getPositioning(), width: st.width, height : st.height};
\r
5052 afterFx : function(o){
\r
5054 this.applyStyles(o.afterStyle);
\r
5057 this.addClass(o.afterCls);
\r
5059 if(o.remove === true){
\r
5062 Ext.callback(o.callback, o.scope, [this]);
\r
5063 if(!o.concurrent){
\r
5064 this.fxQueue.shift();
\r
5070 getFxEl : function(){ // support for composite element fx
\r
5071 return Ext.get(this.dom);
\r
5075 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
\r
5076 animType = animType || 'run';
\r
5078 var anim = Ext.lib.Anim[animType](
\r
5080 (opt.duration || defaultDur) || .35,
\r
5081 (opt.easing || defaultEase) || 'easeOut',
\r
5083 Ext.callback(cb, this);
\r
5092 // backwords compat
\r
5093 Ext.Fx.resize = Ext.Fx.scale;
\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
5100 Ext.CompositeElement = function(els){
\r
5101 this.elements = [];
\r
5102 this.addElements(els);
\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
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
5120 fill : function(els){
\r
5121 this.elements = [];
\r
5127 filter : function(selector){
\r
5129 this.each(function(el){
\r
5130 if(el.is(selector)){
\r
5131 els[els.length] = el.dom;
\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
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
5152 this.addElements([els]);
\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
5168 item : function(index){
\r
5169 return this.elements[index] || null;
\r
5173 first : function(){
\r
5174 return this.item(0);
\r
5178 last : function(){
\r
5179 return this.item(this.elements.length-1);
\r
5183 getCount : function(){
\r
5184 return this.elements.length;
\r
5188 contains : function(el){
\r
5189 return this.indexOf(el) !== -1;
\r
5193 indexOf : function(el){
\r
5194 return this.elements.indexOf(Ext.get(el));
\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
5206 var index = typeof el == 'number' ? el : this.indexOf(el);
\r
5207 if(index !== -1 && this.elements[index]){
\r
5209 var d = this.elements[index];
\r
5213 Ext.removeNode(d);
\r
5216 this.elements.splice(index, 1);
\r
5222 replaceElement : function(el, replacement, domReplace){
\r
5223 var index = typeof el == 'number' ? el : this.indexOf(el);
\r
5226 this.elements[index].replaceWith(replacement);
\r
5228 this.elements.splice(index, 1, Ext.get(replacement))
\r
5235 clear : function(){
\r
5236 this.elements = [];
\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
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
5255 Ext.CompositeElementLite = function(els){
\r
5256 Ext.CompositeElementLite.superclass.constructor.call(this, els);
\r
5257 this.el = new Ext.Element.Flyweight();
\r
5259 Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {
\r
5260 addElements : function(els){
\r
5262 if(Ext.isArray(els)){
\r
5263 this.elements = this.elements.concat(els);
\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
5274 invoke : function(fn, args){
\r
5275 var els = this.elements;
\r
5277 for(var i = 0, len = els.length; i < len; i++) {
\r
5279 Ext.Element.prototype[fn].apply(el, args);
\r
5284 item : function(index){
\r
5285 if(!this.elements[index]){
\r
5288 this.el.dom = this.elements[index];
\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
5302 each : function(fn, scope){
\r
5303 var els = this.elements;
\r
5305 for(var i = 0, len = els.length; i < len; i++){
\r
5307 if(fn.call(scope || el, el, this, i) === false){
\r
5314 indexOf : function(el){
\r
5315 return this.elements.indexOf(Ext.getDom(el));
\r
5318 replaceElement : function(el, replacement, domReplace){
\r
5319 var index = typeof el == 'number' ? el : this.indexOf(el);
\r
5321 replacement = Ext.getDom(replacement);
\r
5323 var d = this.elements[index];
\r
5324 d.parentNode.insertBefore(replacement, d);
\r
5325 Ext.removeNode(d);
\r
5327 this.elements.splice(index, 1, replacement);
\r
5332 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
\r
5334 Ext.Element.selectorFunction = Ext.DomQuery.select;
\r
5337 Ext.Element.select = function(selector, unique, root){
\r
5339 if(typeof selector == "string"){
\r
5340 els = Ext.Element.selectorFunction(selector, root);
\r
5341 }else if(selector.length !== undefined){
\r
5344 throw "Invalid selector";
\r
5346 if(unique === true){
\r
5347 return new Ext.CompositeElement(els);
\r
5349 return new Ext.CompositeElementLite(els);
\r
5353 Ext.select = Ext.Element.select;
\r
5355 Ext.data.Connection = function(config){
\r
5356 Ext.apply(this, config);
\r
5361 "requestcomplete",
\r
5363 "requestexception"
\r
5365 Ext.data.Connection.superclass.constructor.call(this);
\r
5368 Ext.extend(Ext.data.Connection, Ext.util.Observable, {
\r
5379 disableCaching: true,
\r
5382 disableCachingParam: '_dc',
\r
5386 request : function(o){
\r
5387 if(this.fireEvent("beforerequest", this, o) !== false){
\r
5390 if(typeof p == "function"){
\r
5391 p = p.call(o.scope||window, o);
\r
5393 if(typeof p == "object"){
\r
5394 p = Ext.urlEncode(p);
\r
5396 if(this.extraParams){
\r
5397 var extras = Ext.urlEncode(this.extraParams);
\r
5398 p = p ? (p + '&' + extras) : extras;
\r
5401 var url = o.url || this.url;
\r
5402 if(typeof url == 'function'){
\r
5403 url = url.call(o.scope||window, o);
\r
5407 var form = Ext.getDom(o.form);
\r
5408 url = url || form.action;
\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
5414 var f = Ext.lib.Ajax.serializeForm(form);
\r
5415 p = p ? (p + '&' + f) : f;
\r
5418 var hs = o.headers;
\r
5419 if(this.defaultHeaders){
\r
5420 hs = Ext.apply(hs || {}, this.defaultHeaders);
\r
5427 success: this.handleResponse,
\r
5428 failure: this.handleFailure,
\r
5430 argument: {options: o},
\r
5431 timeout : o.timeout || this.timeout
\r
5434 var method = o.method||this.method||((p || o.xmlData || o.jsonData) ? "POST" : "GET");
\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
5441 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
\r
5445 }else if(this.autoAbort !== false){
\r
5448 if((method == 'GET' || o.xmlData || o.jsonData) && p){
\r
5449 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
\r
5452 this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
\r
5453 return this.transId;
\r
5455 Ext.callback(o.callback, o.scope, [o, null, null]);
\r
5461 isLoading : function(transId){
\r
5463 return Ext.lib.Ajax.isCallInProgress(transId);
\r
5465 return this.transId ? true : false;
\r
5470 abort : function(transId){
\r
5471 if(transId || this.isLoading()){
\r
5472 Ext.lib.Ajax.abort(transId || this.transId);
\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
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
5497 doFormUpload : function(o, ps, url){
\r
5498 var id = Ext.id();
\r
5499 var frame = document.createElement('iframe');
\r
5502 frame.className = 'x-hidden';
\r
5504 frame.src = Ext.SSL_SECURE_URL;
\r
5506 document.body.appendChild(frame);
\r
5509 document.frames[id].name = id;
\r
5512 var form = Ext.getDom(o.form);
\r
5514 form.method = 'POST';
\r
5515 form.enctype = form.encoding = 'multipart/form-data';
\r
5517 form.action = url;
\r
5521 if(ps){ // add dynamic params
\r
5523 ps = Ext.urlDecode(ps, false);
\r
5525 if(ps.hasOwnProperty(k)){
\r
5526 hd = document.createElement('input');
\r
5527 hd.type = 'hidden';
\r
5530 form.appendChild(hd);
\r
5537 var r = { // bogus response object
\r
5538 responseText : '',
\r
5539 responseXML : null
\r
5542 r.argument = o ? o.argument : null;
\r
5547 doc = frame.contentWindow.document;
\r
5549 doc = (frame.contentDocument || window.frames[id].document);
\r
5551 if(doc && doc.body){
\r
5552 r.responseText = doc.body.innerHTML;
\r
5554 if(doc && doc.XMLDocument){
\r
5555 r.responseXML = doc.XMLDocument;
\r
5557 r.responseXML = doc;
\r
5564 Ext.EventManager.removeListener(frame, 'load', cb, this);
\r
5566 this.fireEvent("requestcomplete", this, r, o);
\r
5568 Ext.callback(o.success, o.scope, [r, o]);
\r
5569 Ext.callback(o.callback, o.scope, [o, true, r]);
\r
5571 setTimeout(function(){Ext.removeNode(frame);}, 100);
\r
5574 Ext.EventManager.on(frame, 'load', cb, this);
\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
5586 Ext.Ajax = new Ext.data.Connection({
\r
5604 autoAbort : false,
\r
5607 serializeForm : function(form){
\r
5608 return Ext.lib.Ajax.serializeForm(form);
\r
5612 Ext.Updater = Ext.extend(Ext.util.Observable, {
\r
5613 constructor: function(el, forceNew){
\r
5615 if(!forceNew && el.updateManager){
\r
5616 return el.updateManager;
\r
5621 this.defaultUrl = null;
\r
5631 var d = Ext.Updater.defaults;
\r
5633 this.sslBlankUrl = d.sslBlankUrl;
\r
5635 this.disableCaching = d.disableCaching;
\r
5637 this.indicatorText = d.indicatorText;
\r
5639 this.showLoadIndicator = d.showLoadIndicator;
\r
5641 this.timeout = d.timeout;
\r
5643 this.loadScripts = d.loadScripts;
\r
5645 this.transaction = null;
\r
5647 this.refreshDelegate = this.refresh.createDelegate(this);
\r
5649 this.updateDelegate = this.update.createDelegate(this);
\r
5651 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
\r
5653 if(!this.renderer){
\r
5655 this.renderer = this.getDefaultRenderer();
\r
5657 Ext.Updater.superclass.constructor.call(this);
\r
5660 getDefaultRenderer: function() {
\r
5661 return new Ext.Updater.BasicRenderer();
\r
5664 getEl : function(){
\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
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
5684 this.showLoading();
\r
5687 this.defaultUrl = url;
\r
5689 if(typeof url == "function"){
\r
5690 url = url.call(this);
\r
5693 var o = Ext.apply({}, {
\r
5695 params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,
\r
5696 success: this.processSuccess,
\r
5697 failure: this.processFailure,
\r
5699 callback: undefined,
\r
5700 timeout: (this.timeout*1000),
\r
5701 disableCaching: this.disableCaching,
\r
5706 "callback": callback,
\r
5707 "scope": callerScope || window,
\r
5712 this.transaction = Ext.Ajax.request(o);
\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
5722 form = Ext.getDom(form)
\r
5723 this.transaction = Ext.Ajax.request({
\r
5726 success: this.processSuccess,
\r
5727 failure: this.processFailure,
\r
5729 timeout: (this.timeout*1000),
\r
5733 "callback": callback,
\r
5737 this.showLoading.defer(1, this);
\r
5742 refresh : function(callback){
\r
5743 if(this.defaultUrl == null){
\r
5746 this.update(this.defaultUrl, null, callback, true);
\r
5750 startAutoRefresh : function(interval, url, params, callback, refreshNow){
\r
5752 this.update(url || this.defaultUrl, params, callback, true);
\r
5754 if(this.autoRefreshProcId){
\r
5755 clearInterval(this.autoRefreshProcId);
\r
5757 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
\r
5761 stopAutoRefresh : function(){
\r
5762 if(this.autoRefreshProcId){
\r
5763 clearInterval(this.autoRefreshProcId);
\r
5764 delete this.autoRefreshProcId;
\r
5769 isAutoRefreshing : function(){
\r
5770 return this.autoRefreshProcId ? true : false;
\r
5774 showLoading : function(){
\r
5775 if(this.showLoadIndicator){
\r
5776 this.el.update(this.indicatorText);
\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
5788 if(this.loadScripts){
\r
5789 this.renderer.render(this.el, response, this,
\r
5790 this.updateComplete.createDelegate(this, [response]));
\r
5792 this.renderer.render(this.el, response, this);
\r
5793 this.updateComplete(response);
\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
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
5815 setRenderer : function(renderer){
\r
5816 this.renderer = renderer;
\r
5820 getRenderer : function(){
\r
5821 return this.renderer;
\r
5825 setDefaultUrl : function(defaultUrl){
\r
5826 this.defaultUrl = defaultUrl;
\r
5830 abort : function(){
\r
5831 if(this.transaction){
\r
5832 Ext.Ajax.abort(this.transaction);
\r
5837 isUpdating : function(){
\r
5838 if(this.transaction){
\r
5839 return Ext.Ajax.isLoading(this.transaction);
\r
5846 Ext.Updater.defaults = {
\r
5850 loadScripts : false,
\r
5852 sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false"),
\r
5854 disableCaching : false,
\r
5856 showLoadIndicator : true,
\r
5858 indicatorText : '<div class="loading-indicator">Loading...</div>'
\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
5868 Ext.Updater.BasicRenderer = function(){};
\r
5870 Ext.Updater.BasicRenderer.prototype = {
\r
5872 render : function(el, response, updateManager, callback){
\r
5873 el.update(response.responseText, updateManager.loadScripts, callback);
\r
5877 Ext.UpdateManager = Ext.Updater;
\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
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
5902 p = Ext.type(p) == 'function'? p() : p;
\r
5903 Date.parseCodes[character] = p; // reassign function result to prevent repeated execution
\r
5906 return p? Ext.applyIf({
\r
5907 c: p.c? xf(p.c, currentGroup || "{0}") : p.c
\r
5911 s:Ext.escapeRe(character) // treat unrecognised characters as literals
\r
5915 // private shorthand for Date.formatCodeToRegex since we'll be using it fairly often
\r
5916 var $f = Date.formatCodeToRegex;
\r
5920 parseFunctions: {count:0},
\r
5922 formatFunctions: {count:0},
\r
5923 daysInMonth : [31,28,31,30,31,30,31,31,30,31,30,31],
\r
5991 getShortMonthName : function(month) {
\r
5992 return Date.monthNames[month].substring(0, 3);
\r
5996 getShortDayName : function(day) {
\r
5997 return Date.dayNames[day].substring(0, 3);
\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
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
6044 return code.join(" + ");
\r
6047 U: "Math.round(this.getTime() / 1000)"
\r
6051 parseDate : function(input, format) {
\r
6052 var p = Date.parseFunctions;
\r
6053 if (p[format] == null) {
\r
6054 Date.createParser(format);
\r
6056 var func = p[format];
\r
6057 return Date[func](input);
\r
6061 getFormatCode : function(character) {
\r
6062 var f = Date.formatCodes[character];
\r
6065 f = Ext.type(f) == 'function'? f() : f;
\r
6066 Date.formatCodes[character] = f; // reassign function result to prevent repeated execution
\r
6069 // note: unknown characters are treated as literals
\r
6070 return f || ("'" + String.escape(character) + "'");
\r
6074 createNewFormat : function(format) {
\r
6075 var funcName = "format" + Date.formatFunctions.count++,
\r
6076 code = "Date.prototype." + funcName + " = function(){return ",
\r
6080 Date.formatFunctions[format] = funcName;
\r
6082 for (var i = 0; i < format.length; ++i) {
\r
6083 ch = format.charAt(i);
\r
6084 if (!special && ch == "\\") {
\r
6087 else if (special) {
\r
6089 code += "'" + String.escape(ch) + "' + ";
\r
6092 code += Date.getFormatCode(ch) + " + ";
\r
6095 eval(code.substring(0, code.length - 3) + ";}");
\r
6099 createParser : function() {
\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
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
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
6135 return function(format) {
\r
6136 var funcName = "parse" + Date.parseFunctions.count++,
\r
6137 regexNum = Date.parseRegexes.length,
\r
6144 Date.parseFunctions[format] = funcName;
\r
6146 for (var i = 0; i < format.length; ++i) {
\r
6147 ch = format.charAt(i);
\r
6148 if (!special && ch == "\\") {
\r
6151 else if (special) {
\r
6153 regex += String.escape(ch);
\r
6156 var obj = $f(ch, currentGroup);
\r
6157 currentGroup += obj.g;
\r
6159 if (obj.g && obj.c) {
\r
6165 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
\r
6166 eval(xf(code, funcName, regexNum, calc));
\r
6175 c:"d = parseInt(results[{0}], 10);\n",
\r
6176 s:"(\\d{2})" // day of month with leading zeroes (01 - 31)
\r
6180 c:"d = parseInt(results[{0}], 10);\n",
\r
6181 s:"(\\d{1,2})" // day of month without leading zeroes (1 - 31)
\r
6184 for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); // get localised short day names
\r
6188 s:"(?:" + a.join("|") +")"
\r
6195 s:"(?:" + Date.dayNames.join("|") + ")"
\r
6201 s:"[1-7]" // ISO-8601 day number (1 (monday) - 7 (sunday))
\r
6206 s:"(?:st|nd|rd|th)"
\r
6211 s:"[0-6]" // javascript day number (0 (sunday) - 6 (saturday))
\r
6216 s:"(?:\\d{1,3})" // day of the year (0 - 364 (365 in leap years))
\r
6221 s:"(?:\\d{2})" // ISO-8601 week number (with leading zero)
\r
6226 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", // get localised month number
\r
6227 s:"(" + Date.monthNames.join("|") + ")"
\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
6238 c:"m = parseInt(results[{0}], 10) - 1;\n",
\r
6239 s:"(\\d{2})" // month number with leading zeros (01 - 12)
\r
6243 c:"m = parseInt(results[{0}], 10) - 1;\n",
\r
6244 s:"(\\d{1,2})" // month number without leading zeros (1 - 12)
\r
6249 s:"(?:\\d{2})" // no. of days in the month (28 - 31)
\r
6261 c:"y = parseInt(results[{0}], 10);\n",
\r
6262 s:"(\\d{4})" // 4-digit year
\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
6272 c:"if (results[{0}] == 'am') {\n"
\r
6273 + "if (h == 12) { h = 0; }\n"
\r
6274 + "} else { if (h < 12) { h += 12; }}",
\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
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
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
6302 c:"i = parseInt(results[{0}], 10);\n",
\r
6303 s:"(\\d{2})" // minutes with leading zeros (00 - 59)
\r
6307 c:"s = parseInt(results[{0}], 10);\n",
\r
6308 s:"(\\d{2})" // seconds with leading zeros (00 - 59)
\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
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
6324 s: "([+\-]\\d{4})" // GMT offset in hrs and mins
\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
6335 s: "([+\-]\\d{2}:\\d{2})" // GMT offset in hrs and mins (with colon separator)
\r
6340 s:"[A-Z]{1,4}" // timezone abbrev. may be between 1 - 4 chars
\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
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
6367 for (var i = 0, l = arr.length; i < l; ++i) {
\r
6368 calc.push(arr[i].c);
\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
6381 c:"u = parseInt(results[{0}], 10);\n",
\r
6382 s:"(-?\\d+)" // leading minus sign indicates seconds before UNIX epoch
\r
6389 Ext.apply(Date.prototype, {
\r
6391 dateFormat : function(format) {
\r
6392 if (Date.formatFunctions[format] == null) {
\r
6393 Date.createNewFormat(format);
\r
6395 var func = Date.formatFunctions[format];
\r
6396 return this[func]();
\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
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
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
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
6425 getDayOfYear : function() {
\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
6431 return num + this.getDate() - 1;
\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
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
6445 return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
\r
6450 isLeapYear : function() {
\r
6451 var year = this.getFullYear();
\r
6452 return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
\r
6456 getFirstDayOfMonth : function() {
\r
6457 var day = (this.getDay() - (this.getDate() - 1)) % 7;
\r
6458 return (day < 0) ? (day + 7) : day;
\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
6469 getFirstDateOfMonth : function() {
\r
6470 return new Date(this.getFullYear(), this.getMonth(), 1);
\r
6474 getLastDateOfMonth : function() {
\r
6475 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
\r
6479 getDaysInMonth : function() {
\r
6480 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
\r
6481 return Date.daysInMonth[this.getMonth()];
\r
6485 getSuffix : function() {
\r
6486 switch (this.getDate()) {
\r
6503 clone : function() {
\r
6504 return new Date(this.getTime());
\r
6508 clearTime : function(clone){
\r
6510 return this.clone().clearTime();
\r
6513 this.setMinutes(0);
\r
6514 this.setSeconds(0);
\r
6515 this.setMilliseconds(0);
\r
6520 add : function(interval, value){
\r
6521 var d = this.clone();
\r
6522 if (!interval || value === 0) return d;
\r
6524 switch(interval.toLowerCase()){
\r
6526 d.setMilliseconds(this.getMilliseconds() + value);
\r
6529 d.setSeconds(this.getSeconds() + value);
\r
6532 d.setMinutes(this.getMinutes() + value);
\r
6535 d.setHours(this.getHours() + value);
\r
6538 d.setDate(this.getDate() + value);
\r
6541 var day = this.getDate();
\r
6543 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
\r
6546 d.setMonth(this.getMonth() + value);
\r
6549 d.setFullYear(this.getFullYear() + value);
\r
6556 between : function(start, end){
\r
6557 var t = this.getTime();
\r
6558 return start.getTime() <= t && t <= end.getTime();
\r
6564 Date.prototype.format = Date.prototype.dateFormat;
\r
6568 // safari setMonth is broken
\r
6570 Date.brokenSetMonth = Date.prototype.setMonth;
\r
6571 Date.prototype.setMonth = function(num){
\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
6579 return Date.brokenSetMonth.apply(this, arguments);
\r
6584 Ext.util.DelayedTask = function(fn, scope, args){
\r
6585 var id = null, d, t;
\r
6587 var call = function(){
\r
6588 var now = new Date().getTime();
\r
6590 clearInterval(id);
\r
6592 fn.apply(scope, args || []);
\r
6596 this.delay = function(delay, newFn, newScope, newArgs){
\r
6597 if(id && delay != d){
\r
6601 t = new Date().getTime();
\r
6603 scope = newScope || scope;
\r
6604 args = newArgs || args;
\r
6606 id = setInterval(call, d);
\r
6611 this.cancel = function(){
\r
6613 clearInterval(id);
\r
6619 Ext.util.TaskRunner = function(interval){
\r
6620 interval = interval || 10;
\r
6621 var tasks = [], removeQueue = [];
\r
6623 var running = false;
\r
6626 var stopThread = function(){
\r
6628 clearInterval(id);
\r
6633 var startThread = function(){
\r
6636 id = setInterval(runTasks, interval);
\r
6641 var removeTask = function(t){
\r
6642 removeQueue.push(t);
\r
6644 t.onStop.apply(t.scope || t);
\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
6655 if(tasks.length < 1){
\r
6660 var now = new Date().getTime();
\r
6661 for(var i = 0, len = tasks.length; i < len; ++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
6672 if(t.duration && t.duration <= (now - t.taskStartTime)){
\r
6679 this.start = function(task){
\r
6681 task.taskStartTime = new Date().getTime();
\r
6682 task.taskRunTime = 0;
\r
6683 task.taskRunCount = 0;
\r
6689 this.stop = function(task){
\r
6695 this.stopAll = function(){
\r
6697 for(var i = 0, len = tasks.length; i < len; i++){
\r
6698 if(tasks[i].onStop){
\r
6699 tasks[i].onStop();
\r
6708 Ext.TaskMgr = new Ext.util.TaskRunner();
\r
6710 Ext.util.MixedCollection = function(allowFunctions, keyFn){
\r
6726 this.allowFunctions = allowFunctions === true;
\r
6728 this.getKey = keyFn;
\r
6730 Ext.util.MixedCollection.superclass.constructor.call(this);
\r
6733 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
\r
6734 allowFunctions : false,
\r
6737 add : function(key, o){
\r
6738 if(arguments.length == 1){
\r
6740 key = this.getKey(o);
\r
6742 if(typeof key == "undefined" || key === null){
\r
6744 this.items.push(o);
\r
6745 this.keys.push(null);
\r
6747 var old = this.map[key];
\r
6749 return this.replace(key, o);
\r
6752 this.items.push(o);
\r
6753 this.map[key] = o;
\r
6754 this.keys.push(key);
\r
6756 this.fireEvent("add", this.length-1, o, key);
\r
6761 getKey : function(o){
\r
6766 replace : function(key, o){
\r
6767 if(arguments.length == 1){
\r
6769 key = this.getKey(o);
\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
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
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
6790 for(var key in objs){
\r
6791 if(this.allowFunctions || typeof objs[key] != "function"){
\r
6792 this.add(key, objs[key]);
\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
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
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
6826 insert : function(index, key, o){
\r
6827 if(arguments.length == 2){
\r
6829 key = this.getKey(o);
\r
6831 if(index >= this.length){
\r
6832 return this.add(key, o);
\r
6835 this.items.splice(index, 0, o);
\r
6836 if(typeof key != "undefined" && key != null){
\r
6837 this.map[key] = o;
\r
6839 this.keys.splice(index, 0, key);
\r
6840 this.fireEvent("add", index, o, key);
\r
6845 remove : function(o){
\r
6846 return this.removeAt(this.indexOf(o));
\r
6850 removeAt : function(index){
\r
6851 if(index < this.length && index >= 0){
\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
6859 this.keys.splice(index, 1);
\r
6860 this.fireEvent("remove", o, key);
\r
6867 removeKey : function(key){
\r
6868 return this.removeAt(this.indexOfKey(key));
\r
6872 getCount : function(){
\r
6873 return this.length;
\r
6877 indexOf : function(o){
\r
6878 return this.items.indexOf(o);
\r
6882 indexOfKey : function(key){
\r
6883 return this.keys.indexOf(key);
\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
6893 itemAt : function(index){
\r
6894 return this.items[index];
\r
6898 key : function(key){
\r
6899 return this.map[key];
\r
6903 contains : function(o){
\r
6904 return this.indexOf(o) != -1;
\r
6908 containsKey : function(key){
\r
6909 return typeof this.map[key] != "undefined";
\r
6913 clear : function(){
\r
6918 this.fireEvent("clear");
\r
6922 first : function(){
\r
6923 return this.items[0];
\r
6927 last : function(){
\r
6928 return this.items[this.length-1];
\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
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
6941 c.sort(function(a, b){
\r
6942 var v = fn(a[property], b[property]) * dsc;
\r
6944 v = (a.index < b.index ? -1 : 1);
\r
6948 for(var i = 0, len = c.length; i < len; i++){
\r
6949 items[i] = c[i].value;
\r
6952 this.fireEvent("sort", this);
\r
6956 sort : function(dir, fn){
\r
6957 this._sort("value", dir, fn);
\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
6969 getRange : function(start, end){
\r
6970 var items = this.items;
\r
6971 if(items.length < 1){
\r
6974 start = start || 0;
\r
6975 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
\r
6978 for(var i = start; i <= end; i++) {
\r
6979 r[r.length] = items[i];
\r
6982 for(var i = start; i >= end; i--) {
\r
6983 r[r.length] = items[i];
\r
6990 filter : function(property, value, anyMatch, caseSensitive){
\r
6991 if(Ext.isEmpty(value, false)){
\r
6992 return this.clone();
\r
6994 value = this.createValueMatcher(value, anyMatch, caseSensitive);
\r
6995 return this.filterBy(function(o){
\r
6996 return o && value.test(o[property]);
\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
7014 findIndex : function(property, value, start, anyMatch, caseSensitive){
\r
7015 if(Ext.isEmpty(value, false)){
\r
7018 value = this.createValueMatcher(value, anyMatch, caseSensitive);
\r
7019 return this.findIndexBy(function(o){
\r
7020 return o && value.test(o[property]);
\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
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
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
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
7058 r.getKey = this.getKey;
\r
7063 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
\r
7065 Ext.util.JSON = new (function(){
\r
7066 var useHasOwn = !!{}.hasOwnProperty;
\r
7068 // crashes Safari in some instances
\r
7069 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
\r
7071 var pad = function(n) {
\r
7072 return n < 10 ? "0" + n : n;
\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
7092 c = b.charCodeAt();
\r
7094 Math.floor(c / 16).toString(16) +
\r
7095 (c % 16).toString(16);
\r
7098 return '"' + s + '"';
\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
7105 switch (typeof v) {
\r
7114 a.push(v === null ? "null" : Ext.util.JSON.encode(v));
\r
7119 return a.join("");
\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
7132 this.encode = function(o){
\r
7133 if(typeof o == "undefined" || o === 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
7146 var a = ["{"], b, i, v;
\r
7148 if(!useHasOwn || o.hasOwnProperty(i)) {
\r
7150 switch (typeof v) {
\r
7159 a.push(this.encode(i), ":",
\r
7160 v === null ? "null" : this.encode(v));
\r
7166 return a.join("");
\r
7171 this.decode = function(json){
\r
7172 return eval("(" + json + ')');
\r
7176 Ext.encode = Ext.util.JSON.encode;
\r
7178 Ext.decode = Ext.util.JSON.decode;
\r
7181 Ext.util.Format = function(){
\r
7182 var trimRe = /^\s+|\s+$/g;
\r
7185 ellipsis : function(value, len){
\r
7186 if(value && value.length > len){
\r
7187 return value.substr(0, len-3)+"...";
\r
7193 undef : function(value){
\r
7194 return value !== undefined ? value : "";
\r
7198 defaultValue : function(value, defaultValue){
\r
7199 return value !== undefined && value !== '' ? value : defaultValue;
\r
7203 htmlEncode : function(value){
\r
7204 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
\r
7208 htmlDecode : function(value){
\r
7209 return !value ? value : String(value).replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"').replace(/&/g, "&");
\r
7213 trim : function(value){
\r
7214 return String(value).replace(trimRe, "");
\r
7218 substr : function(value, start, length){
\r
7219 return String(value).substr(start, length);
\r
7223 lowercase : function(value){
\r
7224 return String(value).toLowerCase();
\r
7228 uppercase : function(value){
\r
7229 return String(value).toUpperCase();
\r
7233 capitalize : function(value){
\r
7234 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
\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
7244 return eval(fn).call(window, value);
\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
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
7261 if(v.charAt(0) == '-'){
\r
7262 return '-$' + v.substr(1);
\r
7268 date : function(v, format){
\r
7272 if(!Ext.isDate(v)){
\r
7273 v = new Date(Date.parse(v));
\r
7275 return v.dateFormat(format || "m/d/Y");
\r
7279 dateRenderer : function(format){
\r
7280 return function(v){
\r
7281 return Ext.util.Format.date(v, format);
\r
7286 stripTagsRE : /<\/?[^>]+>/gi,
\r
7289 stripTags : function(v){
\r
7290 return !v ? v : String(v).replace(this.stripTagsRE, "");
\r
7294 stripScriptsRe : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
\r
7297 stripScripts : function(v){
\r
7298 return !v ? v : String(v).replace(this.stripScriptsRe, "");
\r
7302 fileSize : function(size){
\r
7304 return size + " bytes";
\r
7305 } else if(size < 1048576) {
\r
7306 return (Math.round(((size*10) / 1024))/10) + " KB";
\r
7308 return (Math.round(((size*10) / 1048576))/10) + " MB";
\r
7312 math : function(){
\r
7314 return function(v, a){
\r
7316 fns[a] = new Function('v', 'return v ' + a + ';');
\r
7323 nl2br : function(v){
\r
7324 return v === undefined || v === null ? '' : v.replace(/\n/g, '<br/>');
\r
7329 Ext.XTemplate = function(){
\r
7330 Ext.XTemplate.superclass.constructor.apply(this, arguments);
\r
7331 var s = this.html;
\r
7333 s = ['<tpl>', s, '</tpl>'].join('');
\r
7335 var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;
\r
7337 var nameRe = /^<tpl\b[^>]*?for="(.*?)"/;
\r
7338 var ifRe = /^<tpl\b[^>]*?if="(.*?)"/;
\r
7339 var execRe = /^<tpl\b[^>]*?exec="(.*?)"/;
\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
7350 exp = m3 && m3[1] ? m3[1] : null;
\r
7352 fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return '+(Ext.util.Format.htmlDecode(exp))+'; }');
\r
7356 exp = m4 && m4[1] ? m4[1] : null;
\r
7358 exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ '+(Ext.util.Format.htmlDecode(exp))+'; }');
\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
7375 s = s.replace(m[0], '{xtpl'+ id + '}');
\r
7378 for(var i = tpls.length-1; i >= 0; --i){
\r
7379 this.compileTpl(tpls[i]);
\r
7381 this.master = tpls[tpls.length-1];
\r
7384 Ext.extend(Ext.XTemplate, Ext.Template, {
\r
7386 re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
\r
7388 codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
\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
7396 if(t.exec && t.exec.call(this, values, parent, xindex, xcount)){
\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
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
7406 return buf.join('');
\r
7408 return t.compiled.call(this, vs, parent, xindex, xcount);
\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
7423 }else if(name === '#'){
\r
7425 }else if(name.indexOf('.') != -1){
\r
7428 v = "values['" + name + "']";
\r
7431 v = '(' + v + math + ')';
\r
7433 if(format && useF){
\r
7434 args = args ? ',' + args : "";
\r
7435 if(format.substr(0, 5) != "this."){
\r
7436 format = "fm." + format + '(';
\r
7438 format = 'this.call("'+ format.substr(5) + '", ';
\r
7439 args = ", values";
\r
7442 args= ''; format = "("+v+" === undefined ? '' : ";
\r
7444 return "'"+ sep + format + v + args + ")"+sep+"'";
\r
7446 var codeFn = function(m, code){
\r
7447 return "'"+ sep +'('+code+')'+sep+"'";
\r
7451 // branched to use + in gecko and [].join() in others
\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
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
7467 applyTemplate : function(values){
\r
7468 return this.master.compiled.call(this, values, {}, 1, 1);
\r
7472 compile : function(){return this;}
\r
7480 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
\r
7483 Ext.XTemplate.from = function(el){
\r
7484 el = Ext.getDom(el);
\r
7485 return new Ext.XTemplate(el.value || el.innerHTML);
\r
7488 Ext.util.CSS = function(){
\r
7490 var doc = document;
\r
7492 var camelRe = /(-[a-z])/gi;
\r
7493 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
\r
7497 createStyleSheet : function(cssText, id){
\r
7499 var head = doc.getElementsByTagName("head")[0];
\r
7500 var rules = doc.createElement("style");
\r
7501 rules.setAttribute("type", "text/css");
\r
7503 rules.setAttribute("id", id);
\r
7506 head.appendChild(rules);
\r
7507 ss = rules.styleSheet;
\r
7508 ss.cssText = cssText;
\r
7511 rules.appendChild(doc.createTextNode(cssText));
\r
7513 rules.cssText = cssText;
\r
7515 head.appendChild(rules);
\r
7516 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
\r
7518 this.cacheStyleSheet(ss);
\r
7523 removeStyleSheet : function(id){
\r
7524 var existing = doc.getElementById(id);
\r
7526 existing.parentNode.removeChild(existing);
\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
7542 refreshCache : function(){
\r
7543 return this.getRules(true);
\r
7547 cacheStyleSheet : function(ss){
\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
7560 getRules : function(refreshCache){
\r
7561 if(rules == null || refreshCache){
\r
7563 var ds = doc.styleSheets;
\r
7564 for(var i =0, len = ds.length; i < len; i++){
\r
7566 this.cacheStyleSheet(ds[i]);
\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
7579 for(var i = 0; i < selector.length; i++){
\r
7580 if(rs[selector[i]]){
\r
7581 return rs[selector[i]];
\r
7589 updateRule : function(selector, property, value){
\r
7590 if(!Ext.isArray(selector)){
\r
7591 var rule = this.getRule(selector);
\r
7593 rule.style[property.replace(camelRe, camelFn)] = value;
\r
7597 for(var i = 0; i < selector.length; i++){
\r
7598 if(this.updateRule(selector[i], property, value)){
\r
7608 Ext.util.ClickRepeater = function(el, config)
\r
7610 this.el = Ext.get(el);
\r
7611 this.el.unselectable();
\r
7613 Ext.apply(this, config);
\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
7630 if(this.stopDefault){
\r
7636 // allow inline handler
\r
7638 this.on("click", this.handler, this.scope || this);
\r
7641 Ext.util.ClickRepeater.superclass.constructor.call(this);
\r
7644 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
\r
7647 preventDefault : true,
\r
7648 stopDefault : false,
\r
7652 destroy : function() {
\r
7653 Ext.destroy(this.el);
\r
7654 this.purgeListeners();
\r
7658 handleMouseDown : function(){
\r
7659 clearTimeout(this.timer);
\r
7661 if(this.pressClass){
\r
7662 this.el.addClass(this.pressClass);
\r
7664 this.mousedownTime = new Date();
\r
7666 Ext.getDoc().on("mouseup", this.handleMouseUp, this);
\r
7667 this.el.on("mouseout", this.handleMouseOut, this);
\r
7669 this.fireEvent("mousedown", this);
\r
7670 this.fireEvent("click", this);
\r
7672 // Do not honor delay or interval if acceleration wanted.
\r
7673 if (this.accelerate) {
\r
7676 this.timer = this.click.defer(this.delay || this.interval, this);
\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
7687 this.interval, this);
\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
7695 handleMouseOut : function(){
\r
7696 clearTimeout(this.timer);
\r
7697 if(this.pressClass){
\r
7698 this.el.removeClass(this.pressClass);
\r
7700 this.el.on("mouseover", this.handleMouseReturn, this);
\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
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
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
7732 Ext.KeyNav.prototype = {
\r
7736 defaultEventAction: "stopEvent",
\r
7738 forceKeyDown : false,
\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
7747 if(Ext.isSafari2 && h && k >= 37 && k <= 40){
\r
7753 relay : function(e){
\r
7754 var k = e.getKey();
\r
7755 var h = this.keyToHandler[k];
\r
7757 if(this.doRelay(e, this[h], h) !== true){
\r
7758 e[this.defaultEventAction]();
\r
7764 doRelay : function(e, h, hname){
\r
7765 return h.call(this.scope || this, e);
\r
7768 // possible handlers
\r
7782 // quick lookup hash
\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
7804 this.el.on("keydown", this.prepareEvent, this);
\r
7805 this.el.on("keypress", this.relay, this);
\r
7807 this.disabled = false;
\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
7817 this.el.un("keydown", this.prepareEvent, this);
\r
7818 this.el.un("keypress", this.relay, this);
\r
7820 this.disabled = true;
\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
7830 this.addBinding(config);
\r
7835 Ext.KeyMap.prototype = {
\r
7837 stopEvent : false,
\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
7847 var keyCode = config.key,
\r
7848 shift = config.shift,
\r
7849 ctrl = config.ctrl,
\r
7851 fn = config.fn || config.handler,
\r
7852 scope = config.scope;
\r
7854 if (config.stopEvent) {
\r
7855 this.stopEvent = config.stopEvent;
\r
7858 if(typeof keyCode == "string"){
\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
7866 var keyArray = Ext.isArray(keyCode);
\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
7872 for(var i = 0, len = keyCode.length; i < len; i++){
\r
7873 if(keyCode[i] == k){
\r
7874 if(this.stopEvent){
\r
7877 fn.call(scope || window, k, e);
\r
7883 if(this.stopEvent){
\r
7886 fn.call(scope || window, k, e);
\r
7891 this.bindings.push(handler);
\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
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
7926 isEnabled : function(){
\r
7927 return this.enabled;
\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
7939 disable: function(){
\r
7941 this.el.removeListener(this.eventName, this.handleKeyDown, this);
\r
7942 this.enabled = false;
\r
7947 Ext.util.TextMetrics = function(){
\r
7951 measure : function(el, text, fixedWidth){
\r
7953 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
\r
7956 shared.setFixedWidth(fixedWidth || 'auto');
\r
7957 return shared.getSize(text);
\r
7961 createInstance : function(el, fixedWidth){
\r
7962 return Ext.util.TextMetrics.Instance(el, fixedWidth);
\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
7975 ml.setWidth(fixedWidth);
\r
7980 getSize : function(text){
\r
7982 var s = ml.getSize();
\r
7988 bind : function(el){
\r
7990 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
\r
7995 setFixedWidth : function(width){
\r
7996 ml.setWidth(width);
\r
8000 getWidth : function(text){
\r
8001 ml.dom.style.width = 'auto';
\r
8002 return this.getSize(text).width;
\r
8006 getHeight : function(text){
\r
8007 return this.getSize(text).height;
\r
8011 instance.bind(bindTo);
\r
8016 // backwards compat
\r
8017 Ext.Element.measureText = Ext.util.TextMetrics.measure;
\r
8022 var Event=Ext.EventManager;
\r
8023 var Dom=Ext.lib.Dom;
\r
8026 Ext.dd.DragDrop = function(id, sGroup, config) {
\r
8028 this.init(id, sGroup, config);
\r
8032 Ext.dd.DragDrop.prototype = {
\r
8047 invalidHandleTypes: null,
\r
8050 invalidHandleIds: null,
\r
8053 invalidHandleClasses: null,
\r
8068 lock: function() { this.locked = true; },
\r
8074 unlock: function() { this.locked = false; },
\r
8086 __ygDragDrop: true,
\r
8089 constrainX: false,
\r
8092 constrainY: false,
\r
8107 maintainOffset: false,
\r
8116 primaryButtonOnly: true,
\r
8122 hasOuterHandles: false,
\r
8125 b4StartDrag: function(x, y) { },
\r
8128 startDrag: function(x, y) { },
\r
8131 b4Drag: function(e) { },
\r
8134 onDrag: function(e) { },
\r
8137 onDragEnter: function(e, id) { },
\r
8140 b4DragOver: function(e) { },
\r
8143 onDragOver: function(e, id) { },
\r
8146 b4DragOut: function(e) { },
\r
8149 onDragOut: function(e, id) { },
\r
8152 b4DragDrop: function(e) { },
\r
8155 onDragDrop: function(e, id) { },
\r
8158 onInvalidDrop: function(e) { },
\r
8161 b4EndDrag: function(e) { },
\r
8164 endDrag: function(e) { },
\r
8167 b4MouseDown: function(e) { },
\r
8170 onMouseDown: function(e) { },
\r
8173 onMouseUp: function(e) { },
\r
8176 onAvailable: function () {
\r
8180 defaultPadding : {left:0, right:0, top:0, bottom:0},
\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
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
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
8200 var topSpace = b.y - c.y;
\r
8201 var leftSpace = b.x - c.x;
\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
8208 this.setYConstraint(topSpace - (pad.top||0), //top
\r
8209 c.height - topSpace - b.height - (pad.bottom||0), //bottom
\r
8215 getEl: function() {
\r
8216 if (!this._domRef) {
\r
8217 this._domRef = Ext.getDom(this.id);
\r
8220 return this._domRef;
\r
8224 getDragEl: function() {
\r
8225 return Ext.getDom(this.dragElId);
\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
8236 initTarget: function(id, sGroup, config) {
\r
8238 // configuration attributes
\r
8239 this.config = config || {};
\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
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
8255 // add to an interaction group
\r
8256 this.addToGroup((sGroup) ? sGroup : "default");
\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
8262 // the linked element is the element that gets dragged by default
\r
8263 this.setDragElId(id);
\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
8270 this.applyConfig();
\r
8272 this.handleOnAvailable();
\r
8276 applyConfig: function() {
\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
8288 handleOnAvailable: function() {
\r
8289 this.available = true;
\r
8290 this.resetConstraints();
\r
8291 this.onAvailable();
\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
8302 this.padding = [iTop, iRight, iBot, iLeft];
\r
8307 setInitPosition: function(diffX, diffY) {
\r
8308 var el = this.getEl();
\r
8310 if (!this.DDM.verifyEl(el)) {
\r
8314 var dx = diffX || 0;
\r
8315 var dy = diffY || 0;
\r
8317 var p = Dom.getXY( el );
\r
8319 this.initPageX = p[0] - dx;
\r
8320 this.initPageY = p[1] - dy;
\r
8322 this.lastPageX = p[0];
\r
8323 this.lastPageY = p[1];
\r
8326 this.setStartPosition(p);
\r
8330 setStartPosition: function(pos) {
\r
8331 var p = pos || Dom.getXY( this.getEl() );
\r
8332 this.deltaSetXY = null;
\r
8334 this.startPageX = p[0];
\r
8335 this.startPageY = p[1];
\r
8339 addToGroup: function(sGroup) {
\r
8340 this.groups[sGroup] = true;
\r
8341 this.DDM.regDragDrop(this, sGroup);
\r
8345 removeFromGroup: function(sGroup) {
\r
8346 if (this.groups[sGroup]) {
\r
8347 delete this.groups[sGroup];
\r
8350 this.DDM.removeDDFromGroup(this, sGroup);
\r
8354 setDragElId: function(id) {
\r
8355 this.dragElId = id;
\r
8359 setHandleElId: function(id) {
\r
8360 if (typeof id !== "string") {
\r
8363 this.handleElId = id;
\r
8364 this.DDM.regHandle(this.id, id);
\r
8368 setOuterHandleElId: function(id) {
\r
8369 if (typeof id !== "string") {
\r
8372 Event.on(id, "mousedown",
\r
8373 this.handleMouseDown, this);
\r
8374 this.setHandleElId(id);
\r
8376 this.hasOuterHandles = true;
\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
8387 destroy : function(){
\r
8392 isLocked: function() {
\r
8393 return (this.DDM.isLocked() || this.locked);
\r
8397 handleMouseDown: function(e, oDD){
\r
8398 if (this.primaryButtonOnly && e.button != 0) {
\r
8402 if (this.isLocked()) {
\r
8406 this.DDM.refreshCache(this.groups);
\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
8411 if (this.clickValidator(e)) {
\r
8413 // set the initial element position
\r
8414 this.setStartPosition();
\r
8417 this.b4MouseDown(e);
\r
8418 this.onMouseDown(e);
\r
8420 this.DDM.handleMouseDown(e, this);
\r
8422 this.DDM.stopEvent(e);
\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
8438 addInvalidHandleType: function(tagName) {
\r
8439 var type = tagName.toUpperCase();
\r
8440 this.invalidHandleTypes[type] = type;
\r
8444 addInvalidHandleId: function(id) {
\r
8445 if (typeof id !== "string") {
\r
8448 this.invalidHandleIds[id] = id;
\r
8452 addInvalidHandleClass: function(cssClass) {
\r
8453 this.invalidHandleClasses.push(cssClass);
\r
8457 removeInvalidHandleType: function(tagName) {
\r
8458 var type = tagName.toUpperCase();
\r
8459 // this.invalidHandleTypes[type] = null;
\r
8460 delete this.invalidHandleTypes[type];
\r
8464 removeInvalidHandleId: function(id) {
\r
8465 if (typeof id !== "string") {
\r
8468 delete this.invalidHandleIds[id];
\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
8481 isValidHandleChild: function(node) {
\r
8484 // var n = (node.nodeName == "#text") ? node.parentNode : node;
\r
8487 nodeName = node.nodeName.toUpperCase();
\r
8489 nodeName = node.nodeName;
\r
8491 valid = valid && !this.invalidHandleTypes[nodeName];
\r
8492 valid = valid && !this.invalidHandleIds[node.id];
\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
8504 setXTicks: function(iStartX, iTickSize) {
\r
8506 this.xTickSize = iTickSize;
\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
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
8524 this.xTicks.sort(this.DDM.numericSort) ;
\r
8528 setYTicks: function(iStartY, iTickSize) {
\r
8530 this.yTickSize = iTickSize;
\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
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
8548 this.yTicks.sort(this.DDM.numericSort) ;
\r
8552 setXConstraint: function(iLeft, iRight, iTickSize) {
\r
8553 this.leftConstraint = iLeft;
\r
8554 this.rightConstraint = iRight;
\r
8556 this.minX = this.initPageX - iLeft;
\r
8557 this.maxX = this.initPageX + iRight;
\r
8558 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
\r
8560 this.constrainX = true;
\r
8564 clearConstraints: function() {
\r
8565 this.constrainX = false;
\r
8566 this.constrainY = false;
\r
8567 this.clearTicks();
\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
8579 setYConstraint: function(iUp, iDown, iTickSize) {
\r
8580 this.topConstraint = iUp;
\r
8581 this.bottomConstraint = iDown;
\r
8583 this.minY = this.initPageY - iUp;
\r
8584 this.maxY = this.initPageY + iDown;
\r
8585 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
\r
8587 this.constrainY = true;
\r
8592 resetConstraints: function() {
\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
8601 this.setInitPosition(dx, dy);
\r
8603 // This is the first time we have detected the element's position
\r
8605 this.setInitPosition();
\r
8608 if (this.constrainX) {
\r
8609 this.setXConstraint( this.leftConstraint,
\r
8610 this.rightConstraint,
\r
8614 if (this.constrainY) {
\r
8615 this.setYConstraint( this.topConstraint,
\r
8616 this.bottomConstraint,
\r
8622 getTick: function(val, 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
8628 } else if (tickArray[0] >= val) {
\r
8629 // The value is lower than the first tick, so we return the first
\r
8631 return tickArray[0];
\r
8633 for (var i=0, len=tickArray.length; i<len; ++i) {
\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
8642 // The value is larger than the last tick, so we return the last
\r
8644 return tickArray[tickArray.length - 1];
\r
8649 toString: function() {
\r
8650 return ("DragDrop " + this.id);
\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
8663 Ext.dd.DragDropMgr = function() {
\r
8665 var Event = Ext.EventManager;
\r
8676 dragCurrent: null,
\r
8688 preventDefault: true,
\r
8691 stopPropagation: true,
\r
8694 initialized: false,
\r
8700 init: function() {
\r
8701 this.initialized = true;
\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
8721 oDD[sMethod].apply(oDD, args);
\r
8727 _onLoad: function() {
\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
8741 _onResize: function(e) {
\r
8742 this._execOnAll("resetConstraints", []);
\r
8746 lock: function() { this.locked = true; },
\r
8749 unlock: function() { this.locked = false; },
\r
8752 isLocked: function() { return this.locked; },
\r
8755 locationCache: {},
\r
8761 clickPixelThresh: 3,
\r
8764 clickTimeThresh: 350,
\r
8767 dragThreshMet: false,
\r
8770 clickTimeout: null,
\r
8779 regDragDrop: function(oDD, sGroup) {
\r
8780 if (!this.initialized) { this.init(); }
\r
8782 if (!this.ids[sGroup]) {
\r
8783 this.ids[sGroup] = {};
\r
8785 this.ids[sGroup][oDD.id] = oDD;
\r
8789 removeDDFromGroup: function(oDD, sGroup) {
\r
8790 if (!this.ids[sGroup]) {
\r
8791 this.ids[sGroup] = {};
\r
8794 var obj = this.ids[sGroup];
\r
8795 if (obj && obj[oDD.id]) {
\r
8796 delete obj[oDD.id];
\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
8807 delete this.handleIds[oDD.id];
\r
8811 regHandle: function(sDDId, sHandleId) {
\r
8812 if (!this.handleIds[sDDId]) {
\r
8813 this.handleIds[sDDId] = {};
\r
8815 this.handleIds[sDDId][sHandleId] = sHandleId;
\r
8819 isDragDrop: function(id) {
\r
8820 return ( this.getDDById(id) ) ? true : false;
\r
8824 getRelated: function(p_oDD, bTargetsOnly) {
\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
8832 if (!bTargetsOnly || dd.isTarget) {
\r
8833 oDDs[oDDs.length] = dd;
\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
8854 isTypeOfDD: function (oDD) {
\r
8855 return (oDD && oDD.__ygDragDrop);
\r
8859 isHandle: function(sDDId, sHandleId) {
\r
8860 return ( this.handleIds[sDDId] &&
\r
8861 this.handleIds[sDDId][sHandleId] );
\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
8875 handleMouseDown: function(e, oDD) {
\r
8876 if(Ext.QuickTips){
\r
8877 Ext.QuickTips.disable();
\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
8885 this.currentTarget = e.getTarget();
\r
8886 this.dragCurrent = oDD;
\r
8888 var el = oDD.getEl();
\r
8890 // track start position
\r
8891 this.startX = e.getPageX();
\r
8892 this.startY = e.getPageY();
\r
8894 this.deltaX = this.startX - el.offsetLeft;
\r
8895 this.deltaY = this.startY - el.offsetTop;
\r
8897 this.dragThreshMet = false;
\r
8899 this.clickTimeout = setTimeout(
\r
8901 var DDM = Ext.dd.DDM;
\r
8902 DDM.startDrag(DDM.startX, DDM.startY);
\r
8904 this.clickTimeThresh );
\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
8914 this.dragThreshMet = true;
\r
8918 handleMouseUp: function(e) {
\r
8920 if(Ext.QuickTips){
\r
8921 Ext.QuickTips.enable();
\r
8923 if (! this.dragCurrent) {
\r
8927 clearTimeout(this.clickTimeout);
\r
8929 if (this.dragThreshMet) {
\r
8930 this.fireEvents(e, true);
\r
8936 this.stopEvent(e);
\r
8940 stopEvent: function(e){
\r
8941 if(this.stopPropagation) {
\r
8942 e.stopPropagation();
\r
8945 if (this.preventDefault) {
\r
8946 e.preventDefault();
\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
8959 this.dragCurrent.onMouseUp(e);
\r
8962 this.dragCurrent = null;
\r
8963 this.dragOvers = {};
\r
8967 handleMouseMove: function(e) {
\r
8968 if (! this.dragCurrent) {
\r
8972 // var button = e.which || e.button;
\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
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
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
8997 this.stopEvent(e);
\r
9003 fireEvents: function(e, isDrop) {
\r
9004 var dc = this.dragCurrent;
\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
9012 var pt = e.getPoint();
\r
9014 // cache the previous dragOver array
\r
9015 var oldOvers = [];
\r
9018 var overEvts = [];
\r
9019 var dropEvts = [];
\r
9020 var enterEvts = [];
\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
9026 var ddo = this.dragOvers[i];
\r
9028 if (! this.isTypeOfDD(ddo)) {
\r
9032 if (! this.isOverTarget(pt, ddo, this.mode)) {
\r
9033 outEvts.push( ddo );
\r
9036 oldOvers[i] = true;
\r
9037 delete this.dragOvers[i];
\r
9040 for (var sGroup in dc.groups) {
\r
9042 if ("string" != typeof sGroup) {
\r
9046 for (i in this.ids[sGroup]) {
\r
9047 var oDD = this.ids[sGroup][i];
\r
9048 if (! this.isTypeOfDD(oDD)) {
\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
9056 dropEvts.push( oDD );
\r
9057 // look for drag enter and drag over interactions
\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
9065 overEvts.push( oDD );
\r
9068 this.dragOvers[oDD.id] = oDD;
\r
9076 if (outEvts.length) {
\r
9077 dc.b4DragOut(e, outEvts);
\r
9078 dc.onDragOut(e, outEvts);
\r
9081 if (enterEvts.length) {
\r
9082 dc.onDragEnter(e, enterEvts);
\r
9085 if (overEvts.length) {
\r
9086 dc.b4DragOver(e, overEvts);
\r
9087 dc.onDragOver(e, overEvts);
\r
9090 if (dropEvts.length) {
\r
9091 dc.b4DragDrop(e, dropEvts);
\r
9092 dc.onDragDrop(e, dropEvts);
\r
9096 // fire dragout events
\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
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
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
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
9123 // notify about a drop that did not find a target
\r
9124 if (isDrop && !dropEvts.length) {
\r
9125 dc.onInvalidDrop(e);
\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
9136 // If there is only one item, it wins
\r
9137 //} else if (dds.length == 1) {
\r
9139 var len = dds.length;
\r
9144 // Loop through the targeted items
\r
9145 for (var i=0; i<len; ++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
9150 if (dd.cursorIsOver) {
\r
9153 // Otherwise the object with the most overlap wins
\r
9156 winner.overlap.getArea() < dd.overlap.getArea()) {
\r
9167 refreshCache: function(groups) {
\r
9168 for (var sGroup in groups) {
\r
9169 if ("string" != typeof sGroup) {
\r
9172 for (var i in this.ids[sGroup]) {
\r
9173 var oDD = this.ids[sGroup][i];
\r
9175 if (this.isTypeOfDD(oDD)) {
\r
9176 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
\r
9177 var loc = this.getLocation(oDD);
\r
9179 this.locationCache[oDD.id] = loc;
\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
9192 verifyEl: function(el) {
\r
9197 parent = el.offsetParent;
\r
9200 parent = el.offsetParent;
\r
9211 getLocation: function(oDD) {
\r
9212 if (! this.isTypeOfDD(oDD)) {
\r
9216 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
\r
9219 pos= Ext.lib.Dom.getXY(el);
\r
9227 x2 = x1 + el.offsetWidth;
\r
9229 y2 = y1 + el.offsetHeight;
\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
9236 return new Ext.lib.Region( t, r, b, l );
\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
9253 oTarget.cursorIsOver = loc.contains( pt );
\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
9266 oTarget.overlap = null;
\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
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
9280 var overlap = curRegion.intersect(loc);
\r
9283 oTarget.overlap = overlap;
\r
9284 return (intersect) ? true : oTarget.cursorIsOver;
\r
9291 _onUnload: function(e, me) {
\r
9292 Ext.dd.DragDropMgr.unregAll();
\r
9296 unregAll: function() {
\r
9298 if (this.dragCurrent) {
\r
9300 this.dragCurrent = null;
\r
9303 this._execOnAll("unreg", []);
\r
9305 for (var i in this.elementCache) {
\r
9306 delete this.elementCache[i];
\r
9309 this.elementCache = {};
\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
9327 getElement: function(id) {
\r
9328 return Ext.getDom(id);
\r
9332 getCss: function(id) {
\r
9333 var el = Ext.getDom(id);
\r
9334 return (el) ? el.style : null;
\r
9338 ElementWrapper: function(el) {
\r
9340 this.el = el || null;
\r
9342 this.id = this.el && el.id;
\r
9344 this.css = this.el && el.style;
\r
9348 getPosX: function(el) {
\r
9349 return Ext.lib.Dom.getX(el);
\r
9353 getPosY: function(el) {
\r
9354 return Ext.lib.Dom.getY(el);
\r
9358 swapNode: function(n1, n2) {
\r
9359 if (n1.swapNode) {
\r
9362 var p = n2.parentNode;
\r
9363 var s = n2.nextSibling;
\r
9366 p.insertBefore(n1, n2);
\r
9367 } else if (n2 == n1.nextSibling) {
\r
9368 p.insertBefore(n2, n1);
\r
9370 n1.parentNode.replaceChild(n2, n1);
\r
9371 p.insertBefore(n1, s);
\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
9384 l = db.scrollLeft;
\r
9388 return { top: t, left: l };
\r
9392 getStyle: function(el, styleProp) {
\r
9393 return Ext.fly(el).getStyle(styleProp);
\r
9397 getScrollTop: function () { return this.getScroll().top; },
\r
9400 getScrollLeft: function () { return this.getScroll().left; },
\r
9403 moveToEl: function (moveEl, targetEl) {
\r
9404 var aCoord = Ext.lib.Dom.getXY(targetEl);
\r
9405 Ext.lib.Dom.setXY(moveEl, aCoord);
\r
9409 numericSort: function(a, b) { return (a - b); },
\r
9415 _addListeners: function() {
\r
9416 var DDM = Ext.dd.DDM;
\r
9417 if ( Ext.lib.Event && document ) {
\r
9420 if (DDM._timeoutCount > 2000) {
\r
9422 setTimeout(DDM._addListeners, 10);
\r
9423 if (document && document.body) {
\r
9424 DDM._timeoutCount += 1;
\r
9431 handleWasClicked: function(node, id) {
\r
9432 if (this.isHandle(id, node.id)) {
\r
9435 // check to see if this is a text node child of the one we want
\r
9436 var p = node.parentNode;
\r
9439 if (this.isHandle(id, p.id)) {
\r
9454 // shorter alias, save a few bytes
\r
9455 Ext.dd.DDM = Ext.dd.DragDropMgr;
\r
9456 Ext.dd.DDM._addListeners();
\r
9461 Ext.dd.DD = function(id, sGroup, config) {
\r
9463 this.init(id, sGroup, config);
\r
9467 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
\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
9480 setDelta: function(iDeltaX, iDeltaY) {
\r
9481 this.deltaX = iDeltaX;
\r
9482 this.deltaY = iDeltaY;
\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
9490 var el = this.getDragEl();
\r
9491 this.alignElWithMouse(el, iPageX, iPageY);
\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
9505 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
\r
9508 this.cachePosition(oCoord.x, oCoord.y);
\r
9509 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
\r
9514 cachePosition: function(iPageX, iPageY) {
\r
9516 this.lastPageX = iPageX;
\r
9517 this.lastPageY = iPageY;
\r
9519 var aCoord = Ext.lib.Dom.getXY(this.getEl());
\r
9520 this.lastPageX = aCoord[0];
\r
9521 this.lastPageY = aCoord[1];
\r
9526 autoScroll: function(x, y, h, w) {
\r
9528 if (this.scroll) {
\r
9529 // The client height
\r
9530 var clientH = Ext.lib.Dom.getViewHeight();
\r
9532 // The client width
\r
9533 var clientW = Ext.lib.Dom.getViewWidth();
\r
9535 // The amt scrolled down
\r
9536 var st = this.DDM.getScrollTop();
\r
9538 // The amt scrolled right
\r
9539 var sl = this.DDM.getScrollLeft();
\r
9541 // Location of the bottom of the element
\r
9544 // Location of the right of the element
\r
9545 var right = w + x;
\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
9552 // The distance from the cursor to the right of the visible area
\r
9553 var toRight = (clientW + sl - x - this.deltaX);
\r
9556 // How close to the edge the cursor must be before we scroll
\r
9557 // var thresh = (document.all) ? 100 : 40;
\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
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
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
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
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
9592 getTargetCoord: function(iPageX, iPageY) {
\r
9595 var x = iPageX - this.deltaX;
\r
9596 var y = iPageY - this.deltaY;
\r
9598 if (this.constrainX) {
\r
9599 if (x < this.minX) { x = this.minX; }
\r
9600 if (x > this.maxX) { x = this.maxX; }
\r
9603 if (this.constrainY) {
\r
9604 if (y < this.minY) { y = this.minY; }
\r
9605 if (y > this.maxY) { y = this.maxY; }
\r
9608 x = this.getTick(x, this.xTicks);
\r
9609 y = this.getTick(y, this.yTicks);
\r
9612 return {x:x, y:y};
\r
9616 applyConfig: function() {
\r
9617 Ext.dd.DD.superclass.applyConfig.call(this);
\r
9618 this.scroll = (this.config.scroll !== false);
\r
9622 b4MouseDown: function(e) {
\r
9623 // this.resetConstraints();
\r
9624 this.autoOffset(e.getPageX(),
\r
9629 b4Drag: function(e) {
\r
9630 this.setDragElPos(e.getPageX(),
\r
9634 toString: function() {
\r
9635 return ("DD " + this.id);
\r
9638 //////////////////////////////////////////////////////////////////////////
\r
9639 // Debugging ygDragDrop events that can be overridden
\r
9640 //////////////////////////////////////////////////////////////////////////
\r
9645 Ext.dd.DDProxy = function(id, sGroup, config) {
\r
9647 this.init(id, sGroup, config);
\r
9653 Ext.dd.DDProxy.dragElId = "ygddfdiv";
\r
9655 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
\r
9658 resizeFrame: true,
\r
9661 centerFrame: false,
\r
9664 createFrame: function() {
\r
9666 var body = document.body;
\r
9668 if (!body || !body.firstChild) {
\r
9669 setTimeout( function() { self.createFrame(); }, 50 );
\r
9673 var div = this.getDragEl();
\r
9676 div = document.createElement("div");
\r
9677 div.id = this.dragElId;
\r
9678 var s = div.style;
\r
9680 s.position = "absolute";
\r
9681 s.visibility = "hidden";
\r
9682 s.cursor = "move";
\r
9683 s.border = "2px solid #aaa";
\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
9694 initFrame: function() {
\r
9695 this.createFrame();
\r
9698 applyConfig: function() {
\r
9699 Ext.dd.DDProxy.superclass.applyConfig.call(this);
\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
9707 showFrame: function(iPageX, iPageY) {
\r
9708 var el = this.getEl();
\r
9709 var dragEl = this.getDragEl();
\r
9710 var s = dragEl.style;
\r
9712 this._resizeProxy();
\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
9719 this.setDragElPos(iPageX, iPageY);
\r
9721 Ext.fly(dragEl).show();
\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
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
9740 // overrides Ext.dd.DragDrop
\r
9741 b4StartDrag: function(x, y) {
\r
9742 // show the drag frame
\r
9743 this.showFrame(x, y);
\r
9746 // overrides Ext.dd.DragDrop
\r
9747 b4EndDrag: function(e) {
\r
9748 Ext.fly(this.getDragEl()).hide();
\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
9756 var lel = this.getEl();
\r
9757 var del = this.getDragEl();
\r
9759 // Show the drag frame briefly so we can get its position
\r
9760 del.style.visibility = "";
\r
9762 this.beforeMove();
\r
9763 // Hide the linked element before the move to get around a Safari
\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
9773 beforeMove : function(){
\r
9777 afterDrag : function(){
\r
9781 toString: function() {
\r
9782 return ("DDProxy " + this.id);
\r
9787 Ext.dd.DDTarget = function(id, sGroup, config) {
\r
9789 this.initTarget(id, sGroup, config);
\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
9800 Ext.dd.DragTracker = function(config){
\r
9801 Ext.apply(this, config);
\r
9811 this.dragRegion = new Ext.lib.Region(0,0,0,0);
\r
9814 this.initEl(this.el);
\r
9818 Ext.extend(Ext.dd.DragTracker, Ext.util.Observable, {
\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
9829 destroy : function(){
\r
9830 this.el.un('mousedown', this.onMouseDown, this);
\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
9848 onMouseMove: function(e, target){
\r
9849 e.preventDefault();
\r
9850 var xy = e.getXY(), s = this.startXY;
\r
9853 if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
\r
9854 this.triggerStart();
\r
9859 this.fireEvent('mousemove', this, e);
\r
9861 this.fireEvent('drag', this, e);
\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
9875 this.fireEvent('dragend', this, e);
\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
9885 clearStart : function(){
\r
9887 clearTimeout(this.timer);
\r
9888 delete this.timer;
\r
9892 stopSelect : function(e){
\r
9897 onBeforeStart : function(e){
\r
9901 onStart : function(xy){
\r
9905 onDrag : function(e){
\r
9909 onEnd : function(e){
\r
9913 getDragTarget : function(){
\r
9914 return this.dragTarget;
\r
9917 getDragCt : function(){
\r
9921 getXY : function(constrain){
\r
9922 return constrain ?
\r
9923 this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
\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
9933 'point' : function(xy){
\r
9935 if(!this.elRegion){
\r
9936 this.elRegion = this.getDragCt().getRegion();
\r
9939 var dr = this.dragRegion;
\r
9944 dr.bottom = xy[1];
\r
9946 dr.constrainTo(this.elRegion);
\r
9948 return [dr.left, dr.top];
\r
9953 Ext.dd.ScrollManager = function(){
\r
9954 var ddm = Ext.dd.DragDropMgr;
\r
9956 var dragEl = null;
\r
9959 var onStop = function(e){
\r
9964 var triggerRefresh = function(){
\r
9965 if(ddm.dragCurrent){
\r
9966 ddm.refreshCache(ddm.dragCurrent.groups);
\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
9976 if(proc.el.scroll(proc.dir, inc)){
\r
9980 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
\r
9985 var clearProc = function(){
\r
9987 clearInterval(proc.id);
\r
9994 var startProc = function(el, 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
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
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
10023 }else if(r.right - pt.x <= c.hthresh){
\r
10024 if(proc.el != el){
\r
10025 startProc(el, "left");
\r
10028 }else if(pt.y - r.top <= c.vthresh){
\r
10029 if(proc.el != el){
\r
10030 startProc(el, "up");
\r
10033 }else if(pt.x - r.left <= c.hthresh){
\r
10034 if(proc.el != el){
\r
10035 startProc(el, "right");
\r
10044 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
\r
10045 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
\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
10055 el = Ext.get(el);
\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
10067 el = Ext.get(el);
\r
10068 delete els[el.id];
\r
10087 animDuration: .4,
\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
10100 Ext.dd.Registry = function(){
\r
10101 var elements = {};
\r
10102 var handles = {};
\r
10103 var autoIdSeed = 0;
\r
10105 var getId = function(el, autogen){
\r
10106 if(typeof el == "string"){
\r
10110 if(!id && autogen !== false){
\r
10111 id = "extdd-" + (++autoIdSeed);
\r
10119 register : function(el, data){
\r
10120 data = data || {};
\r
10121 if(typeof el == "string"){
\r
10122 el = document.getElementById(el);
\r
10125 elements[getId(el)] = data;
\r
10126 if(data.isHandle !== false){
\r
10127 handles[data.ddel.id] = data;
\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
10138 unregister : function(el){
\r
10139 var id = getId(el, false);
\r
10140 var data = elements[id];
\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
10153 getHandle : function(id){
\r
10154 if(typeof id != "string"){ // must be element?
\r
10157 return handles[id];
\r
10161 getHandleFromEvent : function(e){
\r
10162 var t = Ext.lib.Event.getTarget(e);
\r
10163 return t ? handles[t.id] : null;
\r
10167 getTarget : function(id){
\r
10168 if(typeof id != "string"){ // must be element?
\r
10171 return elements[id];
\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
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
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
10192 shadow: !config || config.shadow !== false
\r
10194 this.ghost = Ext.get(this.el.dom.childNodes[1]);
\r
10195 this.dropStatus = this.dropNotAllowed;
\r
10198 Ext.dd.StatusProxy.prototype = {
\r
10200 dropAllowed : "x-dd-drop-ok",
\r
10202 dropNotAllowed : "x-dd-drop-nodrop",
\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
10214 reset : function(clearGhost){
\r
10215 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
\r
10216 this.dropStatus = this.dropNotAllowed;
\r
10218 this.ghost.update("");
\r
10223 update : function(html){
\r
10224 if(typeof html == "string"){
\r
10225 this.ghost.update(html);
\r
10227 this.ghost.update("");
\r
10228 html.style.margin = "0";
\r
10229 this.ghost.dom.appendChild(html);
\r
10231 var el = this.ghost.dom.firstChild;
\r
10233 Ext.fly(el).setStyle(Ext.isIE ? 'styleFloat' : 'cssFloat', 'none');
\r
10238 getEl : function(){
\r
10243 getGhost : function(){
\r
10244 return this.ghost;
\r
10248 hide : function(clear){
\r
10251 this.reset(true);
\r
10256 stop : function(){
\r
10257 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
\r
10258 this.anim.stop();
\r
10263 show : function(){
\r
10268 sync : function(){
\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
10284 callback: this.afterRepair,
\r
10288 this.afterRepair();
\r
10293 afterRepair : function(){
\r
10295 if(typeof this.callback == "function"){
\r
10296 this.callback.call(this.scope || this);
\r
10298 this.callback = null;
\r
10299 this.scope = null;
\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
10309 Ext.apply(this, config);
\r
10312 this.proxy = new Ext.dd.StatusProxy();
\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
10317 this.dragging = false;
\r
10320 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
\r
10323 dropAllowed : "x-dd-drop-ok",
\r
10325 dropNotAllowed : "x-dd-drop-nodrop",
\r
10328 getDragData : function(e){
\r
10329 return this.dragData;
\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
10341 this.proxy.setStatus(this.dropAllowed);
\r
10344 if(this.afterDragEnter){
\r
10346 this.afterDragEnter(target, e, id);
\r
10352 beforeDragEnter : function(target, e, id){
\r
10357 alignElWithMouse: function() {
\r
10358 Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
\r
10359 this.proxy.sync();
\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
10371 if(this.afterDragOver){
\r
10373 this.afterDragOver(target, e, id);
\r
10379 beforeDragOver : function(target, e, id){
\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
10390 this.proxy.reset();
\r
10391 if(this.afterDragOut){
\r
10393 this.afterDragOut(target, e, id);
\r
10396 this.cachedTarget = null;
\r
10400 beforeDragOut : function(target, e, id){
\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
10412 this.onInvalidDrop(target, e, id);
\r
10415 this.onValidDrop(target, e, id);
\r
10418 if(this.afterDragDrop){
\r
10420 this.afterDragDrop(target, e, id);
\r
10423 delete this.cachedTarget;
\r
10427 beforeDragDrop : function(target, e, id){
\r
10432 onValidDrop : function(target, e, id){
\r
10433 this.hideProxy();
\r
10434 if(this.afterValidDrop){
\r
10436 this.afterValidDrop(target, e, id);
\r
10441 getRepairXY : function(e, data){
\r
10442 return this.el.getXY();
\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
10452 this.cacheTarget = null;
\r
10454 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
\r
10456 if(this.afterInvalidDrop){
\r
10458 this.afterInvalidDrop(e, id);
\r
10463 afterRepair : function(){
\r
10464 if(Ext.enableFx){
\r
10465 this.el.highlight(this.hlColor || "c3daf9");
\r
10467 this.dragging = false;
\r
10471 beforeInvalidDrop : function(target, e, id){
\r
10476 handleMouseDown : function(e){
\r
10477 if(this.dragging) {
\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
10489 onBeforeDrag : function(data, e){
\r
10494 onStartDrag : Ext.emptyFn,
\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
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
10515 getProxy : function(){
\r
10516 return this.proxy;
\r
10520 hideProxy : function(){
\r
10521 this.proxy.hide();
\r
10522 this.proxy.reset(true);
\r
10523 this.dragging = false;
\r
10527 triggerCacheRefresh : function(){
\r
10528 Ext.dd.DDM.refreshCache(this.groups);
\r
10531 // private - override to prevent hiding
\r
10532 b4EndDrag: function(e) {
\r
10535 // private - override to prevent moving
\r
10536 endDrag : function(e){
\r
10537 this.onEndDrag(this.dragData, e);
\r
10541 onEndDrag : function(data, e){
\r
10544 // private - pin to cursor
\r
10545 autoOffset : function(x, y) {
\r
10546 this.setDelta(-12, -20);
\r
10550 Ext.dd.DropTarget = function(el, config){
\r
10551 this.el = Ext.get(el);
\r
10553 Ext.apply(this, config);
\r
10555 if(this.containerScroll){
\r
10556 Ext.dd.ScrollManager.register(this.el);
\r
10559 Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
\r
10560 {isTarget: true});
\r
10564 Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
\r
10568 dropAllowed : "x-dd-drop-ok",
\r
10570 dropNotAllowed : "x-dd-drop-nodrop",
\r
10576 isNotifyTarget : true,
\r
10579 notifyEnter : function(dd, e, data){
\r
10580 if(this.overClass){
\r
10581 this.el.addClass(this.overClass);
\r
10583 return this.dropAllowed;
\r
10587 notifyOver : function(dd, e, data){
\r
10588 return this.dropAllowed;
\r
10592 notifyOut : function(dd, e, data){
\r
10593 if(this.overClass){
\r
10594 this.el.removeClass(this.overClass);
\r
10599 notifyDrop : function(dd, e, data){
\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
10611 Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
\r
10616 getDragData : function(e){
\r
10617 return Ext.dd.Registry.getHandleFromEvent(e);
\r
10621 onInitDrag : function(x, y){
\r
10622 this.proxy.update(this.dragData.ddel.cloneNode(true));
\r
10623 this.onStartDrag(x, y);
\r
10628 afterRepair : function(){
\r
10629 if(Ext.enableFx){
\r
10630 Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
\r
10632 this.dragging = false;
\r
10636 getRepairXY : function(e){
\r
10637 return Ext.Element.fly(this.dragData.ddel).getXY();
\r
10641 Ext.dd.DropZone = function(el, config){
\r
10642 Ext.dd.DropZone.superclass.constructor.call(this, el, config);
\r
10645 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
\r
10647 getTargetFromEvent : function(e){
\r
10648 return Ext.dd.Registry.getTargetFromEvent(e);
\r
10652 onNodeEnter : function(n, dd, e, data){
\r
10657 onNodeOver : function(n, dd, e, data){
\r
10658 return this.dropAllowed;
\r
10662 onNodeOut : function(n, dd, e, data){
\r
10667 onNodeDrop : function(n, dd, e, data){
\r
10672 onContainerOver : function(dd, e, data){
\r
10673 return this.dropNotAllowed;
\r
10677 onContainerDrop : function(dd, e, data){
\r
10682 notifyEnter : function(dd, e, data){
\r
10683 return this.dropNotAllowed;
\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
10694 return this.onContainerOver(dd, e, data);
\r
10696 if(this.lastOverNode != n){
\r
10697 if(this.lastOverNode){
\r
10698 this.onNodeOut(this.lastOverNode, dd, e, data);
\r
10700 this.onNodeEnter(n, dd, e, data);
\r
10701 this.lastOverNode = n;
\r
10703 return this.onNodeOver(n, dd, e, data);
\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
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
10720 var n = this.getTargetFromEvent(e);
\r
10722 this.onNodeDrop(n, dd, e, data) :
\r
10723 this.onContainerDrop(dd, e, data);
\r
10727 triggerCacheRefresh : function(){
\r
10728 Ext.dd.DDM.refreshCache(this.groups);
\r
10733 Ext.data.SortTypes = {
\r
10735 none : function(s){
\r
10740 stripTagsRE : /<\/?[^>]+>/gi,
\r
10743 asText : function(s){
\r
10744 return String(s).replace(this.stripTagsRE, "");
\r
10748 asUCText : function(s){
\r
10749 return String(s).toUpperCase().replace(this.stripTagsRE, "");
\r
10753 asUCString : function(s) {
\r
10754 return String(s).toUpperCase();
\r
10758 asDate : function(s) {
\r
10762 if(Ext.isDate(s)){
\r
10763 return s.getTime();
\r
10765 return Date.parse(String(s));
\r
10769 asFloat : function(s) {
\r
10770 var val = parseFloat(String(s).replace(/,/g, ""));
\r
10771 if(isNaN(val)) val = 0;
\r
10776 asInt : function(s) {
\r
10777 var val = parseInt(String(s).replace(/,/g, ""));
\r
10778 if(isNaN(val)) val = 0;
\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
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
10795 for(var i = 0, len = o.length; i < len; i++){
\r
10796 p.fields.add(new Ext.data.Field(o[i]));
\r
10798 f.getField = function(name){
\r
10799 return p.fields.get(name);
\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
10809 Ext.data.Record.prototype = {
\r
10821 join : function(store){
\r
10822 this.store = store;
\r
10826 set : function(name, value){
\r
10827 if(String(this.data[name]) == String(value)){
\r
10830 this.dirty = true;
\r
10831 if(!this.modified){
\r
10832 this.modified = {};
\r
10834 if(typeof this.modified[name] == 'undefined'){
\r
10835 this.modified[name] = this.data[name];
\r
10837 this.data[name] = value;
\r
10838 if(!this.editing && this.store){
\r
10839 this.store.afterEdit(this);
\r
10844 get : function(name){
\r
10845 return this.data[name];
\r
10849 beginEdit : function(){
\r
10850 this.editing = true;
\r
10851 this.modified = {};
\r
10855 cancelEdit : function(){
\r
10856 this.editing = false;
\r
10857 delete this.modified;
\r
10861 endEdit : function(){
\r
10862 this.editing = false;
\r
10863 if(this.dirty && this.store){
\r
10864 this.store.afterEdit(this);
\r
10869 reject : function(silent){
\r
10870 var m = this.modified;
\r
10872 if(typeof m[n] != "function"){
\r
10873 this.data[n] = m[n];
\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
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
10895 getChanges : function(){
\r
10896 var m = this.modified, cs = {};
\r
10898 if(m.hasOwnProperty(n)){
\r
10899 cs[n] = this.data[n];
\r
10906 hasError : function(){
\r
10907 return this.error != null;
\r
10911 clearError : function(){
\r
10912 this.error = null;
\r
10916 copy : function(newId) {
\r
10917 return new this.constructor(Ext.apply({}, this.data), newId || this.id);
\r
10921 isModified : function(fieldName){
\r
10922 return !!(this.modified && this.modified.hasOwnProperty(fieldName));
\r
10926 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
\r
10930 register : function(){
\r
10931 for(var i = 0, s; s = arguments[i]; i++){
\r
10937 unregister : function(){
\r
10938 for(var i = 0, s; s = arguments[i]; i++){
\r
10939 this.remove(this.lookup(s));
\r
10944 lookup : function(id){
\r
10945 return typeof id == "object" ? id : this.get(id);
\r
10948 // getKey implementation for MixedCollection
\r
10949 getKey : function(o){
\r
10950 return o.storeId || o.id;
\r
10954 Ext.data.Store = function(config){
\r
10955 this.data = new Ext.util.MixedCollection(false);
\r
10956 this.data.getKey = function(o){
\r
10960 this.baseParams = {};
\r
10962 this.paramNames = {
\r
10963 "start" : "start",
\r
10964 "limit" : "limit",
\r
10969 if(config && config.data){
\r
10970 this.inlineData = config.data;
\r
10971 delete config.data;
\r
10974 Ext.apply(this, config);
\r
10976 if(this.url && !this.proxy){
\r
10977 this.proxy = new Ext.data.HttpProxy({url: this.url});
\r
10980 if(this.reader){ // reader passed
\r
10981 if(!this.recordType){
\r
10982 this.recordType = this.reader.recordType;
\r
10984 if(this.reader.onMetaChange){
\r
10985 this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
\r
10990 if(this.recordType){
\r
10992 this.fields = this.recordType.prototype.fields;
\r
10994 this.modified = [];
\r
11018 this.relayEvents(this.proxy, ["loadexception"]);
\r
11021 this.sortToggle = {};
\r
11022 if(this.sortInfo){
\r
11023 this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
\r
11026 Ext.data.Store.superclass.constructor.call(this);
\r
11028 if(this.storeId || this.id){
\r
11029 Ext.StoreMgr.register(this);
\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
11040 Ext.extend(Ext.data.Store, Ext.util.Observable, {
\r
11050 remoteSort : false,
\r
11053 pruneModifiedRecords : false,
\r
11056 lastOptions : null,
\r
11058 destroy : function(){
\r
11059 if(this.storeId || this.id){
\r
11060 Ext.StoreMgr.unregister(this);
\r
11062 this.data = null;
\r
11063 this.purgeListeners();
\r
11067 add : function(records){
\r
11068 records = [].concat(records);
\r
11069 if(records.length < 1){
\r
11072 for(var i = 0, len = records.length; i < len; i++){
\r
11073 records[i].join(this);
\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
11080 this.fireEvent("add", this, records, index);
\r
11084 addSorted : function(record){
\r
11085 var index = this.findInsertIndex(record);
\r
11086 this.insert(index, record);
\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
11096 if(this.snapshot){
\r
11097 this.snapshot.remove(record);
\r
11099 this.fireEvent("remove", this, record, index);
\r
11103 removeAt : function(index){
\r
11104 this.remove(this.getAt(index));
\r
11108 removeAll : function(){
\r
11109 this.data.clear();
\r
11110 if(this.snapshot){
\r
11111 this.snapshot.clear();
\r
11113 if(this.pruneModifiedRecords){
\r
11114 this.modified = [];
\r
11116 this.fireEvent("clear", this);
\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
11126 this.fireEvent("add", this, records, index);
\r
11130 indexOf : function(record){
\r
11131 return this.data.indexOf(record);
\r
11135 indexOfId : function(id){
\r
11136 return this.data.indexOfKey(id);
\r
11140 getById : function(id){
\r
11141 return this.data.key(id);
\r
11145 getAt : function(index){
\r
11146 return this.data.itemAt(index);
\r
11150 getRange : function(start, end){
\r
11151 return this.data.getRange(start, end);
\r
11155 storeOptions : function(o){
\r
11156 o = Ext.apply({}, o);
\r
11157 delete o.callback;
\r
11159 this.lastOptions = o;
\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
11173 this.proxy.load(p, this.reader, this.loadRecords, this, options);
\r
11181 reload : function(options){
\r
11182 this.load(Ext.applyIf(options||{}, this.lastOptions));
\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
11192 if(options.callback){
\r
11193 options.callback.call(options.scope || this, [], options, false);
\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
11202 for(var i = 0, len = r.length; i < len; i++){
\r
11205 if(this.snapshot){
\r
11206 this.data = this.snapshot;
\r
11207 delete this.snapshot;
\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
11215 this.totalLength = Math.max(t, this.data.length+r.length);
\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
11225 loadData : function(o, append){
\r
11226 var r = this.reader.readRecords(o);
\r
11227 this.loadRecords(r, {add: append}, true);
\r
11231 getCount : function(){
\r
11232 return this.data.length || 0;
\r
11236 getTotalCount : function(){
\r
11237 return this.totalLength || 0;
\r
11241 getSortState : function(){
\r
11242 return this.sortInfo;
\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
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
11261 this.data.sort(direction, fn);
\r
11262 if(this.snapshot && this.snapshot != this.data){
\r
11263 this.snapshot.sort(direction, fn);
\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
11275 sort : function(fieldName, dir){
\r
11276 var f = this.fields.get(fieldName);
\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
11287 var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
\r
11288 var si = (this.sortInfo) ? this.sortInfo : null;
\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
11296 if (!this.load(this.lastOptions)) {
\r
11298 this.sortToggle[f.name] = st;
\r
11301 this.sortInfo = si;
\r
11308 each : function(fn, scope){
\r
11309 this.data.each(fn, scope);
\r
11313 getModifiedRecords : function(){
\r
11314 return this.modified;
\r
11318 createFilterFn : function(property, value, anyMatch, caseSensitive){
\r
11319 if(Ext.isEmpty(value, false)){
\r
11322 value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
\r
11323 return function(r){
\r
11324 return value.test(r.data[property]);
\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
11334 for(var i = start; i <= end; i++){
\r
11335 v += (rs[i].data[property] || 0);
\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
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
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
11360 queryBy : function(fn, scope){
\r
11361 var data = this.snapshot || this.data;
\r
11362 return data.filterBy(fn, scope||this);
\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
11372 findBy : function(fn, scope, start){
\r
11373 return this.data.findIndexBy(fn, scope, start);
\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
11384 if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
\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
11404 isFiltered : function(){
\r
11405 return this.snapshot && this.snapshot != this.data;
\r
11409 afterEdit : function(record){
\r
11410 if(this.modified.indexOf(record) == -1){
\r
11411 this.modified.push(record);
\r
11413 this.fireEvent("update", this, record, Ext.data.Record.EDIT);
\r
11417 afterReject : function(record){
\r
11418 this.modified.remove(record);
\r
11419 this.fireEvent("update", this, record, Ext.data.Record.REJECT);
\r
11423 afterCommit : function(record){
\r
11424 this.modified.remove(record);
\r
11425 this.fireEvent("update", this, record, Ext.data.Record.COMMIT);
\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
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
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
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
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
11474 Ext.data.Record.create(config.fields)
\r
11478 Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {
\r
11479 loadData : function(data, append){
\r
11480 if(this.expandData === true){
\r
11482 for(var i = 0, len = data.length; i < len; i++){
\r
11483 r[r.length] = [data[i]];
\r
11487 Ext.data.SimpleStore.superclass.loadData.call(this, data, append);
\r
11491 Ext.data.JsonStore = function(c){
\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
11499 Ext.extend(Ext.data.JsonStore, Ext.data.Store);
\r
11501 Ext.data.Field = function(config){
\r
11502 if(typeof config == "string"){
\r
11503 config = {name: config};
\r
11505 Ext.apply(this, config);
\r
11508 this.type = "auto";
\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
11517 // set default sortType for strings and dates
\r
11518 if(!this.sortType){
\r
11519 switch(this.type){
\r
11521 this.sortType = st.asUCString;
\r
11524 this.sortType = st.asDate;
\r
11527 this.sortType = st.none;
\r
11532 var stripRe = /[\$,%]/g;
\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
11542 cv = function(v){ return v; };
\r
11545 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
\r
11548 cv = function(v){
\r
11549 return v !== undefined && v !== null && v !== '' ?
\r
11550 parseInt(String(v).replace(stripRe, ""), 10) : '';
\r
11554 cv = function(v){
\r
11555 return v !== undefined && v !== null && v !== '' ?
\r
11556 parseFloat(String(v).replace(stripRe, ""), 10) : '';
\r
11561 cv = function(v){ return v === true || v === "true" || v == 1; };
\r
11564 cv = function(v){
\r
11568 if(Ext.isDate(v)){
\r
11572 if(dateFormat == "timestamp"){
\r
11573 return new Date(v*1000);
\r
11575 if(dateFormat == "time"){
\r
11576 return new Date(parseInt(v, 10));
\r
11578 return Date.parseDate(v, dateFormat);
\r
11580 var parsed = Date.parse(v);
\r
11581 return parsed ? new Date(parsed) : null;
\r
11586 this.convert = cv;
\r
11590 Ext.data.Field.prototype = {
\r
11595 dateFormat: null,
\r
11597 defaultValue: "",
\r
11606 Ext.data.DataReader = function(meta, recordType){
\r
11608 this.meta = meta;
\r
11609 this.recordType = Ext.isArray(recordType) ?
\r
11610 Ext.data.Record.create(recordType) : recordType;
\r
11613 Ext.data.DataReader.prototype = {
\r
11617 Ext.data.DataProxy = function(){
\r
11624 Ext.data.DataProxy.superclass.constructor.call(this);
\r
11627 Ext.extend(Ext.data.DataProxy, Ext.util.Observable);
\r
11629 Ext.data.MemoryProxy = function(data){
\r
11630 Ext.data.MemoryProxy.superclass.constructor.call(this);
\r
11631 this.data = data;
\r
11634 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
\r
11638 load : function(params, reader, callback, scope, arg){
\r
11639 params = params || {};
\r
11642 result = reader.readRecords(this.data);
\r
11644 this.fireEvent("loadexception", this, arg, null, e);
\r
11645 callback.call(scope, null, arg, false);
\r
11648 callback.call(scope, result, arg, true);
\r
11652 update : function(params, records){
\r
11657 Ext.data.HttpProxy = function(conn){
\r
11658 Ext.data.HttpProxy.superclass.constructor.call(this);
\r
11660 this.conn = conn;
\r
11661 this.useAjax = !conn || !conn.events;
\r
11666 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
\r
11668 getConnection : function(){
\r
11669 return this.useAjax ? Ext.Ajax : this.conn;
\r
11673 load : function(params, reader, callback, scope, arg){
\r
11674 if(this.fireEvent("beforeload", this, params) !== false){
\r
11676 params : params || {},
\r
11678 callback : callback,
\r
11683 callback : this.loadResponse,
\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
11691 this.activeRequest = Ext.Ajax.request(o);
\r
11693 this.conn.request(o);
\r
11696 callback.call(scope||this, null, arg, false);
\r
11701 loadResponse : function(o, success, response){
\r
11702 delete this.activeRequest;
\r
11704 this.fireEvent("loadexception", this, o, response);
\r
11705 o.request.callback.call(o.request.scope, null, o.request.arg, false);
\r
11710 result = o.reader.read(response);
\r
11712 this.fireEvent("loadexception", this, o, response, e);
\r
11713 o.request.callback.call(o.request.scope, null, o.request.arg, false);
\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
11721 update : function(dataSet){
\r
11726 updateResponse : function(dataSet){
\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
11739 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
\r
11741 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
\r
11746 callbackParam : "callback",
\r
11751 load : function(params, reader, callback, scope, arg){
\r
11752 if(this.fireEvent("beforeload", this, params) !== false){
\r
11754 var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
\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
11761 var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
\r
11764 cb : "stcCallback"+transId,
\r
11765 scriptId : "stcScript"+transId,
\r
11769 callback : callback,
\r
11775 window[trans.cb] = function(o){
\r
11776 conn.handleResponse(o, trans);
\r
11779 url += String.format("&{0}={1}", this.callbackParam, trans.cb);
\r
11781 if(this.autoAbort !== false){
\r
11785 trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
\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
11793 this.trans = trans;
\r
11795 callback.call(scope||this, null, arg, false);
\r
11800 isLoading : function(){
\r
11801 return this.trans ? true : false;
\r
11805 abort : function(){
\r
11806 if(this.isLoading()){
\r
11807 this.destroyTrans(this.trans);
\r
11812 destroyTrans : function(trans, isLoaded){
\r
11813 this.head.removeChild(document.getElementById(trans.scriptId));
\r
11814 clearTimeout(trans.timeoutId);
\r
11816 window[trans.cb] = undefined;
\r
11818 delete window[trans.cb];
\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
11825 delete window[trans.cb];
\r
11832 handleResponse : function(o, trans){
\r
11833 this.trans = false;
\r
11834 this.destroyTrans(trans, true);
\r
11837 result = trans.reader.readRecords(o);
\r
11839 this.fireEvent("loadexception", this, o, trans.arg, e);
\r
11840 trans.callback.call(trans.scope||window, null, trans.arg, false);
\r
11843 this.fireEvent("load", this, o, trans.arg);
\r
11844 trans.callback.call(trans.scope||window, result, trans.arg, true);
\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
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
11860 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
\r
11863 read : function(response){
\r
11864 var json = response.responseText;
\r
11865 var o = eval("("+json+")");
\r
11867 throw {message: "JsonReader.read: Json object not found"};
\r
11869 return this.readRecords(o);
\r
11872 // private function a store will implement
\r
11873 onMetaChange : function(meta, recordType, o){
\r
11878 simpleAccess: function(obj, subsc) {
\r
11879 return obj[subsc];
\r
11883 getJsonAccessor: function(){
\r
11884 var re = /[\[\.]/;
\r
11885 return function(expr) {
\r
11887 return(re.test(expr))
\r
11888 ? new Function("obj", "return obj." + expr)
\r
11890 return obj[expr];
\r
11893 return Ext.emptyFn;
\r
11898 readRecords : function(o){
\r
11900 this.jsonData = o;
\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
11907 var s = this.meta, Record = this.recordType,
\r
11908 f = Record.prototype.fields, fi = f.items, fl = f.length;
\r
11910 // Generate extraction functions for the totalProperty, the root, the id, and for each field
\r
11912 if(s.totalProperty) {
\r
11913 this.getTotal = this.getJsonAccessor(s.totalProperty);
\r
11915 if(s.successProperty) {
\r
11916 this.getSuccess = this.getJsonAccessor(s.successProperty);
\r
11918 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
\r
11920 var g = this.getJsonAccessor(s.id);
\r
11921 this.getId = function(rec) {
\r
11923 return (r === undefined || r === "") ? null : r;
\r
11926 this.getId = function(){return null;};
\r
11929 for(var i = 0; i < fl; i++){
\r
11931 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
\r
11932 this.ef[i] = this.getJsonAccessor(map);
\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
11940 totalRecords = v;
\r
11943 if(s.successProperty){
\r
11944 var v = this.getSuccess(o);
\r
11945 if(v === false || v === 'false'){
\r
11949 var records = [];
\r
11950 for(var i = 0; i < c; i++){
\r
11953 var id = this.getId(n);
\r
11954 for(var j = 0; j < fl; j++){
\r
11956 var v = this.ef[j](n);
\r
11957 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);
\r
11959 var record = new Record(values, id);
\r
11961 records[i] = record;
\r
11964 success : success,
\r
11965 records : records,
\r
11966 totalRecords : totalRecords
\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
11975 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
\r
11977 read : function(response){
\r
11978 var doc = response.responseXML;
\r
11980 throw {message: "XmlReader.read: XML Document not available"};
\r
11982 return this.readRecords(doc);
\r
11986 readRecords : function(doc){
\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
11998 if(this.meta.success){
\r
11999 var sv = q.selectValue(this.meta.success, root, true);
\r
12000 success = sv !== false && sv !== 'false';
\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
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
12014 var record = new recordType(values, id);
\r
12016 records[records.length] = record;
\r
12020 success : success,
\r
12021 records : records,
\r
12022 totalRecords : totalRecords || records.length
\r
12027 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
\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
12034 for(var i = 0; i < root.length; i++){
\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
12045 var record = new recordType(values, id);
\r
12047 records[records.length] = record;
\r
12050 records : records,
\r
12051 totalRecords : records.length
\r
12056 Ext.data.Tree = function(root){
\r
12057 this.nodeHash = {};
\r
12059 this.root = null;
\r
12061 this.setRootNode(root);
\r
12082 Ext.data.Tree.superclass.constructor.call(this);
\r
12085 Ext.extend(Ext.data.Tree, Ext.util.Observable, {
\r
12087 pathSeparator: "/",
\r
12090 proxyNodeEvent : function(){
\r
12091 return this.fireEvent.apply(this, arguments);
\r
12095 getRootNode : function(){
\r
12096 return this.root;
\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
12109 getNodeById : function(id){
\r
12110 return this.nodeHash[id];
\r
12114 registerNode : function(node){
\r
12115 this.nodeHash[node.id] = node;
\r
12119 unregisterNode : function(node){
\r
12120 delete this.nodeHash[node.id];
\r
12123 toString : function(){
\r
12124 return "[Tree"+(this.id?" "+this.id:"")+"]";
\r
12129 Ext.data.Node = function(attributes){
\r
12131 this.attributes = attributes || {};
\r
12132 this.leaf = this.attributes.leaf;
\r
12134 this.id = this.attributes.id;
\r
12136 this.id = Ext.id(null, "ynode-");
\r
12137 this.attributes.id = this.id;
\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
12150 this.parentNode = null;
\r
12152 this.firstChild = null;
\r
12154 this.lastChild = null;
\r
12156 this.previousSibling = null;
\r
12158 this.nextSibling = null;
\r
12170 "beforeappend" : true,
\r
12172 "beforeremove" : true,
\r
12174 "beforemove" : true,
\r
12176 "beforeinsert" : true
\r
12178 this.listeners = this.attributes.listeners;
\r
12179 Ext.data.Node.superclass.constructor.call(this);
\r
12182 Ext.extend(Ext.data.Node, Ext.util.Observable, {
\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
12189 // then bubble it up to the tree if the event wasn't cancelled
\r
12190 var ot = this.getOwnerTree();
\r
12192 if(ot.proxyNodeEvent.apply(ot, arguments) === false){
\r
12200 isLeaf : function(){
\r
12201 return this.leaf === true;
\r
12205 setFirstChild : function(node){
\r
12206 this.firstChild = node;
\r
12210 setLastChild : function(node){
\r
12211 this.lastChild = node;
\r
12216 isLast : function(){
\r
12217 return (!this.parentNode ? true : this.parentNode.lastChild == this);
\r
12221 isFirst : function(){
\r
12222 return (!this.parentNode ? true : this.parentNode.firstChild == this);
\r
12226 hasChildNodes : function(){
\r
12227 return !this.isLeaf() && this.childNodes.length > 0;
\r
12231 isExpandable : function(){
\r
12232 return this.attributes.expandable || this.hasChildNodes();
\r
12236 appendChild : function(node){
\r
12237 var multi = false;
\r
12238 if(Ext.isArray(node)){
\r
12240 }else if(arguments.length > 1){
\r
12241 multi = arguments;
\r
12243 // if passed an array or multiple args do them one by one
\r
12245 for(var i = 0, len = multi.length; i < len; i++) {
\r
12246 this.appendChild(multi[i]);
\r
12249 if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
\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
12256 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
\r
12259 oldParent.removeChild(node);
\r
12261 index = this.childNodes.length;
\r
12263 this.setFirstChild(node);
\r
12265 this.childNodes.push(node);
\r
12266 node.parentNode = this;
\r
12267 var ps = this.childNodes[index-1];
\r
12269 node.previousSibling = ps;
\r
12270 ps.nextSibling = node;
\r
12272 node.previousSibling = null;
\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
12279 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
\r
12286 removeChild : function(node){
\r
12287 var index = this.childNodes.indexOf(node);
\r
12291 if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
\r
12295 // remove it from childNodes collection
\r
12296 this.childNodes.splice(index, 1);
\r
12298 // update siblings
\r
12299 if(node.previousSibling){
\r
12300 node.previousSibling.nextSibling = node.nextSibling;
\r
12302 if(node.nextSibling){
\r
12303 node.nextSibling.previousSibling = node.previousSibling;
\r
12306 // update child refs
\r
12307 if(this.firstChild == node){
\r
12308 this.setFirstChild(node.nextSibling);
\r
12310 if(this.lastChild == node){
\r
12311 this.setLastChild(node.previousSibling);
\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
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
12329 if(node == refNode){
\r
12333 if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
\r
12336 var index = this.childNodes.indexOf(refNode);
\r
12337 var oldParent = node.parentNode;
\r
12338 var refIndex = index;
\r
12340 // when moving internally, indexes will change after remove
\r
12341 if(oldParent == this && this.childNodes.indexOf(node) < index){
\r
12345 // it's a move, make sure we move it cleanly
\r
12347 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
\r
12350 oldParent.removeChild(node);
\r
12352 if(refIndex == 0){
\r
12353 this.setFirstChild(node);
\r
12355 this.childNodes.splice(refIndex, 0, node);
\r
12356 node.parentNode = this;
\r
12357 var ps = this.childNodes[refIndex-1];
\r
12359 node.previousSibling = ps;
\r
12360 ps.nextSibling = node;
\r
12362 node.previousSibling = null;
\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
12369 node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
\r
12375 remove : function(){
\r
12376 this.parentNode.removeChild(this);
\r
12381 item : function(index){
\r
12382 return this.childNodes[index];
\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
12394 indexOf : function(child){
\r
12395 return this.childNodes.indexOf(child);
\r
12399 getOwnerTree : function(){
\r
12400 // if it doesn't have one, look for one
\r
12401 if(!this.ownerTree){
\r
12405 this.ownerTree = p.ownerTree;
\r
12408 p = p.parentNode;
\r
12411 return this.ownerTree;
\r
12415 getDepth : function(){
\r
12418 while(p.parentNode){
\r
12420 p = p.parentNode;
\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
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
12438 tree.registerNode(this);
\r
12444 getPath : function(attr){
\r
12445 attr = attr || "id";
\r
12446 var p = this.parentNode;
\r
12447 var b = [this.attributes[attr]];
\r
12449 b.unshift(p.attributes[attr]);
\r
12450 p = p.parentNode;
\r
12452 var sep = this.getOwnerTree().pathSeparator;
\r
12453 return sep + b.join(sep);
\r
12457 bubble : function(fn, scope, args){
\r
12460 if(fn.apply(scope || p, args || [p]) === false){
\r
12463 p = p.parentNode;
\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
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
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
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
12510 sort : function(fn, scope){
\r
12511 var cs = this.childNodes;
\r
12512 var len = cs.length;
\r
12514 var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
\r
12516 for(var i = 0; i < len; i++){
\r
12518 n.previousSibling = cs[i-1];
\r
12519 n.nextSibling = cs[i+1];
\r
12521 this.setFirstChild(n);
\r
12524 this.setLastChild(n);
\r
12531 contains : function(node){
\r
12532 return node.isAncestor(this);
\r
12536 isAncestor : function(node){
\r
12537 var p = this.parentNode;
\r
12542 p = p.parentNode;
\r
12547 toString : function(){
\r
12548 return "[Node"+(this.id?" "+this.id:"")+"]";
\r
12552 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
\r
12555 remoteGroup : false,
\r
12557 groupOnSort:false,
\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
12568 this.applySort();
\r
12569 this.fireEvent('datachanged', this);
\r
12574 groupBy : function(field, forceRegroup){
\r
12575 if(this.groupField == field && !forceRegroup){
\r
12576 return; // already grouped by this field
\r
12578 this.groupField = field;
\r
12579 if(this.remoteGroup){
\r
12580 if(!this.baseParams){
\r
12581 this.baseParams = {};
\r
12583 this.baseParams['groupBy'] = field;
\r
12585 if(this.groupOnSort){
\r
12586 this.sort(field);
\r
12589 if(this.remoteGroup){
\r
12592 var si = this.sortInfo || {};
\r
12593 if(si.field != field){
\r
12594 this.applySort();
\r
12596 this.sortData(field);
\r
12598 this.fireEvent('datachanged', this);
\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
12614 applyGrouping : function(alwaysFireChange){
\r
12615 if(this.groupField !== false){
\r
12616 this.groupBy(this.groupField, true);
\r
12619 if(alwaysFireChange === true){
\r
12620 this.fireEvent('datachanged', this);
\r
12627 getGroupState : function(){
\r
12628 return this.groupOnSort && this.groupField !== false ?
\r
12629 (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
\r
12633 Ext.ComponentMgr = function(){
\r
12634 var all = new Ext.util.MixedCollection();
\r
12639 register : function(c){
\r
12644 unregister : function(c){
\r
12649 get : function(id){
\r
12650 return all.get(id);
\r
12654 onAvailable : function(id, fn, scope){
\r
12655 all.on("add", function(index, o){
\r
12657 fn.call(scope || o, o);
\r
12658 all.un("add", fn, scope);
\r
12667 registerType : function(xtype, cls){
\r
12668 types[xtype] = cls;
\r
12669 cls.xtype = xtype;
\r
12673 create : function(config, defaultType){
\r
12674 return new types[config.xtype || defaultType](config);
\r
12680 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
\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
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
12694 this.initialConfig = config;
\r
12696 Ext.apply(this, config);
\r
12719 'beforestaterestore',
\r
12723 'beforestatesave',
\r
12728 Ext.ComponentMgr.register(this);
\r
12729 Ext.Component.superclass.constructor.call(this);
\r
12731 if(this.baseAction){
\r
12732 this.baseAction.addComponent(this);
\r
12735 this.initComponent();
\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
12743 this.plugins = this.initPlugin(this.plugins);
\r
12747 if(this.stateful !== false){
\r
12748 this.initState(config);
\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
12761 Ext.Component.AUTO_ID = 1000;
\r
12763 Ext.extend(Ext.Component, Ext.util.Observable, {
\r
12764 // Configs below are used for all Components when rendered by FormLayout.
\r
12790 disabledClass : "x-item-disabled",
\r
12792 allowDomMove : true,
\r
12794 autoShow : false,
\r
12796 hideMode: 'display',
\r
12798 hideParent: false,
\r
12804 disabled : false,
\r
12806 rendered : false,
\r
12809 ctype : "Ext.Component",
\r
12812 actionMode : "el",
\r
12815 getActionEl : function(){
\r
12816 return this[this.actionMode];
\r
12819 initPlugin : function(p){
\r
12825 initComponent : Ext.emptyFn,
\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
12835 this.container = Ext.get(container);
\r
12837 this.container.addClass(this.ctCls);
\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
12844 position = Ext.getDom(position);
\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
12852 this.el.addClass(this.cls);
\r
12856 this.el.applyStyles(this.style);
\r
12857 delete this.style;
\r
12859 if(this.overCls){
\r
12860 this.el.addClassOnOver(this.overCls);
\r
12862 this.fireEvent("render", this);
\r
12863 this.afterRender(this.container);
\r
12867 if(this.disabled){
\r
12871 if(this.stateful !== false){
\r
12872 this.initStateEvents();
\r
12879 initState : function(config){
\r
12880 if(Ext.state.Manager){
\r
12881 var id = this.getStateId();
\r
12883 var state = Ext.state.Manager.get(id);
\r
12885 if(this.fireEvent('beforestaterestore', this, state) !== false){
\r
12886 this.applyState(state);
\r
12887 this.fireEvent('staterestore', this, state);
\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
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
12909 applyState : function(state, config){
\r
12911 Ext.apply(this, state);
\r
12916 getState : function(){
\r
12921 saveState : function(){
\r
12922 if(Ext.state.Manager){
\r
12923 var id = this.getStateId();
\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
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
12942 addClass : function(cls){
\r
12944 this.el.addClass(cls);
\r
12946 this.cls = this.cls ? this.cls + ' ' + cls : cls;
\r
12951 removeClass : function(cls){
\r
12953 this.el.removeClass(cls);
\r
12954 }else if(this.cls){
\r
12955 this.cls = this.cls.split(' ').remove(cls).join(' ');
\r
12960 // default function is not really useful
\r
12961 onRender : function(ct, position){
\r
12963 if(typeof this.autoEl == 'string'){
\r
12964 this.el = document.createElement(this.autoEl);
\r
12966 var div = document.createElement('div');
\r
12967 Ext.DomHelper.overwrite(div, this.autoEl);
\r
12968 this.el = div.firstChild;
\r
12970 if (!this.el.id) {
\r
12971 this.el.id = this.getId();
\r
12975 this.el = Ext.get(this.el);
\r
12976 if(this.allowDomMove !== false){
\r
12977 ct.dom.insertBefore(this.el.dom, position);
\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
12993 afterRender : Ext.emptyFn,
\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
13006 this.onDestroy();
\r
13007 Ext.ComponentMgr.unregister(this);
\r
13008 this.fireEvent("destroy", this);
\r
13009 this.purgeListeners();
\r
13014 beforeDestroy : Ext.emptyFn,
\r
13017 onDestroy : Ext.emptyFn,
\r
13020 getEl : function(){
\r
13025 getId : function(){
\r
13026 return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));
\r
13030 getItemId : function(){
\r
13031 return this.itemId || this.getId();
\r
13035 focus : function(selectText, delay){
\r
13037 this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);
\r
13040 if(this.rendered){
\r
13042 if(selectText === true){
\r
13043 this.el.dom.select();
\r
13050 blur : function(){
\r
13051 if(this.rendered){
\r
13058 disable : function(){
\r
13059 if(this.rendered){
\r
13060 this.onDisable();
\r
13062 this.disabled = true;
\r
13063 this.fireEvent("disable", this);
\r
13068 onDisable : function(){
\r
13069 this.getActionEl().addClass(this.disabledClass);
\r
13070 this.el.dom.disabled = true;
\r
13074 enable : function(){
\r
13075 if(this.rendered){
\r
13078 this.disabled = false;
\r
13079 this.fireEvent("enable", this);
\r
13084 onEnable : function(){
\r
13085 this.getActionEl().removeClass(this.disabledClass);
\r
13086 this.el.dom.disabled = false;
\r
13090 setDisabled : function(disabled){
\r
13091 this[disabled ? "disable" : "enable"]();
\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
13101 if(this.rendered){
\r
13104 this.fireEvent("show", this);
\r
13110 onShow : function(){
\r
13111 if(this.hideParent){
\r
13112 this.container.removeClass('x-hide-' + this.hideMode);
\r
13114 this.getActionEl().removeClass('x-hide-' + this.hideMode);
\r
13120 hide: function(){
\r
13121 if(this.fireEvent("beforehide", this) !== false){
\r
13122 this.hidden = true;
\r
13123 if(this.rendered){
\r
13126 this.fireEvent("hide", this);
\r
13132 onHide : function(){
\r
13133 if(this.hideParent){
\r
13134 this.container.addClass('x-hide-' + this.hideMode);
\r
13136 this.getActionEl().addClass('x-hide-' + this.hideMode);
\r
13141 setVisible: function(visible){
\r
13151 isVisible : function(){
\r
13152 return this.rendered && this.getActionEl().isVisible();
\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
13165 getXType : function(){
\r
13166 return this.constructor.xtype;
\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
13178 return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
\r
13182 getXTypes : function(){
\r
13183 var tc = this.constructor;
\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
13190 tc.xtypeChain = c;
\r
13191 tc.xtypes = c.join('/');
\r
13193 return tc.xtypes;
\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
13203 findParentByType: function(xtype) {
\r
13204 return typeof xtype == 'function' ?
\r
13205 this.findParentBy(function(p){
\r
13206 return p.constructor === xtype;
\r
13208 this.findParentBy(function(p){
\r
13209 return p.constructor.xtype === xtype;
\r
13213 // internal function for auto removal of assigned event handlers on destruction
\r
13214 mon : function(item, ename, fn, scope, opt){
\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
13225 item: item, ename: ename, fn: fn, scope: scope
\r
13227 item.on(ename, fn, scope, opt);
\r
13231 Ext.reg('component', Ext.Component);
\r
13234 Ext.Action = function(config){
\r
13235 this.initialConfig = config;
\r
13239 Ext.Action.prototype = {
\r
13251 setText : function(text){
\r
13252 this.initialConfig.text = text;
\r
13253 this.callEach('setText', [text]);
\r
13257 getText : function(){
\r
13258 return this.initialConfig.text;
\r
13262 setIconClass : function(cls){
\r
13263 this.initialConfig.iconCls = cls;
\r
13264 this.callEach('setIconClass', [cls]);
\r
13268 getIconClass : function(){
\r
13269 return this.initialConfig.iconCls;
\r
13273 setDisabled : function(v){
\r
13274 this.initialConfig.disabled = v;
\r
13275 this.callEach('setDisabled', [v]);
\r
13279 enable : function(){
\r
13280 this.setDisabled(false);
\r
13284 disable : function(){
\r
13285 this.setDisabled(true);
\r
13289 isDisabled : function(){
\r
13290 return this.initialConfig.disabled;
\r
13294 setHidden : function(v){
\r
13295 this.initialConfig.hidden = v;
\r
13296 this.callEach('setVisible', [!v]);
\r
13300 show : function(){
\r
13301 this.setHidden(false);
\r
13305 hide : function(){
\r
13306 this.setHidden(true);
\r
13310 isHidden : function(){
\r
13311 return this.initialConfig.hidden;
\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
13322 each : function(fn, scope){
\r
13323 Ext.each(this.items, fn, scope);
\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
13335 addComponent : function(comp){
\r
13336 this.items.push(comp);
\r
13337 comp.on('destroy', this.removeComponent, this);
\r
13341 removeComponent : function(comp){
\r
13342 this.items.remove(comp);
\r
13346 execute : function(){
\r
13347 this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
\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
13357 this.dom = Ext.getDom(existingEl);
\r
13360 var o = config.dh || {tag: "div", cls: "x-layer"};
\r
13361 this.dom = dh.append(pel, o);
\r
13364 this.addClass(config.cls);
\r
13366 this.constrain = config.constrain !== false;
\r
13367 this.visibilityMode = Ext.Element.VISIBILITY;
\r
13369 this.id = this.dom.id = config.id;
\r
13371 this.id = Ext.id(this.dom);
\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
13382 this.shadowOffset = 0;
\r
13384 this.useShim = config.shim !== false && Ext.useShims;
\r
13385 this.useDisplay = config.useDisplay;
\r
13389 var supr = Ext.Element.prototype;
\r
13391 // shims are shared among layer to keep from having 100 iframes
\r
13394 Ext.extend(Ext.Layer, Ext.Element, {
\r
13396 getZIndex : function(){
\r
13397 return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
\r
13400 getShim : function(){
\r
13401 if(!this.useShim){
\r
13405 return this.shim;
\r
13407 var shim = shims.shift();
\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
13414 var pn = this.dom.parentNode;
\r
13415 if(shim.dom.parentNode != pn){
\r
13416 pn.insertBefore(shim.dom, this.dom);
\r
13418 shim.setStyle('z-index', this.getZIndex()-2);
\r
13419 this.shim = shim;
\r
13423 hideShim : function(){
\r
13425 this.shim.setDisplayed(false);
\r
13426 shims.push(this.shim);
\r
13427 delete this.shim;
\r
13431 disableShadow : function(){
\r
13433 this.shadowDisabled = true;
\r
13434 this.shadow.hide();
\r
13435 this.lastShadowOffset = this.shadowOffset;
\r
13436 this.shadowOffset = 0;
\r
13440 enableShadow : function(show){
\r
13442 this.shadowDisabled = false;
\r
13443 this.shadowOffset = this.lastShadowOffset;
\r
13444 delete this.lastShadowOffset;
\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
13459 var w = this.getWidth(),
\r
13460 h = this.getHeight();
\r
13462 var l = this.getLeft(true),
\r
13463 t = this.getTop(true);
\r
13465 if(sw && !this.shadowDisabled){
\r
13466 if(doShow && !sw.isVisible()){
\r
13469 sw.realign(l, t, w, h);
\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
13486 sh.setSize(w, h);
\r
13487 sh.setLeftTop(l, t);
\r
13494 destroy : function(){
\r
13497 this.shadow.hide();
\r
13499 this.removeAllListeners();
\r
13500 Ext.removeNode(this.dom);
\r
13501 Ext.Element.uncache(this.id);
\r
13504 remove : function(){
\r
13509 beginUpdate : function(){
\r
13510 this.updating = true;
\r
13514 endUpdate : function(){
\r
13515 this.updating = false;
\r
13520 hideUnders : function(negOffset){
\r
13522 this.shadow.hide();
\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
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
13544 if((y + h) > vh+s.top){
\r
13545 y = vh - h - this.shadowOffset;
\r
13548 // then make sure top/left isn't negative
\r
13559 var ay = this.avoidY;
\r
13560 if(y <= ay && (y+h) >= ay){
\r
13565 this.storeXY(xy);
\r
13566 supr.setXY.call(this, xy);
\r
13572 isVisible : function(){
\r
13573 return this.visible;
\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
13589 hideAction : function(){
\r
13590 this.visible = false;
\r
13591 if(this.useDisplay === true){
\r
13592 this.setDisplayed(false);
\r
13594 this.setLeftTop(-10000,-10000);
\r
13598 // overridden Element method
\r
13599 setVisible : function(v, a, d, c, e){
\r
13601 this.showAction();
\r
13604 var cb = function(){
\r
13609 }.createDelegate(this);
\r
13610 supr.setVisible.call(this, true, true, d, cb, e);
\r
13613 this.hideUnders(true);
\r
13618 this.hideAction();
\r
13622 }.createDelegate(this);
\r
13624 supr.setVisible.call(this, v, a, d, cb, e);
\r
13628 this.hideAction();
\r
13633 storeXY : function(xy){
\r
13634 delete this.lastLT;
\r
13635 this.lastXY = xy;
\r
13638 storeLeftTop : function(left, top){
\r
13639 delete this.lastXY;
\r
13640 this.lastLT = [left, top];
\r
13644 beforeFx : function(){
\r
13645 this.beforeAction();
\r
13646 return Ext.Layer.superclass.beforeFx.apply(this, arguments);
\r
13650 afterFx : function(){
\r
13651 Ext.Layer.superclass.afterFx.apply(this, arguments);
\r
13652 this.sync(this.isVisible());
\r
13656 beforeAction : function(){
\r
13657 if(!this.updating && this.shadow){
\r
13658 this.shadow.hide();
\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
13669 setTop : function(top){
\r
13670 this.storeLeftTop(this.getLeft(true), top);
\r
13671 supr.setTop.apply(this, arguments);
\r
13675 setLeftTop : function(left, top){
\r
13676 this.storeLeftTop(left, top);
\r
13677 supr.setLeftTop.apply(this, arguments);
\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
13693 createCB : function(c){
\r
13695 return function(){
\r
13696 el.constrainXY();
\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
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
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
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
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
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
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
13754 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
\r
13760 setZIndex : function(zindex){
\r
13761 this.zindex = zindex;
\r
13762 this.setStyle("z-index", zindex + 2);
\r
13764 this.shadow.setZIndex(zindex + 1);
\r
13767 this.shim.setStyle("z-index", zindex);
\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
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
13786 a.l -= this.offset + rad;
\r
13787 a.t -= this.offset + rad;
\r
13798 a.l -= (this.offset - rad);
\r
13799 a.t -= this.offset + rad;
\r
13801 a.w -= (this.offset - rad)*2;
\r
13807 a.w = a.h = (o*2);
\r
13812 a.l -= (this.offset - rad);
\r
13813 a.t -= (this.offset - rad);
\r
13815 a.w -= (this.offset + rad + 1);
\r
13816 a.h -= (this.offset + rad);
\r
13822 this.adjusts = a;
\r
13825 Ext.Shadow.prototype = {
\r
13831 defaultMode: "drop",
\r
13834 show : function(target){
\r
13835 target = Ext.get(target);
\r
13837 this.el = Ext.Shadow.Pool.pull();
\r
13838 if(this.el.dom.nextSibling != target.dom){
\r
13839 this.el.insertBefore(target);
\r
13842 this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
\r
13844 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
\r
13847 target.getLeft(true),
\r
13848 target.getTop(true),
\r
13849 target.getWidth(),
\r
13850 target.getHeight()
\r
13852 this.el.dom.style.display = "block";
\r
13856 isVisible : function(){
\r
13857 return this.el ? true : false;
\r
13861 realign : function(l, t, w, h){
\r
13865 var a = this.adjusts, d = this.el.dom, s = d.style;
\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
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
13885 hide : function(){
\r
13887 this.el.dom.style.display = "none";
\r
13888 Ext.Shadow.Pool.push(this.el);
\r
13894 setZIndex : function(z){
\r
13897 this.el.setStyle("z-index", z);
\r
13902 // Private utility class that manages the internal Shadow cache
\r
13903 Ext.Shadow.Pool = function(){
\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
13909 pull : function(){
\r
13910 var sh = p.shift();
\r
13912 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
\r
13913 sh.autoBoxAdjust = false;
\r
13918 push : function(sh){
\r
13924 Ext.BoxComponent = Ext.extend(Ext.Component, {
\r
13937 initComponent : function(){
\r
13938 Ext.BoxComponent.superclass.initComponent.call(this);
\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
13953 setSize : function(w, h){
\r
13954 // support for standard size objects
\r
13955 if(typeof w == 'object'){
\r
13960 if(!this.boxReady){
\r
13966 // prevent recalcs when not needed
\r
13967 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
\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
13982 this.onResize(aw, ah, w, h);
\r
13983 this.fireEvent('resize', this, aw, ah, w, h);
\r
13989 setWidth : function(width){
\r
13990 return this.setSize(width);
\r
13994 setHeight : function(height){
\r
13995 return this.setSize(undefined, height);
\r
13999 getSize : function(){
\r
14000 return this.el.getSize();
\r
14004 getPosition : function(local){
\r
14005 if(local === true){
\r
14006 return [this.el.getLeft(true), this.el.getTop(true)];
\r
14008 return this.xy || this.el.getXY();
\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
14018 var xy = this.xy || this.el.getXY();
\r
14026 updateBox : function(box){
\r
14027 this.setSize(box.width, box.height);
\r
14028 this.setPagePosition(box.x, box.y);
\r
14033 getResizeEl : function(){
\r
14034 return this.resizeEl || this.el;
\r
14038 getPositionEl : function(){
\r
14039 return this.positionEl || this.el;
\r
14043 setPosition : function(x, y){
\r
14044 if(x && typeof x[1] == 'number'){
\r
14050 if(!this.boxReady){
\r
14053 var adj = this.adjustPosition(x, y);
\r
14054 var ax = adj.x, ay = adj.y;
\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
14062 }else if(ay !== undefined){
\r
14065 this.onPosition(ax, ay);
\r
14066 this.fireEvent('move', this, ax, ay);
\r
14072 setPagePosition : function(x, y){
\r
14073 if(x && typeof x[1] == 'number'){
\r
14079 if(!this.boxReady){
\r
14082 if(x === undefined || y === undefined){ // cannot translate undefined points
\r
14085 var p = this.el.translatePoints(x, y);
\r
14086 this.setPosition(p.left, p.top);
\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
14096 if(this.positionEl){
\r
14097 this.positionEl = Ext.get(this.positionEl);
\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
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
14121 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
\r
14126 onPosition : function(x, y){
\r
14131 adjustSize : function(w, h){
\r
14132 if(this.autoWidth){
\r
14135 if(this.autoHeight){
\r
14138 return {width : w, height: h};
\r
14142 adjustPosition : function(x, y){
\r
14143 return {x : x, y: y};
\r
14146 Ext.reg('box', Ext.BoxComponent);
\r
14148 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
\r
14151 this.el = Ext.get(dragElement, true);
\r
14152 this.el.dom.unselectable = "on";
\r
14154 this.resizingEl = Ext.get(resizingElement, true);
\r
14157 this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
\r
14160 this.minSize = 0;
\r
14163 this.maxSize = 2000;
\r
14166 this.animate = false;
\r
14169 this.useShim = false;
\r
14172 this.shim = null;
\r
14174 if(!existingProxy){
\r
14176 this.proxy = Ext.SplitBar.createProxy(this.orientation);
\r
14178 this.proxy = Ext.get(existingProxy).dom;
\r
14181 this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
\r
14184 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
\r
14187 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
\r
14190 this.dragSpecs = {};
\r
14193 this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
\r
14194 this.adapter.init(this);
\r
14196 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\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
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
14217 Ext.SplitBar.superclass.constructor.call(this);
\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: " "}, 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
14239 this.dd.setYConstraint(0, 0);
\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
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
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
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
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
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
14286 getAdapter : function(){
\r
14287 return this.adapter;
\r
14291 setAdapter : function(adapter){
\r
14292 this.adapter = adapter;
\r
14293 this.adapter.init(this);
\r
14297 getMinimumSize : function(){
\r
14298 return this.minSize;
\r
14302 setMinimumSize : function(minSize){
\r
14303 this.minSize = minSize;
\r
14307 getMaximumSize : function(){
\r
14308 return this.maxSize;
\r
14312 setMaximumSize : function(maxSize){
\r
14313 this.maxSize = maxSize;
\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
14325 destroy : function(removeEl){
\r
14327 this.shim.remove();
\r
14330 Ext.destroy(Ext.get(this.proxy));
\r
14332 this.el.remove();
\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
14348 Ext.SplitBar.BasicLayoutAdapter = function(){
\r
14351 Ext.SplitBar.BasicLayoutAdapter.prototype = {
\r
14352 // do nothing for now
\r
14353 init : function(s){
\r
14357 getElementSize : function(s){
\r
14358 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
14359 return s.resizingEl.getWidth();
\r
14361 return s.resizingEl.getHeight();
\r
14366 setElementSize : function(s, newSize, onComplete){
\r
14367 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
14369 s.resizingEl.setWidth(newSize);
\r
14371 onComplete(s, newSize);
\r
14374 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
\r
14379 s.resizingEl.setHeight(newSize);
\r
14381 onComplete(s, newSize);
\r
14384 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
\r
14391 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
\r
14392 this.basic = new Ext.SplitBar.BasicLayoutAdapter();
\r
14393 this.container = Ext.get(container);
\r
14396 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
\r
14397 init : function(s){
\r
14398 this.basic.init(s);
\r
14401 getElementSize : function(s){
\r
14402 return this.basic.getElementSize(s);
\r
14405 setElementSize : function(s, newSize, onComplete){
\r
14406 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
\r
14409 moveSplitter : function(s){
\r
14410 var yes = Ext.SplitBar;
\r
14411 switch(s.placement){
\r
14413 s.el.setX(s.resizingEl.getRight());
\r
14416 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
\r
14419 s.el.setY(s.resizingEl.getBottom());
\r
14422 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
\r
14429 Ext.SplitBar.VERTICAL = 1;
\r
14432 Ext.SplitBar.HORIZONTAL = 2;
\r
14435 Ext.SplitBar.LEFT = 1;
\r
14438 Ext.SplitBar.RIGHT = 2;
\r
14441 Ext.SplitBar.TOP = 3;
\r
14444 Ext.SplitBar.BOTTOM = 4;
\r
14447 Ext.Container = Ext.extend(Ext.BoxComponent, {
\r
14457 autoDestroy: true,
\r
14460 defaultType: 'panel',
\r
14463 initComponent : function(){
\r
14464 Ext.Container.superclass.initComponent.call(this);
\r
14480 var items = this.items;
\r
14482 delete this.items;
\r
14483 if(Ext.isArray(items) && items.length > 0){
\r
14484 this.add.apply(this, items);
\r
14492 initItems : function(){
\r
14494 this.items = new Ext.util.MixedCollection(false, this.getComponentId);
\r
14495 this.getLayout(); // initialize the layout
\r
14500 setLayout : function(layout){
\r
14501 if(this.layout && this.layout != layout){
\r
14502 this.layout.setContainer(null);
\r
14504 this.initItems();
\r
14505 this.layout = layout;
\r
14506 layout.setContainer(this);
\r
14510 render : function(){
\r
14511 Ext.Container.superclass.render.apply(this, arguments);
\r
14513 if(typeof this.layout == 'string'){
\r
14514 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
\r
14516 this.setLayout(this.layout);
\r
14518 if(this.activeItem !== undefined){
\r
14519 var item = this.activeItem;
\r
14520 delete this.activeItem;
\r
14521 this.layout.setActiveItem(item);
\r
14525 if(!this.ownerCt){
\r
14528 if(this.monitorResize === true){
\r
14529 Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
\r
14534 getLayoutTarget : function(){
\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
14544 add : function(comp){
\r
14546 this.initItems();
\r
14548 var a = arguments, len = a.length;
\r
14550 for(var i = 0; i < len; i++) {
\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
14566 insert : function(index, comp){
\r
14568 this.initItems();
\r
14570 var a = arguments, len = a.length;
\r
14572 for(var i = len-1; i >= 1; --i) {
\r
14573 this.insert(index, a[i]);
\r
14577 var c = this.lookupComponent(this.applyDefaults(comp));
\r
14579 if(c.ownerCt == this && this.items.indexOf(c) < index){
\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
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
14600 Ext.apply(c, this.defaults);
\r
14607 onBeforeAdd : function(item){
\r
14608 if(item.ownerCt){
\r
14609 item.ownerCt.remove(item, false);
\r
14611 if(this.hideBorders === true){
\r
14612 item.border = (item.border === true);
\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
14625 if(this.layout && this.layout.activeItem == c){
\r
14626 delete this.layout.activeItem;
\r
14628 this.fireEvent('remove', this, c);
\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
14643 getComponent : function(comp){
\r
14644 if(typeof comp == 'object'){
\r
14647 return this.items.get(comp);
\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
14661 createComponent : function(config){
\r
14662 return Ext.ComponentMgr.create(config, this.defaultType);
\r
14666 doLayout : function(shallow){
\r
14667 if(this.rendered && this.layout){
\r
14668 this.layout.layout();
\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
14682 getLayout : function(){
\r
14683 if(!this.layout){
\r
14684 var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
\r
14685 this.setLayout(layout);
\r
14687 return this.layout;
\r
14691 beforeDestroy : function(){
\r
14693 Ext.destroy.apply(Ext, this.items.items);
\r
14695 if(this.monitorResize){
\r
14696 Ext.EventManager.removeResizeListener(this.doLayout, this);
\r
14698 if (this.layout && this.layout.destroy) {
\r
14699 this.layout.destroy();
\r
14701 Ext.Container.superclass.beforeDestroy.call(this);
\r
14705 bubble : function(fn, scope, args){
\r
14708 if(fn.apply(scope || p, args || [p]) === false){
\r
14716 cascade : function(fn, scope, args){
\r
14717 if(fn.apply(scope || this, args || [this]) !== false){
\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
14724 fn.apply(scope || cs[i], args || [cs[i]]);
\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
14740 return m || null;
\r
14744 findByType : function(xtype, shallow){
\r
14745 return this.findBy(function(c){
\r
14746 return c.isXType(xtype, shallow);
\r
14751 find : function(prop, value){
\r
14752 return this.findBy(function(c){
\r
14753 return c[prop] === value;
\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
14769 Ext.Container.LAYOUTS = {};
\r
14770 Ext.reg('container', Ext.Container);
\r
14772 Ext.layout.ContainerLayout = function(config){
\r
14773 Ext.apply(this, config);
\r
14776 Ext.layout.ContainerLayout.prototype = {
\r
14783 monitorResize:false,
\r
14785 activeItem : null,
\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
14795 onLayout : function(ct, target){
\r
14796 this.renderAll(ct, target);
\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
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
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
14824 if (this.renderHidden && c != this.activeItem) {
\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
14832 if(typeof position == 'number'){
\r
14833 position = target.dom.childNodes[position];
\r
14835 target.dom.insertBefore(c.getEl().dom, position || null);
\r
14836 if (this.renderHidden && c != this.activeItem) {
\r
14843 onResize: function(){
\r
14844 if(this.container.collapsed){
\r
14847 var b = this.container.bufferResize;
\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
14853 this.resizeTask.delay(this.resizeBuffer);
\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
14866 ct.on('resize', this.onResize, this);
\r
14869 this.container = ct;
\r
14873 parseMargins : function(v){
\r
14874 var ms = v.split(' ');
\r
14875 var len = ms.length;
\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
14894 destroy : Ext.emptyFn
\r
14896 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
\r
14898 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
14900 monitorResize:true,
\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
14911 setItemSize : function(item, size){
\r
14912 if(item && size.height > 0){ // display none?
\r
14913 item.setSize(size);
\r
14917 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
\r
14919 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
\r
14921 deferredRender : false,
\r
14924 renderHidden : true,
\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
14933 this.activeItem = item;
\r
14940 renderAll : function(ct, target){
\r
14941 if(this.deferredRender){
\r
14942 this.renderItem(this.activeItem, undefined, target);
\r
14944 Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
\r
14948 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
\r
14950 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
14952 monitorResize:true,
\r
14955 getAnchorViewSize : function(ct, target){
\r
14956 return target.dom == document.body ?
\r
14957 target.getViewSize() : target.getStyleSize();
\r
14961 onLayout : function(ct, target){
\r
14962 Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
\r
14964 var size = this.getAnchorViewSize(ct, target);
\r
14966 var w = size.width, h = size.height;
\r
14968 if(w < 20 || h < 20){
\r
14972 // find the container anchoring size
\r
14974 if(ct.anchorSize){
\r
14975 if(typeof ct.anchorSize == 'number'){
\r
14976 aw = ct.anchorSize;
\r
14978 aw = ct.anchorSize.width;
\r
14979 ah = ct.anchorSize.height;
\r
14982 aw = ct.initialConfig.width;
\r
14983 ah = ct.initialConfig.height;
\r
14986 var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
\r
14987 for(i = 0; i < len; i++){
\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
14998 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
\r
14999 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
\r
15002 c.setSize(cw || undefined, ch || undefined);
\r
15009 parseAnchor : function(a, start, cstart){
\r
15010 if(a && a != 'none'){
\r
15012 if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor
\r
15013 var diff = cstart - start;
\r
15014 return function(v){
\r
15020 }else if(a.indexOf('%') != -1){
\r
15021 var ratio = parseFloat(a.replace('%', ''))*.01; // percentage
\r
15022 return function(v){
\r
15025 return Math.floor(v*ratio);
\r
15029 a = parseInt(a, 10);
\r
15030 if(!isNaN(a)){ // simple offset adjustment
\r
15031 return function(v){
\r
15044 adjustWidthAnchor : function(value, comp){
\r
15049 adjustHeightAnchor : function(value, comp){
\r
15055 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
\r
15057 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
15059 monitorResize:true,
\r
15062 extraCls: 'x-column',
\r
15064 scrollOffset : 0,
\r
15067 isValidParent : function(c, target){
\r
15068 return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;
\r
15072 onLayout : function(ct, target){
\r
15073 var cs = ct.items.items, len = cs.length, c, i;
\r
15075 if(!this.innerCt){
\r
15076 target.addClass('x-column-layout-ct');
\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
15083 this.renderAll(ct, this.innerCt);
\r
15085 var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();
\r
15087 if(size.width < 1 && size.height < 1){ // display none?
\r
15091 var w = size.width - target.getPadding('lr') - this.scrollOffset,
\r
15092 h = size.height - target.getPadding('tb'),
\r
15095 this.innerCt.setWidth(w);
\r
15097 // some columns can be percentages while others are fixed
\r
15098 // so we need to make 2 passes
\r
15100 for(i = 0; i < len; i++){
\r
15102 if(!c.columnWidth){
\r
15103 pw -= (c.getSize().width + c.getEl().getMargins('lr'));
\r
15107 pw = pw < 0 ? 0 : pw;
\r
15109 for(i = 0; i < len; i++){
\r
15111 if(c.columnWidth){
\r
15112 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));
\r
15120 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
\r
15122 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
15124 monitorResize:true,
\r
15126 rendered : false,
\r
15129 onLayout : function(ct, target){
\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
15136 for(var i = 0, len = items.length; i < len; i++) {
\r
15137 var c = items[i];
\r
15138 var pos = c.region;
\r
15140 collapsed.push(c);
\r
15142 c.collapsed = false;
\r
15144 c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
\r
15145 c.render(target, i);
\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
15152 this.rendered = true;
\r
15155 var size = target.getViewSize();
\r
15156 if(size.width < 20 || size.height < 20){ // display none?
\r
15158 this.restoreCollapsed = collapsed;
\r
15161 }else if(this.restoreCollapsed){
\r
15162 collapsed = this.restoreCollapsed;
\r
15163 delete this.restoreCollapsed;
\r
15166 var w = size.width, h = size.height;
\r
15167 var centerW = w, centerH = h, centerY = 0, centerX = 0;
\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
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
15180 centerY = b.height + b.y + m.bottom;
\r
15181 centerH -= centerY;
\r
15182 n.applyLayout(b);
\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
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
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
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
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
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
15224 c.applyLayout(centerBox);
\r
15227 for(var i = 0, len = collapsed.length; i < len; i++){
\r
15228 collapsed[i].collapse(false);
\r
15232 if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
\r
15233 target.repaint();
\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
15243 if(region.destroy){
\r
15244 region.destroy();
\r
15245 }else if (region.split){
\r
15246 region.split.destroy(true);
\r
15250 Ext.layout.BorderLayout.superclass.destroy.call(this);
\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
15262 if(typeof this.margins == 'string'){
\r
15263 this.margins = this.layout.parseMargins(this.margins);
\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
15270 if(this.collapseMode == 'mini' && !this.cmargins){
\r
15271 this.cmargins = {left:0,top:0,right:0,bottom:0};
\r
15273 this.cmargins = Ext.applyIf(this.cmargins || {},
\r
15274 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
\r
15279 Ext.layout.BorderLayout.Region.prototype = {
\r
15287 collapsible : false,
\r
15298 defaultMargins : {left:0,top:0,right:0,bottom:0},
\r
15300 defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
\r
15302 defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
\r
15305 isCollapsed : false,
\r
15312 render : function(ct, p){
\r
15314 p.el.enableDisplayMode();
\r
15315 this.targetEl = ct;
\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
15323 if(ps != 'center'){
\r
15324 p.allowQueuedExpand = false;
\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
15334 if(this.collapsible){
\r
15335 p.collapseEl = 'el';
\r
15336 p.slideAnchor = this.getSlideAnchor();
\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
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}"> </div>'
\r
15352 tt.disableFormats = true;
\r
15354 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
\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
15360 this.collapsedEl.enableDisplayMode('block');
\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: " "
\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
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
15377 if(this.floatable !== false){
\r
15378 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
\r
15379 this.collapsedEl.on("click", this.collapseClick, this);
\r
15383 return this.collapsedEl;
\r
15387 onExpandClick : function(e){
\r
15389 this.afterSlideIn();
\r
15390 this.panel.expand(false);
\r
15392 this.panel.expand();
\r
15397 onCollapseClick : function(e){
\r
15398 this.panel.collapse();
\r
15402 beforeCollapse : function(p, animate){
\r
15403 this.lastAnim = animate;
\r
15404 if(this.splitEl){
\r
15405 this.splitEl.hide();
\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
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
15419 this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
\r
15421 this.state.collapsed = true;
\r
15422 this.panel.saveState();
\r
15426 beforeExpand : function(animate){
\r
15427 var c = this.getCollapsedEl();
\r
15429 if(this.position == 'east' || this.position == 'west'){
\r
15430 this.panel.setSize(undefined, c.getHeight());
\r
15432 this.panel.setSize(c.getWidth(), undefined);
\r
15435 c.dom.style.visibility = 'hidden';
\r
15436 this.panel.el.setStyle('z-index', 100);
\r
15440 onExpand : function(){
\r
15441 this.isCollapsed = false;
\r
15442 if(this.splitEl){
\r
15443 this.splitEl.show();
\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
15452 collapseClick : function(e){
\r
15454 e.stopPropagation();
\r
15457 e.stopPropagation();
\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
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
15481 isVisible : function(){
\r
15482 return !this.panel.hidden;
\r
15486 getMargins : function(){
\r
15487 return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
\r
15491 getSize : function(){
\r
15492 return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
\r
15496 setPanel : function(panel){
\r
15497 this.panel = panel;
\r
15501 getMinWidth: function(){
\r
15502 return this.minWidth;
\r
15506 getMinHeight: function(){
\r
15507 return this.minHeight;
\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
15518 applyLayout : function(box){
\r
15519 if(this.isCollapsed){
\r
15520 this.applyLayoutCollapsed(box);
\r
15522 this.panel.setPosition(box.x, box.y);
\r
15523 this.panel.setSize(box.width, box.height);
\r
15528 beforeSlide: function(){
\r
15529 this.panel.beforeEffect();
\r
15533 afterSlide : function(){
\r
15534 this.panel.afterEffect();
\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
15548 "mouseover" : function(e){
\r
15554 this.el.on(this.autoHideHd);
\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
15567 clearMonitor : function(){
\r
15568 Ext.getDoc().un("click", this.slideInIf, this);
\r
15571 // these names are backwards but not changed for compat
\r
15573 slideOut : function(){
\r
15574 if(this.isSlid || this.el.hasActiveFx()){
\r
15577 this.isSlid = true;
\r
15578 var ts = this.panel.tools;
\r
15579 if(ts && ts.toggle){
\r
15580 ts.toggle.hide();
\r
15583 if(this.position == 'east' || this.position == 'west'){
\r
15584 this.panel.setSize(undefined, this.collapsedEl.getHeight());
\r
15586 this.panel.setSize(this.collapsedEl.getWidth(), undefined);
\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
15604 this.initAutoHide();
\r
15605 Ext.getDoc().on("click", this.slideInIf, this);
\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
15619 var ts = this.panel.tools;
\r
15620 if(ts && ts.toggle){
\r
15621 ts.toggle.show();
\r
15626 slideIn : function(cb){
\r
15627 if(!this.isSlid || this.el.hasActiveFx()){
\r
15628 Ext.callback(cb);
\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
15637 this.afterSlide();
\r
15638 this.afterSlideIn();
\r
15639 Ext.callback(cb);
\r
15646 this.afterSlideIn();
\r
15651 slideInIf : function(e){
\r
15652 if(!e.within(this.el)){
\r
15660 "east" : "right",
\r
15662 "south" : "bottom"
\r
15675 "west" : "tl-tr",
\r
15676 "east" : "tr-tl",
\r
15677 "north" : "tl-bl",
\r
15678 "south" : "bl-tl"
\r
15682 getAnchor : function(){
\r
15683 return this.anchors[this.position];
\r
15687 getCollapseAnchor : function(){
\r
15688 return this.canchors[this.position];
\r
15692 getSlideAnchor : function(){
\r
15693 return this.sanchors[this.position];
\r
15697 getAlignAdj : function(){
\r
15698 var cm = this.cmargins;
\r
15699 switch(this.position){
\r
15716 getExpandAdj : function(){
\r
15717 var c = this.collapsedEl, cm = this.cmargins;
\r
15718 switch(this.position){
\r
15720 return [-(cm.right+c.getWidth()+cm.left), 0];
\r
15723 return [cm.right+c.getWidth()+cm.left, 0];
\r
15726 return [0, -(cm.top+cm.bottom+c.getHeight())];
\r
15729 return [0, cm.top+cm.bottom+c.getHeight()];
\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
15742 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
\r
15744 splitTip : "Drag to resize.",
\r
15746 collapsibleSplitTip : "Drag to resize. Double click to hide.",
\r
15748 useSplitTips : false,
\r
15751 splitSettings : {
\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
15760 orientation: Ext.SplitBar.VERTICAL,
\r
15761 placement: Ext.SplitBar.BOTTOM,
\r
15762 maxFn : 'getVMaxSize',
\r
15763 minProp: 'minHeight',
\r
15764 maxProp: 'maxHeight'
\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
15774 orientation: Ext.SplitBar.HORIZONTAL,
\r
15775 placement: Ext.SplitBar.LEFT,
\r
15776 maxFn : 'getHMaxSize',
\r
15777 minProp: 'minWidth',
\r
15778 maxProp: 'maxWidth'
\r
15784 west : function(box){
\r
15785 if(this.isCollapsed){
\r
15786 return this.applyLayoutCollapsed(box);
\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
15796 east : function(box){
\r
15797 if(this.isCollapsed){
\r
15798 return this.applyLayoutCollapsed(box);
\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
15808 north : function(box){
\r
15809 if(this.isCollapsed){
\r
15810 return this.applyLayoutCollapsed(box);
\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
15820 south : function(box){
\r
15821 if(this.isCollapsed){
\r
15822 return this.applyLayoutCollapsed(box);
\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
15835 render : function(ct, p){
\r
15836 Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
\r
15838 var ps = this.position;
\r
15840 this.splitEl = ct.createChild({
\r
15841 cls: "x-layout-split x-layout-split-"+ps, html: " ",
\r
15842 id: this.panel.id + '-xsplit'
\r
15845 if(this.collapseMode == 'mini'){
\r
15846 this.miniSplitEl = this.splitEl.createChild({
\r
15847 cls: "x-layout-mini x-layout-mini-"+ps, html: " "
\r
15849 this.miniSplitEl.addClassOnOver('x-layout-mini-over');
\r
15850 this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
\r
15853 var s = this.splitSettings[ps];
\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
15864 this.splitEl.hide();
\r
15867 if(this.useSplitTips){
\r
15868 this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
\r
15870 if(this.collapsible){
\r
15871 this.splitEl.on("dblclick", this.onCollapseClick, this);
\r
15875 //docs inherit from superclass
\r
15876 getSize : function(){
\r
15877 if(this.isCollapsed){
\r
15878 return this.collapsedEl.getSize();
\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
15884 s.width += this.splitEl.dom.offsetWidth;
\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
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
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
15911 this.panel.setSize(newSize, s.height);
\r
15912 this.state.width = newSize;
\r
15914 this.layout.layout();
\r
15915 this.panel.saveState();
\r
15920 getSplitBar : function(){
\r
15921 return this.split;
\r
15925 destroy : function() {
\r
15927 this.miniSplitEl,
\r
15934 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
\r
15936 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
\r
15938 labelSeparator : ':',
\r
15941 getAnchorViewSize : function(ct, target){
\r
15942 return (ct.body||ct.el).getStyleSize();
\r
15946 setContainer : function(ct){
\r
15947 Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
\r
15949 if(ct.labelAlign){
\r
15950 ct.addClass('x-form-label-'+ct.labelAlign);
\r
15953 if(ct.hideLabels){
\r
15954 this.labelStyle = "display:none";
\r
15955 this.elementStyle = "padding-left:0;";
\r
15956 this.labelAdjust = 0;
\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
15966 if(ct.labelAlign == 'top'){
\r
15967 this.labelStyle = "width:auto;";
\r
15968 this.labelAdjust = 0;
\r
15969 this.elementStyle = "padding-left:0;";
\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
15982 t.disableFormats = true;
\r
15984 Ext.layout.FormLayout.prototype.fieldTpl = t;
\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
15994 if (ls.substr(-1, 1) != ';'){
\r
16003 renderItem : function(c, position, target){
\r
16004 if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){
\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
16013 if(typeof position == 'number'){
\r
16014 position = target.dom.childNodes[position] || null;
\r
16017 this.fieldTpl.insertBefore(position, args);
\r
16019 this.fieldTpl.append(target, args);
\r
16021 c.render('x-form-el-'+c.id);
\r
16023 Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
\r
16028 adjustWidthAnchor : function(value, comp){
\r
16029 return value - (comp.isFormField ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
\r
16033 isValidParent : function(c, target){
\r
16040 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
\r
16042 Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {
\r
16046 autoWidth : true,
\r
16048 titleCollapse : true,
\r
16050 hideCollapseTool : false,
\r
16052 collapseFirst : false,
\r
16056 sequence : false,
\r
16058 activeOnTop : false,
\r
16060 renderItem : function(c){
\r
16061 if(this.animate === false){
\r
16062 c.animCollapse = false;
\r
16064 c.collapsible = true;
\r
16065 if(this.autoWidth){
\r
16066 c.autoWidth = true;
\r
16068 if(this.titleCollapse){
\r
16069 c.titleCollapse = true;
\r
16071 if(this.hideCollapseTool){
\r
16072 c.hideCollapseTool = true;
\r
16074 if(this.collapseFirst !== undefined){
\r
16075 c.collapseFirst = this.collapseFirst;
\r
16077 if(!this.activeItem && !c.collapsed){
\r
16078 this.activeItem = c;
\r
16079 }else if(this.activeItem){
\r
16080 c.collapsed = true;
\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
16088 beforeExpand : function(p, anim){
\r
16089 var ai = this.activeItem;
\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
16100 ai.collapse(this.animate);
\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
16111 setItemSize : function(item, size){
\r
16112 if(this.fill && item){
\r
16113 var items = this.container.items.items;
\r
16115 for(var i = 0, len = items.length; i < len; i++){
\r
16116 var p = items[i];
\r
16118 hh += (p.getSize().height - p.bwrap.getHeight());
\r
16121 size.height -= hh;
\r
16122 item.setSize(size);
\r
16126 Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;
\r
16128 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
16132 monitorResize:false,
\r
16135 setContainer : function(ct){
\r
16136 Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
\r
16138 this.currentRow = 0;
\r
16139 this.currentColumn = 0;
\r
16144 onLayout : function(ct, target){
\r
16145 var cs = ct.items.items, len = cs.length, c, i;
\r
16148 target.addClass('x-table-layout-ct');
\r
16150 this.table = target.createChild(
\r
16151 {tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, null, true);
\r
16153 this.renderAll(ct, target);
\r
16158 getRow : function(index){
\r
16159 var row = this.table.tBodies[0].childNodes[index];
\r
16161 row = document.createElement('tr');
\r
16162 this.table.tBodies[0].appendChild(row);
\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
16175 for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
\r
16176 this.cells[rowIndex][colIndex] = true;
\r
16179 var td = document.createElement('td');
\r
16181 td.id = c.cellId;
\r
16183 var cls = 'x-table-layout-cell';
\r
16185 cls += ' ' + c.cellCls;
\r
16187 td.className = cls;
\r
16189 td.colSpan = c.colspan;
\r
16192 td.rowSpan = c.rowspan;
\r
16194 this.getRow(curRow).appendChild(td);
\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
16209 return [colIndex, rowIndex];
\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
16224 isValidParent : function(c, target){
\r
16231 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
\r
16233 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
\r
16235 extraCls: 'x-abs-layout-item',
\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
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
16251 getAnchorViewSize : function(ct, target){
\r
16252 return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);
\r
16256 isValidParent : function(c, target){
\r
16257 return this.isForm ? true : Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);
\r
16261 adjustWidthAnchor : function(value, comp){
\r
16262 return value ? value - comp.getPosition(true)[0] : value;
\r
16266 adjustHeightAnchor : function(value, comp){
\r
16267 return value ? value - comp.getPosition(true)[1] : value;
\r
16271 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
\r
16273 Ext.Viewport = Ext.extend(Ext.Container, {
\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
16301 fireResize : function(w, h){
\r
16302 this.fireEvent('resize', this, w, h, w, h);
\r
16305 Ext.reg('viewport', Ext.Viewport);
\r
16307 Ext.Panel = Ext.extend(Ext.Container, {
\r
16344 baseCls : 'x-panel',
\r
16346 collapsedCls : 'x-panel-collapsed',
\r
16348 maskDisabled: true,
\r
16350 animCollapse: Ext.enableFx,
\r
16352 headerAsText: true,
\r
16354 buttonAlign: 'right',
\r
16356 collapsed : false,
\r
16358 collapseFirst: true,
\r
16360 minButtonWidth:75,
\r
16362 elements : 'body',
\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
16372 // private, notify box this class will handle heights
\r
16373 deferHeight: true,
\r
16375 expandDefaults: {
\r
16379 collapseDefaults: {
\r
16384 initComponent : function(){
\r
16385 Ext.Panel.superclass.initComponent.call(this);
\r
16399 'beforecollapse',
\r
16414 this.elements += ',tbar';
\r
16415 if(typeof this.tbar == 'object'){
\r
16416 this.topToolbar = this.tbar;
\r
16418 delete this.tbar;
\r
16421 this.elements += ',bbar';
\r
16422 if(typeof this.bbar == 'object'){
\r
16423 this.bottomToolbar = this.bbar;
\r
16425 delete this.bbar;
\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
16435 if(this.footer === true){
\r
16436 this.elements += ',footer';
\r
16437 delete this.footer;
\r
16440 if(this.buttons){
\r
16441 var btns = this.buttons;
\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
16449 this.addButton(btns[i]);
\r
16453 if(this.autoLoad){
\r
16454 this.on('render', this.doAutoLoad, this, {delay:10});
\r
16459 createElement : function(name, pnode){
\r
16461 pnode.appendChild(this[name].dom);
\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
16469 var el = document.createElement('div');
\r
16470 el.className = this[name+'Cls'];
\r
16471 this[name] = Ext.get(pnode.appendChild(el));
\r
16473 if(this[name+'CssClass']){
\r
16474 this[name].addClass(this[name+'CssClass']);
\r
16476 if(this[name+'Style']){
\r
16477 this[name].applyStyles(this[name+'Style']);
\r
16483 onRender : function(ct, position){
\r
16484 Ext.Panel.superclass.onRender.call(this, ct, position);
\r
16486 this.createClasses();
\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
16499 this.el = ct.createChild({
\r
16501 cls: this.baseCls
\r
16504 var el = this.el, d = el.dom;
\r
16507 this.el.addClass(this.cls);
\r
16510 if(this.buttons){
\r
16511 this.elements += ',footer';
\r
16514 // This block allows for maximum flexibility and performance when using existing markup
\r
16516 // framing requires special markup
\r
16518 el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
\r
16520 this.createElement('header', d.firstChild.firstChild.firstChild);
\r
16521 this.createElement('bwrap', d);
\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
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
16535 if(!this.footer){
\r
16536 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
\r
16539 this.createElement('header', d);
\r
16540 this.createElement('bwrap', d);
\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
16549 if(!this.header){
\r
16550 this.body.addClass(this.bodyCls + '-noheader');
\r
16552 this.tbar.addClass(this.tbarCls + '-noheader');
\r
16557 if(this.border === false){
\r
16558 this.el.addClass(this.baseCls + '-noborder');
\r
16559 this.body.addClass(this.bodyCls + '-noborder');
\r
16561 this.header.addClass(this.headerCls + '-noborder');
\r
16564 this.footer.addClass(this.footerCls + '-noborder');
\r
16567 this.tbar.addClass(this.tbarCls + '-noborder');
\r
16570 this.bbar.addClass(this.bbarCls + '-noborder');
\r
16574 if(this.bodyBorder === false){
\r
16575 this.body.addClass(this.bodyCls + '-noborder');
\r
16578 this.bwrap.enableDisplayMode('block');
\r
16581 this.header.unselectable();
\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
16588 if(this.iconCls){
\r
16589 this.setIconClass(this.iconCls);
\r
16594 if(this.floating){
\r
16595 this.makeFloating(this.floating);
\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
16603 handler : this.toggleCollapse,
\r
16607 if(this.titleCollapse && this.header){
\r
16608 this.header.on('click', this.toggleCollapse, this);
\r
16609 this.header.setStyle('cursor', 'pointer');
\r
16613 var ts = this.tools;
\r
16615 this.addTool.apply(this, ts);
\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
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
16635 if(this.tbar && this.topToolbar){
\r
16636 if(Ext.isArray(this.topToolbar)){
\r
16637 this.topToolbar = new Ext.Toolbar(this.topToolbar);
\r
16639 this.topToolbar.render(this.tbar);
\r
16640 this.topToolbar.ownerCt = this;
\r
16642 if(this.bbar && this.bottomToolbar){
\r
16643 if(Ext.isArray(this.bottomToolbar)){
\r
16644 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
\r
16646 this.bottomToolbar.render(this.bbar);
\r
16647 this.bottomToolbar.ownerCt = this;
\r
16652 setIconClass : function(cls){
\r
16653 var old = this.iconCls;
\r
16654 this.iconCls = cls;
\r
16655 if(this.rendered && this.header){
\r
16657 this.header.addClass('x-panel-icon');
\r
16658 this.header.replaceClass(old, this.iconCls);
\r
16660 var hd = this.header.dom;
\r
16661 var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
\r
16663 Ext.fly(img).replaceClass(old, this.iconCls);
\r
16665 Ext.DomHelper.insertBefore(hd.firstChild, {
\r
16666 tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
\r
16671 this.fireEvent('iconchange', this, cls, old);
\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
16682 shim: this.shim === false ? false : undefined
\r
16688 getTopToolbar : function(){
\r
16689 return this.topToolbar;
\r
16693 getBottomToolbar : function(){
\r
16694 return this.bottomToolbar;
\r
16698 addButton : function(config, handler, scope){
\r
16700 handler: handler,
\r
16702 minWidth: this.minButtonWidth,
\r
16705 if(typeof config == "string"){
\r
16706 bc.text = config;
\r
16708 Ext.apply(bc, config);
\r
16710 var btn = new Ext.Button(bc);
\r
16711 btn.ownerCt = this;
\r
16712 if(!this.buttons){
\r
16713 this.buttons = [];
\r
16715 this.buttons.push(btn);
\r
16720 addTool : function(){
\r
16721 if(!this[this.toolTarget]) { // no where to render tools!
\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}"> </div>'
\r
16729 tt.disableFormats = true;
\r
16731 Ext.Panel.prototype.toolTemplate = tt;
\r
16733 for(var i = 0, a = arguments, len = a.length; i < len; 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
16748 if(typeof tc.qtip == 'object'){
\r
16749 Ext.QuickTips.register(Ext.apply({
\r
16753 t.dom.qtip = tc.qtip;
\r
16756 t.addClassOnOver(overCls);
\r
16762 onShow : function(){
\r
16763 if(this.floating){
\r
16764 return this.el.show();
\r
16766 Ext.Panel.superclass.onShow.call(this);
\r
16770 onHide : function(){
\r
16771 if(this.floating){
\r
16772 return this.el.hide();
\r
16774 Ext.Panel.superclass.onHide.call(this);
\r
16778 createToolHandler : function(t, tc, overCls, panel){
\r
16779 return function(e){
\r
16780 t.removeClass(overCls);
\r
16783 tc.handler.call(tc.scope || t, e, t, panel);
\r
16789 afterRender : function(){
\r
16790 if(this.fromMarkup && this.height === undefined && !this.autoHeight){
\r
16791 this.height = this.el.getHeight();
\r
16793 if(this.floating && !this.hidden && !this.initHidden){
\r
16797 this.setTitle(this.title);
\r
16799 this.setAutoScroll();
\r
16801 this.body.update(typeof this.html == 'object' ?
\r
16802 Ext.DomHelper.markup(this.html) :
\r
16804 delete this.html;
\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
16811 if(this.collapsed){
\r
16812 this.collapsed = false;
\r
16813 this.collapse(false);
\r
16815 Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
\r
16816 this.initEvents();
\r
16820 setAutoScroll : function(){
\r
16821 if(this.rendered && this.autoScroll){
\r
16822 var el = this.body || this.el;
\r
16824 el.setOverflow('auto');
\r
16830 getKeyMap : function(){
\r
16831 if(!this.keyMap){
\r
16832 this.keyMap = new Ext.KeyMap(this.el, this.keys);
\r
16834 return this.keyMap;
\r
16838 initEvents : function(){
\r
16840 this.getKeyMap();
\r
16842 if(this.draggable){
\r
16843 this.initDraggable();
\r
16848 initDraggable : function(){
\r
16850 this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
\r
16854 beforeEffect : function(){
\r
16855 if(this.floating){
\r
16856 this.el.beforeAction();
\r
16858 this.el.addClass('x-panel-animated');
\r
16862 afterEffect : function(){
\r
16863 this.syncShadow();
\r
16864 this.el.removeClass('x-panel-animated');
\r
16867 // private - wraps up an animation param with internal callbacks
\r
16868 createEffect : function(a, cb, scope){
\r
16876 }else if(!a.callback){
\r
16878 }else { // wrap it up
\r
16879 o.callback = function(){
\r
16881 Ext.callback(a.callback, a.scope);
\r
16884 return Ext.applyIf(o, a);
\r
16888 collapse : function(animate){
\r
16889 if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
\r
16892 var doAnim = animate === true || (animate !== false && this.animCollapse);
\r
16893 this.beforeEffect();
\r
16894 this.onCollapse(doAnim, animate);
\r
16899 onCollapse : function(doAnim, animArg){
\r
16901 this[this.collapseEl].slideOut(this.slideAnchor,
\r
16902 Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
\r
16903 this.collapseDefaults));
\r
16905 this[this.collapseEl].hide();
\r
16906 this.afterCollapse();
\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
16919 expand : function(animate){
\r
16920 if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
\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
16931 onExpand : function(doAnim, animArg){
\r
16933 this[this.collapseEl].slideIn(this.slideAnchor,
\r
16934 Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
\r
16935 this.expandDefaults));
\r
16937 this[this.collapseEl].show();
\r
16938 this.afterExpand();
\r
16943 afterExpand : function(){
\r
16944 this.collapsed = false;
\r
16945 this.afterEffect();
\r
16946 this.fireEvent('expand', this);
\r
16950 toggleCollapse : function(animate){
\r
16951 this[this.collapsed ? 'expand' : 'collapse'](animate);
\r
16956 onDisable : function(){
\r
16957 if(this.rendered && this.maskDisabled){
\r
16960 Ext.Panel.superclass.onDisable.call(this);
\r
16964 onEnable : function(){
\r
16965 if(this.rendered && this.maskDisabled){
\r
16966 this.el.unmask();
\r
16968 Ext.Panel.superclass.onEnable.call(this);
\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
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
16989 if(this.disabled && this.el._mask){
\r
16990 this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
\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
17000 }, this, {single:true});
\r
17003 this.fireEvent('bodyresize', this, w, h);
\r
17005 this.syncShadow();
\r
17009 adjustBodyHeight : function(h){
\r
17014 adjustBodyWidth : function(w){
\r
17019 onPosition : function(){
\r
17020 this.syncShadow();
\r
17024 getFrameWidth : function(){
\r
17025 var w = this.el.getFrameWidth('lr');
\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
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
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
17049 h += (this.header ? this.header.getHeight() : 0) +
\r
17050 (this.footer ? this.footer.getHeight() : 0);
\r
17056 getInnerWidth : function(){
\r
17057 return this.getSize().width - this.getFrameWidth();
\r
17061 getInnerHeight : function(){
\r
17062 return this.getSize().height - this.getFrameHeight();
\r
17066 syncShadow : function(){
\r
17067 if(this.floating){
\r
17068 this.el.sync(true);
\r
17073 getLayoutTarget : function(){
\r
17074 return this.body;
\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
17084 this.setIconClass(iconCls);
\r
17086 this.fireEvent('titlechange', this, title);
\r
17091 getUpdater : function(){
\r
17092 return this.body.getUpdater();
\r
17096 load : function(){
\r
17097 var um = this.body.getUpdater();
\r
17098 um.update.apply(um, arguments);
\r
17103 beforeDestroy : function(){
\r
17105 this.header.removeAllListeners();
\r
17106 if(this.headerAsText){
\r
17107 Ext.Element.uncache(this.header.child('span'));
\r
17110 Ext.Element.uncache(
\r
17119 for(var k in this.tools){
\r
17120 Ext.destroy(this.tools[k]);
\r
17123 if(this.buttons){
\r
17124 for(var b in this.buttons){
\r
17125 Ext.destroy(this.buttons[b]);
\r
17130 this.bottomToolbar
\r
17132 Ext.Panel.superclass.beforeDestroy.call(this);
\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
17147 createGhost : function(cls, useShim, appendTo){
\r
17148 var el = document.createElement('div');
\r
17149 el.className = 'x-panel-ghost ' + (cls ? cls : '');
\r
17151 el.appendChild(this.el.dom.firstChild.cloneNode(true));
\r
17153 Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
\r
17154 el.style.width = this.el.dom.offsetWidth + 'px';;
\r
17156 this.container.dom.appendChild(el);
\r
17158 Ext.getDom(appendTo).appendChild(el);
\r
17160 if(useShim !== false && this.el.useShim !== false){
\r
17161 var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
\r
17165 return new Ext.Element(el);
\r
17170 doAutoLoad : function(){
\r
17172 typeof this.autoLoad == 'object' ?
\r
17173 this.autoLoad : {url: this.autoLoad});
\r
17177 getTool: function(id) {
\r
17178 return this.tools[id];
\r
17183 Ext.reg('panel', Ext.Panel);
\r
17186 Ext.Window = Ext.extend(Ext.Panel, {
\r
17199 baseCls : 'x-window',
\r
17209 constrainHeader:false,
\r
17213 minimizable : false,
\r
17215 maximizable : false,
\r
17221 expandOnShow: true,
\r
17223 closeAction: 'close',
\r
17225 elements: 'header,body',
\r
17227 // inherited docs, same default
\r
17228 collapsible:false,
\r
17231 initHidden : true,
\r
17233 monitorResize : true,
\r
17240 initComponent : function(){
\r
17241 Ext.Window.superclass.initComponent.call(this);
\r
17257 getState : function(){
\r
17258 return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox());
\r
17262 onRender : function(ct, position){
\r
17263 Ext.Window.superclass.onRender.call(this, ct, position);
\r
17266 this.el.addClass('x-window-plain');
\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: " "});
\r
17273 this.focusEl.swallowEvent('click', true);
\r
17275 this.proxy = this.el.createProxy("x-window-proxy");
\r
17276 this.proxy.enableDisplayMode('block');
\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
17287 initEvents : function(){
\r
17288 Ext.Window.superclass.initEvents.call(this);
\r
17289 if(this.animateTarget){
\r
17290 this.setAnimateTarget(this.animateTarget);
\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
17299 resizeElement : this.resizerAction
\r
17301 this.resizer.window = this;
\r
17302 this.resizer.on("beforeresize", this.beforeResize, this);
\r
17305 if(this.draggable){
\r
17306 this.header.addClass("x-window-draggable");
\r
17308 this.initTools();
\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
17318 if(this.closable){
\r
17319 var km = this.getKeyMap();
\r
17320 km.on(27, this.onEsc, this);
\r
17325 initDraggable : function(){
\r
17327 this.dd = new Ext.Window.DD(this);
\r
17331 onEsc : function(){
\r
17332 this[this.closeAction]();
\r
17336 beforeDestroy : function(){
\r
17338 if(this.doAnchor){
\r
17339 Ext.EventManager.removeResizeListener(this.doAnchor, this);
\r
17340 Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
\r
17349 Ext.Window.superclass.beforeDestroy.call(this);
\r
17353 onDestroy : function(){
\r
17354 if(this.manager){
\r
17355 this.manager.unregister(this);
\r
17357 Ext.Window.superclass.onDestroy.call(this);
\r
17361 initTools : function(){
\r
17362 if(this.minimizable){
\r
17365 handler: this.minimize.createDelegate(this, [])
\r
17368 if(this.maximizable){
\r
17371 handler: this.maximize.createDelegate(this, [])
\r
17375 handler: this.restore.createDelegate(this, []),
\r
17378 this.header.on('dblclick', this.toggleMaximize, this);
\r
17380 if(this.closable){
\r
17383 handler: this[this.closeAction].createDelegate(this, [])
\r
17389 resizerAction : function(){
\r
17390 var box = this.proxy.getBox();
\r
17391 this.proxy.hide();
\r
17392 this.window.handleResize(box);
\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
17404 updateHandles : function(){
\r
17405 if(Ext.isIE && this.resizer){
\r
17406 this.resizer.syncHandleHeight();
\r
17407 this.el.repaint();
\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
17417 this.setSize(box);
\r
17420 this.updateHandles();
\r
17421 this.saveState();
\r
17425 this.fireEvent("resize", this, box.width, box.height);
\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
17440 f.focus.defer(10, f);
\r
17444 setAnimateTarget : function(el){
\r
17445 el = Ext.get(el);
\r
17446 this.animateTarget = el;
\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
17459 this.el.setLeftTop(this.x, this.y);
\r
17461 if(this.expandOnShow){
\r
17462 this.expand(false);
\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
17473 show : function(animateTarget, cb, scope){
\r
17474 if(!this.rendered){
\r
17475 this.render(Ext.getBody());
\r
17477 if(this.hidden === false){
\r
17481 if(this.fireEvent("beforeshow", this) === false){
\r
17485 this.on('show', cb, scope, {single:true});
\r
17487 this.hidden = false;
\r
17488 if(animateTarget !== undefined){
\r
17489 this.setAnimateTarget(animateTarget);
\r
17491 this.beforeShow();
\r
17492 if(this.animateTarget){
\r
17495 this.afterShow();
\r
17500 afterShow : function(){
\r
17501 this.proxy.hide();
\r
17502 this.el.setStyle('display', 'block');
\r
17504 if(this.maximized){
\r
17505 this.fitContainer();
\r
17507 if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
\r
17508 this.cascade(this.setAutoScroll);
\r
17511 if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
\r
17512 Ext.EventManager.onWindowResize(this.onWindowResize, this);
\r
17514 this.doConstrain();
\r
17519 this.keyMap.enable();
\r
17522 this.updateHandles();
\r
17523 this.fireEvent("show", this);
\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
17534 b.duration = .25;
\r
17535 b.easing = 'easeNone';
\r
17538 this.el.setStyle('display', 'none');
\r
17539 this.proxy.shift(b);
\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
17548 if(this.hidden || this.fireEvent("beforehide", this) === false){
\r
17552 this.on('hide', cb, scope, {single:true});
\r
17554 this.hidden = true;
\r
17555 if(animateTarget !== undefined){
\r
17556 this.setAnimateTarget(animateTarget);
\r
17558 if(this.animateTarget){
\r
17562 this.afterHide();
\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
17573 this.mask.hide();
\r
17574 Ext.getBody().removeClass("x-body-masked");
\r
17577 this.keyMap.disable();
\r
17579 this.fireEvent("hide", this);
\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
17589 var b = this.animateTarget.getBox();
\r
17590 b.callback = this.afterHide;
\r
17592 b.duration = .25;
\r
17593 b.easing = 'easeNone';
\r
17596 this.proxy.shift(b);
\r
17600 onWindowResize : function(){
\r
17601 if(this.maximized){
\r
17602 this.fitContainer();
\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
17609 this.doConstrain();
\r
17613 doConstrain : function(){
\r
17614 if(this.constrain || this.constrainHeader){
\r
17616 if(this.constrain){
\r
17618 right:this.el.shadowOffset,
\r
17619 left:this.el.shadowOffset,
\r
17620 bottom:this.el.shadowOffset
\r
17623 var s = this.getSize();
\r
17625 right:-(s.width - 100),
\r
17626 bottom:-(s.height - 25)
\r
17630 var xy = this.el.getConstrainToXY(this.container, true, offsets);
\r
17632 this.setPosition(xy[0], xy[1]);
\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
17644 this.activeGhost = ghost;
\r
17649 unghost : function(show, matchPosition){
\r
17650 if(show !== false){
\r
17653 if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
\r
17654 this.cascade(this.setAutoScroll);
\r
17657 if(matchPosition !== false){
\r
17658 this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
\r
17660 this.activeGhost.hide();
\r
17661 this.activeGhost.remove();
\r
17662 delete this.activeGhost;
\r
17666 minimize : function(){
\r
17667 this.fireEvent('minimize', this);
\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
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
17690 this.maximized = true;
\r
17691 this.el.disableShadow();
\r
17696 if(this.collapsible){
\r
17697 this.tools.toggle.hide();
\r
17699 this.el.addClass('x-window-maximized');
\r
17700 this.container.addClass('x-window-maximized-ct');
\r
17702 this.setPosition(0, 0);
\r
17703 this.fitContainer();
\r
17704 this.fireEvent('maximize', this);
\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
17722 this.dd.unlock();
\r
17724 if(this.collapsible){
\r
17725 this.tools.toggle.show();
\r
17727 this.container.removeClass('x-window-maximized-ct');
\r
17729 this.doConstrain();
\r
17730 this.fireEvent('restore', this);
\r
17735 toggleMaximize : function(){
\r
17736 this[this.maximized ? 'restore' : 'maximize']();
\r
17740 fitContainer : function(){
\r
17741 var vs = this.container.getViewSize();
\r
17742 this.setSize(vs.width, vs.height);
\r
17746 // z-index is managed by the WindowManager and may be overwritten at any time
\r
17747 setZIndex : function(index){
\r
17749 this.mask.setStyle("z-index", index);
\r
17751 this.el.setZIndex(++index);
\r
17754 if(this.resizer){
\r
17755 this.resizer.proxy.setStyle("z-index", ++index);
\r
17758 this.lastZIndex = index;
\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
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
17774 this.doAnchor = function(){
\r
17775 this.alignTo(el, alignment, offsets);
\r
17777 Ext.EventManager.onWindowResize(this.doAnchor, this);
\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
17789 toFront : function(e){
\r
17790 if(this.manager.bringToFront(this)){
\r
17791 if(!e || !e.getTarget().focus){
\r
17799 setActive : function(active){
\r
17801 if(!this.maximized){
\r
17802 this.el.enableShadow(true);
\r
17804 this.fireEvent('activate', this);
\r
17806 this.el.disableShadow();
\r
17807 this.fireEvent('deactivate', this);
\r
17812 toBack : function(){
\r
17813 this.manager.sendToBack(this);
\r
17818 center : function(){
\r
17819 var xy = this.el.getAlignToXY(this.container, 'c-c');
\r
17820 this.setPagePosition(xy[0], xy[1]);
\r
17826 Ext.reg('window', Ext.Window);
\r
17828 // private - custom Window DD implementation
\r
17829 Ext.Window.DD = function(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
17836 Ext.extend(Ext.Window.DD, Ext.dd.DD, {
\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
17850 b4Drag : Ext.emptyFn,
\r
17852 onDrag : function(e){
\r
17853 this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
\r
17856 endDrag : function(e){
\r
17857 this.win.unghost();
\r
17858 this.win.saveState();
\r
17863 Ext.WindowGroup = function(){
\r
17865 var accessList = [];
\r
17866 var front = null;
\r
17869 var sortWindows = function(d1, d2){
\r
17870 return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
\r
17874 var orderWindows = function(){
\r
17875 var a = accessList, len = a.length;
\r
17877 a.sort(sortWindows);
\r
17878 var seed = a[0].manager.zseed;
\r
17879 for(var i = 0; i < len; i++){
\r
17881 if(win && !win.hidden){
\r
17882 win.setZIndex(seed + (i*10));
\r
17890 var setActiveWin = function(win){
\r
17891 if(win != front){
\r
17893 front.setActive(false);
\r
17897 win.setActive(true);
\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
17910 // none to activate
\r
17911 setActiveWin(null);
\r
17919 register : function(win){
\r
17920 list[win.id] = win;
\r
17921 accessList.push(win);
\r
17922 win.on('hide', activateLast);
\r
17926 unregister : function(win){
\r
17927 delete list[win.id];
\r
17928 win.un('hide', activateLast);
\r
17929 accessList.remove(win);
\r
17933 get : function(id){
\r
17934 return typeof id == "object" ? id : list[id];
\r
17938 bringToFront : function(win){
\r
17939 win = this.get(win);
\r
17940 if(win != front){
\r
17941 win._lastAccess = new Date().getTime();
\r
17949 sendToBack : function(win){
\r
17950 win = this.get(win);
\r
17951 win._lastAccess = -(new Date().getTime());
\r
17957 hideAll : function(){
\r
17958 for(var id in list){
\r
17959 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
\r
17966 getActive : function(){
\r
17971 getBy : function(fn, scope){
\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
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
17997 Ext.WindowMgr = new Ext.WindowGroup();
\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
18005 Ext.dd.PanelProxy.prototype = {
\r
18007 insertProxy : true,
\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
18017 getEl : function(){
\r
18018 return this.ghost;
\r
18022 getGhost : function(){
\r
18023 return this.ghost;
\r
18027 getProxy : function(){
\r
18028 return this.proxy;
\r
18032 hide : function(){
\r
18035 this.proxy.remove();
\r
18036 delete this.proxy;
\r
18038 this.panel.el.dom.style.display = '';
\r
18039 this.ghost.remove();
\r
18040 delete this.ghost;
\r
18045 show : function(){
\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
18053 this.panel.el.dom.style.display = 'none';
\r
18058 repair : function(xy, callback, scope){
\r
18060 if(typeof callback == "function"){
\r
18061 callback.call(scope || this);
\r
18066 moveProxy : function(parentNode, before){
\r
18068 parentNode.insertBefore(this.proxy.dom, before);
\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
18081 this.setHandleElId(h.id);
\r
18083 (h ? h : this.panel.body).setStyle('cursor', 'move');
\r
18084 this.scroll = false;
\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
18093 b4MouseDown: function(e) {
\r
18094 var x = e.getPageX();
\r
18095 var y = e.getPageY();
\r
18096 this.autoOffset(x, y);
\r
18098 onInitDrag : function(x, y){
\r
18099 this.onStartDrag(x, y);
\r
18102 createFrame : Ext.emptyFn,
\r
18103 getDragEl : function(e){
\r
18104 return this.proxy.ghost.dom;
\r
18106 endDrag : function(e){
\r
18107 this.proxy.hide();
\r
18108 this.panel.saveState();
\r
18111 autoOffset : function(x, y) {
\r
18112 x -= this.startPageX;
\r
18113 y -= this.startPageY;
\r
18114 this.setDelta(x, y);
\r
18118 Ext.state.Provider = function(){
\r
18120 this.addEvents("statechange");
\r
18122 Ext.state.Provider.superclass.constructor.call(this);
\r
18124 Ext.extend(Ext.state.Provider, Ext.util.Observable, {
\r
18126 get : function(name, defaultValue){
\r
18127 return typeof this.state[name] == "undefined" ?
\r
18128 defaultValue : this.state[name];
\r
18132 clear : function(name){
\r
18133 delete this.state[name];
\r
18134 this.fireEvent("statechange", this, name, null);
\r
18138 set : function(name, value){
\r
18139 this.state[name] = value;
\r
18140 this.fireEvent("statechange", this, name, value);
\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
18152 return parseFloat(v);
\r
18154 return new Date(Date.parse(v));
\r
18156 return (v == "1");
\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
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
18178 encodeValue : function(v){
\r
18180 if(typeof v == "number"){
\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
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
18192 enc = "a:" + flat;
\r
18193 }else if(typeof v == "object"){
\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
18200 enc = "o:" + flat.substring(0, flat.length-1);
\r
18204 return escape(enc);
\r
18209 Ext.state.Manager = function(){
\r
18210 var provider = new Ext.state.Provider();
\r
18214 setProvider : function(stateProvider){
\r
18215 provider = stateProvider;
\r
18219 get : function(key, defaultValue){
\r
18220 return provider.get(key, defaultValue);
\r
18224 set : function(key, value){
\r
18225 provider.set(key, value);
\r
18229 clear : function(key){
\r
18230 provider.clear(key);
\r
18234 getProvider : function(){
\r
18241 Ext.state.CookieProvider = function(config){
\r
18242 Ext.state.CookieProvider.superclass.constructor.call(this);
\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
18251 Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {
\r
18253 set : function(name, value){
\r
18254 if(typeof value == "undefined" || value === null){
\r
18255 this.clear(name);
\r
18258 this.setCookie(name, value);
\r
18259 Ext.state.CookieProvider.superclass.set.call(this, name, value);
\r
18263 clear : function(name){
\r
18264 this.clearCookie(name);
\r
18265 Ext.state.CookieProvider.superclass.clear.call(this, name);
\r
18269 readCookies : function(){
\r
18270 var cookies = {};
\r
18271 var c = document.cookie + ";";
\r
18272 var re = /\s?(.*?)=(.*?);/g;
\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
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
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
18302 Ext.DataView = Ext.extend(Ext.BoxComponent, {
\r
18312 selectedClass : "x-view-selected",
\r
18317 deferEmptyText: true,
\r
18319 trackOver: false,
\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
18342 "containerclick",
\r
18348 "selectionchange",
\r
18354 this.all = new Ext.CompositeElementLite();
\r
18355 this.selected = new Ext.CompositeElementLite();
\r
18359 onRender : function(){
\r
18361 this.el = document.createElement('div');
\r
18362 this.el.id = this.id;
\r
18364 Ext.DataView.superclass.onRender.apply(this, arguments);
\r
18368 afterRender : function(){
\r
18369 Ext.DataView.superclass.afterRender.call(this);
\r
18372 "click": this.onClick,
\r
18373 "dblclick": this.onDblClick,
\r
18374 "contextmenu": this.onContextMenu,
\r
18378 if(this.overClass || this.trackOver){
\r
18380 "mouseover": this.onMouseOver,
\r
18381 "mouseout": this.onMouseOut,
\r
18387 this.setStore(this.store, true);
\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
18400 this.hasSkippedEmptyText = true;
\r
18401 this.all.clear();
\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
18410 prepareData : function(data){
\r
18415 collectData : function(records, startIndex){
\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
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
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
18437 this.all.replaceElement(index, node, true);
\r
18439 this.selected.replaceElement(original, node);
\r
18440 this.all.item(index).addClass(this.selectedClass);
\r
18442 this.updateIndexes(index, index);
\r
18446 onAdd : function(ds, records, index){
\r
18447 if(this.all.getCount() == 0){
\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
18456 n = this.all.last().insertSibling(nodes, 'after', true);
\r
18457 a.push.apply(a, nodes);
\r
18459 this.updateIndexes(index);
\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
18470 refreshNode : function(index){
\r
18471 this.onUpdate(this.store, this.store.getAt(index));
\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
18485 getStore : function(){
\r
18486 return this.store;
\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
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
18508 this.store = store;
\r
18515 findItemFromChild : function(node){
\r
18516 return Ext.fly(node).findParent(this.itemSelector, this.el);
\r
18520 onClick : function(e){
\r
18521 var item = e.getTarget(this.itemSelector, this.el);
\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
18528 if(this.fireEvent("containerclick", this, e) !== false){
\r
18529 this.clearSelections();
\r
18535 onContextMenu : function(e){
\r
18536 var item = e.getTarget(this.itemSelector, this.el);
\r
18538 this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
\r
18543 onDblClick : function(e){
\r
18544 var item = e.getTarget(this.itemSelector, this.el);
\r
18546 this.fireEvent("dblclick", this, this.indexOf(item), item, e);
\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
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
18572 onItemClick : function(item, index, e){
\r
18573 if(this.fireEvent("beforeclick", this, index, item, e) === false){
\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
18587 doSingleSelection : function(item, index, e){
\r
18588 if(e.ctrlKey && this.isSelected(index)){
\r
18589 this.deselect(index);
\r
18591 this.select(index, false);
\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
18602 if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
\r
18603 this.deselect(index);
\r
18605 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
\r
18611 getSelectionCount : function(){
\r
18612 return this.selected.getCount()
\r
18616 getSelectedNodes : function(){
\r
18617 return this.selected.elements;
\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
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
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
18648 getRecord : function(node){
\r
18649 return this.store.getAt(node.viewIndex);
\r
18653 clearSelections : function(suppressEvent, skipUpdate){
\r
18654 if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
\r
18656 this.selected.removeClass(this.selectedClass);
\r
18658 this.selected.clear();
\r
18659 this.last = false;
\r
18660 if(!suppressEvent){
\r
18661 this.fireEvent("selectionchange", this, this.selected.elements);
\r
18667 isSelected : function(node){
\r
18668 return this.selected.contains(this.getNode(node));
\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
18679 Ext.fly(node).removeClass(this.selectedClass);
\r
18680 this.fireEvent("selectionchange", this, this.selected.elements);
\r
18685 select : function(nodeInfo, keepExisting, suppressEvent){
\r
18686 if(Ext.isArray(nodeInfo)){
\r
18687 if(!keepExisting){
\r
18688 this.clearSelections(true);
\r
18690 for(var i = 0, len = nodeInfo.length; i < len; i++){
\r
18691 this.select(nodeInfo[i], true, true);
\r
18693 if(!suppressEvent){
\r
18694 this.fireEvent("selectionchange", this, this.selected.elements);
\r
18697 var node = this.getNode(nodeInfo);
\r
18698 if(!keepExisting){
\r
18699 this.clearSelections(true);
\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
18715 selectRange : function(start, end, keepExisting){
\r
18716 if(!keepExisting){
\r
18717 this.clearSelections(true);
\r
18719 this.select(this.getNodes(start, end), true);
\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
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
18743 for(i = start; i >= end && ns[i]; i--){
\r
18744 nodes.push(ns[i]);
\r
18751 indexOf : function(node){
\r
18752 node = this.getNode(node);
\r
18753 if(typeof node.viewIndex == "number"){
\r
18754 return node.viewIndex;
\r
18756 return this.all.indexOf(node);
\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
18768 onDestroy : function(){
\r
18769 Ext.DataView.superclass.onDestroy.call(this);
\r
18770 this.setStore(null);
\r
18774 Ext.reg('dataview', Ext.DataView);
\r
18776 Ext.ColorPalette = function(config){
\r
18777 Ext.ColorPalette.superclass.constructor.call(this, config);
\r
18783 if(this.handler){
\r
18784 this.on("select", this.handler, this.scope, true);
\r
18787 Ext.extend(Ext.ColorPalette, Ext.Component, {
\r
18790 itemCls : "x-color-palette",
\r
18793 clickEvent:'click',
\r
18795 ctype: "Ext.ColorPalette",
\r
18798 allowReselect : false,
\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
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"> </span></em></a></tpl>'
\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
18827 afterRender : function(){
\r
18828 Ext.ColorPalette.superclass.afterRender.call(this);
\r
18830 var s = this.value;
\r
18831 this.value = null;
\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
18846 select : function(color){
\r
18847 color = color.replace("#", "");
\r
18848 if(color != this.value || this.allowReselect){
\r
18849 var el = this.el;
\r
18851 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
\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
18861 Ext.reg('colorpalette', Ext.ColorPalette);
\r
18863 Ext.DatePicker = Ext.extend(Ext.Component, {
\r
18865 todayText : "Today",
\r
18867 okText : " OK ", //   to give the user extra clicking room
\r
18869 cancelText : "Cancel",
\r
18871 todayTip : "{0} (Spacebar)",
\r
18873 minText : "This date is before the minimum date",
\r
18875 maxText : "This date is after the maximum date",
\r
18877 format : "m/d/y",
\r
18879 disabledDaysText : "Disabled",
\r
18881 disabledDatesText : "Disabled",
\r
18883 constrainToViewport : true,
\r
18885 monthNames : Date.monthNames,
\r
18887 dayNames : Date.dayNames,
\r
18889 nextText: 'Next Month (Control+Right)',
\r
18891 prevText: 'Previous Month (Control+Left)',
\r
18893 monthYearText: 'Choose a month (Control+Up/Down to move years)',
\r
18897 showToday : true,
\r
18905 initComponent : function(){
\r
18906 Ext.DatePicker.superclass.initComponent.call(this);
\r
18908 this.value = this.value ?
\r
18909 this.value.clearTime() : new Date().clearTime();
\r
18916 if(this.handler){
\r
18917 this.on("select", this.handler, this.scope || this);
\r
18920 this.initDisabledDays();
\r
18924 initDisabledDays : function(){
\r
18925 if(!this.disabledDatesRE && this.disabledDates){
\r
18926 var dd = this.disabledDates;
\r
18928 for(var i = 0; i < dd.length; i++){
\r
18930 if(i != dd.length-1) re += "|";
\r
18932 this.disabledDatesRE = new RegExp(re + ")");
\r
18937 setDisabledDates : function(dd){
\r
18938 if(Ext.isArray(dd)){
\r
18939 this.disabledDates = dd;
\r
18940 this.disabledDatesRE = null;
\r
18942 this.disabledDatesRE = dd;
\r
18944 this.initDisabledDays();
\r
18945 this.update(this.value, true);
\r
18949 setDisabledDays : function(dd){
\r
18950 this.disabledDays = dd;
\r
18951 this.update(this.value, true);
\r
18955 setMinDate : function(dt){
\r
18956 this.minDate = dt;
\r
18957 this.update(this.value, true);
\r
18961 setMaxDate : function(dt){
\r
18962 this.maxDate = dt;
\r
18963 this.update(this.value, true);
\r
18967 setValue : function(value){
\r
18968 var old = this.value;
\r
18969 this.value = value.clearTime(true);
\r
18971 this.update(this.value);
\r
18976 getValue : function(){
\r
18977 return this.value;
\r
18981 focus : function(){
\r
18983 this.update(this.activeDate);
\r
18988 onRender : function(container, position){
\r
18990 '<table cellspacing="0">',
\r
18991 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </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
18999 m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
\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
19006 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
\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
19012 var el = document.createElement("div");
\r
19013 el.className = "x-date-picker";
\r
19014 el.innerHTML = m.join("");
\r
19016 container.dom.insertBefore(el, position);
\r
19018 this.el = Ext.get(el);
\r
19019 this.eventEl = Ext.get(el.firstChild);
\r
19021 this.leftClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
\r
19022 handler: this.showPrevMonth,
\r
19024 preventDefault:true,
\r
19028 this.rightClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
\r
19029 handler: this.showNextMonth,
\r
19031 preventDefault:true,
\r
19035 this.eventEl.on("mousewheel", this.handleMouseWheel, this);
\r
19037 this.monthPicker = this.el.down('div.x-date-mp');
\r
19038 this.monthPicker.enableDisplayMode('block');
\r
19040 var kn = new Ext.KeyNav(this.eventEl, {
\r
19041 "left" : function(e){
\r
19043 this.showPrevMonth() :
\r
19044 this.update(this.activeDate.add("d", -1));
\r
19047 "right" : function(e){
\r
19049 this.showNextMonth() :
\r
19050 this.update(this.activeDate.add("d", 1));
\r
19053 "up" : function(e){
\r
19055 this.showNextYear() :
\r
19056 this.update(this.activeDate.add("d", -7));
\r
19059 "down" : function(e){
\r
19061 this.showPrevYear() :
\r
19062 this.update(this.activeDate.add("d", 7));
\r
19065 "pageUp" : function(e){
\r
19066 this.showNextMonth();
\r
19069 "pageDown" : function(e){
\r
19070 this.showPrevMonth();
\r
19073 "enter" : function(e){
\r
19074 e.stopPropagation();
\r
19081 this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});
\r
19083 this.el.unselectable();
\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
19088 this.mbtn = new Ext.Button({
\r
19090 tooltip: this.monthYearText,
\r
19091 renderTo: this.el.child("td.x-date-middle", true)
\r
19094 this.mbtn.on('click', this.showMonthPicker, this);
\r
19095 this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
\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
19110 this.el.repaint();
\r
19112 this.update(this.value);
\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
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
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
19129 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
\r
19131 '</button><button type="button" class="x-date-mp-cancel">',
\r
19133 '</button></td></tr>',
\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
19140 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
\r
19141 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
\r
19143 this.mpMonths.each(function(m, a, i){
\r
19146 m.dom.xmonth = 5 + Math.round(i * .5);
\r
19148 m.dom.xmonth = Math.round((i-1) * .5);
\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
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
19166 this.monthPicker.slideIn('t', {duration:.2});
\r
19170 updateMPYear : function(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
19176 y2 = y + Math.round(i * .5);
\r
19177 td.firstChild.innerHTML = y2;
\r
19180 y2 = y - (5-Math.round(i * .5));
\r
19181 td.firstChild.innerHTML = y2;
\r
19184 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
\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
19196 selectMPMonth: function(m){
\r
19201 onMonthClick : function(e, t){
\r
19203 var el = new Ext.Element(t), pn;
\r
19204 if(el.is('button.x-date-mp-cancel')){
\r
19205 this.hideMonthPicker();
\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
19214 this.hideMonthPicker();
\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
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
19226 else if(el.is('a.x-date-mp-prev')){
\r
19227 this.updateMPYear(this.mpyear-10);
\r
19229 else if(el.is('a.x-date-mp-next')){
\r
19230 this.updateMPYear(this.mpyear+10);
\r
19235 onMonthDblClick : function(e, t){
\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
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
19249 hideMonthPicker : function(disableAnim){
\r
19250 if(this.monthPicker){
\r
19251 if(disableAnim === true){
\r
19252 this.monthPicker.hide();
\r
19254 this.monthPicker.slideOut('t', {duration:.2});
\r
19260 showPrevMonth : function(e){
\r
19261 this.update(this.activeDate.add("mo", -1));
\r
19265 showNextMonth : function(e){
\r
19266 this.update(this.activeDate.add("mo", 1));
\r
19270 showPrevYear : function(){
\r
19271 this.update(this.activeDate.add("y", -1));
\r
19275 showNextYear : function(){
\r
19276 this.update(this.activeDate.add("y", 1));
\r
19280 handleMouseWheel : function(e){
\r
19281 var delta = e.getWheelDelta();
\r
19283 this.showPrevMonth();
\r
19285 } else if(delta < 0){
\r
19286 this.showNextMonth();
\r
19292 handleDateClick : function(e, t){
\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
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
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
19328 var days = date.getDaysInMonth();
\r
19329 var firstOfMonth = date.getFirstDateOfMonth();
\r
19330 var startingPos = firstOfMonth.getDay()-this.startDay;
\r
19332 if(startingPos <= this.startDay){
\r
19333 startingPos += 7;
\r
19336 var pm = date.add("mo", -1);
\r
19337 var prevStart = pm.getDaysInMonth()-startingPos;
\r
19339 var cells = this.cells.elements;
\r
19340 var textEls = this.textNodes;
\r
19341 days += startingPos;
\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
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
19362 this.todayBtn.setDisabled(disable);
\r
19363 this.todayKeyListener[disable ? 'disable' : 'enable']();
\r
19366 var setCellClass = function(cal, cell){
\r
19368 var t = d.getTime();
\r
19369 cell.firstChild.dateValue = t;
\r
19371 cell.className += " x-date-today";
\r
19372 cell.title = cal.todayText;
\r
19375 cell.className += " x-date-selected";
\r
19376 setTimeout(function(){
\r
19377 try{cell.firstChild.focus();}catch(e){}
\r
19382 cell.className = " x-date-disabled";
\r
19383 cell.title = cal.minText;
\r
19387 cell.className = " x-date-disabled";
\r
19388 cell.title = cal.maxText;
\r
19392 if(ddays.indexOf(d.getDay()) != -1){
\r
19393 cell.title = ddaysText;
\r
19394 cell.className = " x-date-disabled";
\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
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
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
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
19428 this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
\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
19448 beforeDestroy : function() {
\r
19449 if(this.rendered){
\r
19451 this.leftClickRpt,
\r
19452 this.rightClickRpt,
\r
19453 this.monthPicker,
\r
19463 Ext.reg('datepicker', Ext.DatePicker);
\r
19465 Ext.TabPanel = Ext.extend(Ext.Panel, {
\r
19469 monitorResize : true,
\r
19471 deferredRender : true,
\r
19477 resizeTabs:false,
\r
19479 enableTabScroll: false,
\r
19481 scrollIncrement : 0,
\r
19483 scrollRepeatInterval : 400,
\r
19485 scrollDuration : .35,
\r
19487 animScroll : true,
\r
19489 tabPosition: 'top',
\r
19491 baseCls: 'x-tab-panel',
\r
19493 autoTabs : false,
\r
19495 autoTabSelector:'div.x-tab',
\r
19497 activeTab : null,
\r
19503 wheelIncrement : 20,
\r
19506 idDelimiter : '__',
\r
19509 itemCls : 'x-tab-item',
\r
19511 // private config overrides
\r
19512 elements: 'body',
\r
19513 headerAsText: false,
\r
19515 hideBorders:true,
\r
19518 initComponent : function(){
\r
19519 this.frame = false;
\r
19520 Ext.TabPanel.superclass.initComponent.call(this);
\r
19523 'beforetabchange',
\r
19529 this.setLayout(new Ext.layout.CardLayout({
\r
19530 deferredRender: this.deferredRender
\r
19532 if(this.tabPosition == 'top'){
\r
19533 this.elements += ',header';
\r
19534 this.stripTarget = 'header';
\r
19536 this.elements += ',footer';
\r
19537 this.stripTarget = 'footer';
\r
19540 this.stack = Ext.TabPanel.AccessStack();
\r
19542 this.initItems();
\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
19556 onRender : function(ct, position){
\r
19557 Ext.TabPanel.superclass.onRender.call(this, ct, position);
\r
19560 var pos = this.tabPosition == 'top' ? 'header' : 'footer';
\r
19561 this[pos].addClass('x-tab-panel-'+pos+'-plain');
\r
19564 var st = this[this.stripTarget];
\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
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
19573 this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});
\r
19574 this.strip.createChild({cls:'x-clear'});
\r
19576 this.body.addClass('x-tab-panel-body-'+this.tabPosition);
\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
19585 tt.disableFormats = true;
\r
19587 Ext.TabPanel.prototype.itemTpl = tt;
\r
19590 this.items.each(this.initTab, this);
\r
19594 afterRender : function(){
\r
19595 Ext.TabPanel.superclass.afterRender.call(this);
\r
19596 if(this.autoTabs){
\r
19597 this.readTabs(false);
\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
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
19615 findTargets : function(e){
\r
19617 var itemEl = e.getTarget('li', this.strip);
\r
19619 item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
\r
19620 if(item.disabled){
\r
19629 close : e.getTarget('.x-tab-strip-close', this.strip),
\r
19636 onStripMouseDown : function(e){
\r
19637 if(e.button != 0){
\r
19640 e.preventDefault();
\r
19641 var t = this.findTargets(e);
\r
19643 this.remove(t.item);
\r
19646 if(t.item && t.item != this.activeTab){
\r
19647 this.setActiveTab(t.item);
\r
19652 onStripContextMenu : function(e){
\r
19653 e.preventDefault();
\r
19654 var t = this.findTargets(e);
\r
19656 this.fireEvent('contextmenu', this, t.item, e);
\r
19661 readTabs : function(removeExisting){
\r
19662 if(removeExisting === true){
\r
19663 this.items.each(function(item){
\r
19664 this.remove(item);
\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
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
19686 if(item.iconCls){
\r
19687 cls += ' x-tab-with-icon';
\r
19690 cls += ' ' + item.tabCls;
\r
19694 id: this.id + this.idDelimiter + item.getItemId(),
\r
19695 text: item.title,
\r
19697 iconCls: item.iconCls || ''
\r
19699 var el = before ?
\r
19700 this.itemTpl.insertBefore(before, p) :
\r
19701 this.itemTpl.append(this.strip, p);
\r
19703 Ext.fly(el).addClassOnOver('x-tab-strip-over');
\r
19706 Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
\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
19718 onAdd : function(tp, item, index){
\r
19719 this.initTab(item, index);
\r
19720 if(this.items.getCount() == 1){
\r
19723 this.delegateUpdates();
\r
19727 onBeforeAdd : function(item){
\r
19728 var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
\r
19730 this.setActiveTab(item);
\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
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
19751 this.setActiveTab(next);
\r
19752 }else if(this.items.getCount() > 0){
\r
19753 this.setActiveTab(0);
\r
19755 this.activeTab = null;
\r
19758 this.delegateUpdates();
\r
19762 onBeforeShowItem : function(item){
\r
19763 if(item != this.activeTab){
\r
19764 this.setActiveTab(item);
\r
19770 onItemDisabled : function(item){
\r
19771 var el = this.getTabEl(item);
\r
19773 Ext.fly(el).addClass('x-item-disabled');
\r
19775 this.stack.remove(item);
\r
19779 onItemEnabled : function(item){
\r
19780 var el = this.getTabEl(item);
\r
19782 Ext.fly(el).removeClass('x-item-disabled');
\r
19787 onItemTitleChanged : function(item){
\r
19788 var el = this.getTabEl(item);
\r
19790 Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
\r
19795 onItemIconChanged: function(item, iconCls, oldCls){
\r
19796 var el = this.getTabEl(item);
\r
19798 Ext.fly(el).child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
\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
19809 onResize : function(){
\r
19810 Ext.TabPanel.superclass.onResize.apply(this, arguments);
\r
19811 this.delegateUpdates();
\r
19815 beginUpdate : function(){
\r
19816 this.suspendUpdates = true;
\r
19820 endUpdate : function(){
\r
19821 this.suspendUpdates = false;
\r
19822 this.delegateUpdates();
\r
19826 hideTabStripItem : function(item){
\r
19827 item = this.getComponent(item);
\r
19828 var el = this.getTabEl(item);
\r
19830 el.style.display = 'none';
\r
19831 this.delegateUpdates();
\r
19833 this.stack.remove(item);
\r
19837 unhideTabStripItem : function(item){
\r
19838 item = this.getComponent(item);
\r
19839 var el = this.getTabEl(item);
\r
19841 el.style.display = '';
\r
19842 this.delegateUpdates();
\r
19847 delegateUpdates : function(){
\r
19848 if(this.suspendUpdates){
\r
19851 if(this.resizeTabs && this.rendered){
\r
19852 this.autoSizeTabs();
\r
19854 if(this.enableTabScroll && this.rendered){
\r
19855 this.autoScrollTabs();
\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
19866 if(!this.resizeTabs || count < 1 || !aw){ // !aw for display:none
\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
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
19883 adjustBodyWidth : function(w){
\r
19885 this.header.setWidth(w);
\r
19888 this.footer.setWidth(w);
\r
19894 setActiveTab : function(item){
\r
19895 item = this.getComponent(item);
\r
19896 if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
\r
19899 if(!this.rendered){
\r
19900 this.activeTab = item;
\r
19903 if(this.activeTab != item){
\r
19904 if(this.activeTab){
\r
19905 var oldEl = this.getTabEl(this.activeTab);
\r
19907 Ext.fly(oldEl).removeClass('x-tab-strip-active');
\r
19909 this.activeTab.fireEvent('deactivate', this.activeTab);
\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
19916 this.layout.setActiveItem(item);
\r
19917 if(this.layoutOnTabChange && item.doLayout){
\r
19920 if(this.scrolling){
\r
19921 this.scrollToTab(item, this.animScroll);
\r
19924 item.fireEvent('activate', item);
\r
19925 this.fireEvent('tabchange', this, item);
\r
19930 getActiveTab : function(){
\r
19931 return this.activeTab || null;
\r
19935 getItem : function(item){
\r
19936 return this.getComponent(item);
\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
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
19952 if(!this.enableTabScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
\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
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
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
19982 this.scrollLeft.show();
\r
19983 this.scrollRight.show();
\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
19992 this.updateScrollButtons();
\r
19997 createScrollers : function(){
\r
19998 this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
\r
19999 var h = this.stripWrap.dom.offsetHeight;
\r
20002 var sl = this.pos.insertFirst({
\r
20003 cls:'x-tab-scroller-left'
\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
20012 this.scrollLeft = sl;
\r
20015 var sr = this.pos.insertFirst({
\r
20016 cls:'x-tab-scroller-right'
\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
20025 this.scrollRight = sr;
\r
20029 getScrollWidth : function(){
\r
20030 return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
\r
20034 getScrollPos : function(){
\r
20035 return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
\r
20039 getScrollArea : function(){
\r
20040 return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
\r
20044 getScrollAnim : function(){
\r
20045 return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
\r
20049 getScrollIncrement : function(){
\r
20050 return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
\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
20062 this.scrollTo(left, animate);
\r
20063 }else if(right > (pos + area)){
\r
20064 this.scrollTo(right - area, animate);
\r
20069 scrollTo : function(pos, animate){
\r
20070 this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
\r
20072 this.updateScrollButtons();
\r
20076 onWheel : function(e){
\r
20077 var d = e.getWheelDelta()*this.wheelIncrement*-1;
\r
20080 var pos = this.getScrollPos();
\r
20081 var newpos = pos + d;
\r
20082 var sw = this.getScrollWidth()-this.getScrollArea();
\r
20084 var s = Math.max(0, Math.min(sw, newpos));
\r
20086 this.scrollTo(s, false);
\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
20096 this.scrollTo(s, this.animScroll);
\r
20101 onScrollLeft : function(){
\r
20102 var pos = this.getScrollPos();
\r
20103 var s = Math.max(0, pos - this.getScrollIncrement());
\r
20105 this.scrollTo(s, this.animScroll);
\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
20117 beforeDestroy : function() {
\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
20127 this.strip.removeAllListeners();
\r
20129 Ext.TabPanel.superclass.beforeDestroy.apply(this);
\r
20145 Ext.reg('tabpanel', Ext.TabPanel);
\r
20148 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
\r
20150 // private utility class used by TabPanel
\r
20151 Ext.TabPanel.AccessStack = function(){
\r
20154 add : function(item){
\r
20155 items.push(item);
\r
20156 if(items.length > 10){
\r
20161 remove : function(item){
\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
20171 next : function(){
\r
20172 return items.pop();
\r
20180 Ext.Button = Ext.extend(Ext.Component, {
\r
20184 disabled : false,
\r
20194 enableToggle: false,
\r
20198 menuAlign : "tl-bl?",
\r
20205 menuClassTarget: 'tr',
\r
20208 clickEvent : 'click',
\r
20211 handleMouseEvents : true,
\r
20214 tooltipType : 'qtip',
\r
20217 buttonSelector : "button:first-child",
\r
20222 initComponent : function(){
\r
20223 Ext.Button.superclass.initComponent.call(this);
\r
20239 'menutriggerover',
\r
20244 this.menu = Ext.menu.MenuMgr.get(this.menu);
\r
20246 if(typeof this.toggleGroup === 'string'){
\r
20247 this.enableToggle = true;
\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> </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> </i></td>',
\r
20259 "</tr></tbody></table>");
\r
20261 this.template = Ext.Button.buttonTemplate;
\r
20263 var btn, targs = [this.text || ' ', this.type];
\r
20266 btn = this.template.insertBefore(position, targs, true);
\r
20268 btn = this.template.append(ct, targs, true);
\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
20274 this.initButtonEl(btn, btnEl);
\r
20277 this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
\r
20279 Ext.ButtonToggleMgr.register(this);
\r
20283 initButtonEl : function(btn, btnEl){
\r
20286 btn.addClass("x-btn");
\r
20289 this.el.dom.id = this.el.id = this.id;
\r
20292 btnEl.setStyle('background-image', 'url(' +this.icon +')');
\r
20294 if(this.iconCls){
\r
20295 btnEl.addClass(this.iconCls);
\r
20297 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
\r
20300 if(this.tabIndex !== undefined){
\r
20301 btnEl.dom.tabIndex = this.tabIndex;
\r
20303 if(this.tooltip){
\r
20304 if(typeof this.tooltip == 'object'){
\r
20305 Ext.QuickTips.register(Ext.apply({
\r
20307 }, this.tooltip));
\r
20309 btnEl.dom[this.tooltipType] = this.tooltip;
\r
20313 if(this.pressed){
\r
20314 this.el.addClass("x-btn-pressed");
\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
20325 this.menu.on("show", this.onMenuShow, this);
\r
20326 this.menu.on("hide", this.onMenuHide, this);
\r
20330 var repeater = new Ext.util.ClickRepeater(btn,
\r
20331 typeof this.repeat == "object" ? this.repeat : {}
\r
20333 repeater.on("click", this.onClick, this);
\r
20336 btn.on(this.clickEvent, this.onClick, this);
\r
20340 afterRender : function(){
\r
20341 Ext.Button.superclass.afterRender.call(this);
\r
20343 this.autoWidth.defer(1, this);
\r
20345 this.autoWidth();
\r
20350 setIconClass : function(cls){
\r
20352 this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);
\r
20354 this.iconCls = cls;
\r
20358 beforeDestroy: function(){
\r
20359 if(this.rendered){
\r
20360 var btnEl = this.el.child(this.buttonSelector);
\r
20362 if(this.tooltip){
\r
20363 Ext.QuickTips.unregister(btnEl);
\r
20365 btnEl.removeAllListeners();
\r
20369 Ext.destroy(this.menu);
\r
20374 onDestroy : function(){
\r
20375 if(this.rendered){
\r
20376 Ext.ButtonToggleMgr.unregister(this);
\r
20381 autoWidth : function(){
\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
20388 ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
\r
20391 if(this.minWidth){
\r
20392 if(this.el.getWidth() < this.minWidth){
\r
20393 this.el.setWidth(this.minWidth);
\r
20400 setHandler : function(handler, scope){
\r
20401 this.handler = handler;
\r
20402 this.scope = scope;
\r
20406 setText : function(text){
\r
20407 this.text = text;
\r
20409 this.el.child("td.x-btn-center " + this.buttonSelector).update(text);
\r
20411 this.autoWidth();
\r
20415 getText : function(){
\r
20416 return this.text;
\r
20420 toggle : function(state){
\r
20421 state = state === undefined ? !this.pressed : state;
\r
20422 if(state != this.pressed){
\r
20424 this.el.addClass("x-btn-pressed");
\r
20425 this.pressed = true;
\r
20426 this.fireEvent("toggle", this, true);
\r
20428 this.el.removeClass("x-btn-pressed");
\r
20429 this.pressed = false;
\r
20430 this.fireEvent("toggle", this, false);
\r
20432 if(this.toggleHandler){
\r
20433 this.toggleHandler.call(this.scope || this, this, state);
\r
20439 focus : function(){
\r
20440 this.el.child(this.buttonSelector).focus();
\r
20444 onDisable : function(){
\r
20446 if(!Ext.isIE6 || !this.text){
\r
20447 this.el.addClass(this.disabledClass);
\r
20449 this.el.dom.disabled = true;
\r
20451 this.disabled = true;
\r
20455 onEnable : function(){
\r
20457 if(!Ext.isIE6 || !this.text){
\r
20458 this.el.removeClass(this.disabledClass);
\r
20460 this.el.dom.disabled = false;
\r
20462 this.disabled = false;
\r
20466 showMenu : function(){
\r
20468 this.menu.show(this.el, this.menuAlign);
\r
20474 hideMenu : function(){
\r
20476 this.menu.hide();
\r
20482 hasVisibleMenu : function(){
\r
20483 return this.menu && this.menu.isVisible();
\r
20487 onClick : function(e){
\r
20489 e.preventDefault();
\r
20491 if(e.button != 0){
\r
20494 if(!this.disabled){
\r
20495 if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
\r
20498 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
\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
20510 isMenuTriggerOver : function(e, internal){
\r
20511 return this.menu && !internal;
\r
20515 isMenuTriggerOut : function(e, internal){
\r
20516 return this.menu && !internal;
\r
20520 onMouseOver : function(e){
\r
20521 if(!this.disabled){
\r
20522 var internal = e.within(this.el, true);
\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
20529 this.fireEvent('mouseover', this, e);
\r
20531 if(this.isMenuTriggerOver(e, internal)){
\r
20532 this.fireEvent('menutriggerover', this, this.menu, e);
\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
20544 this.onMouseOut(e);
\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
20558 onFocus : function(e){
\r
20559 if(!this.disabled){
\r
20560 this.el.addClass("x-btn-focus");
\r
20564 onBlur : function(e){
\r
20565 this.el.removeClass("x-btn-focus");
\r
20569 getClickEl : function(e, isUp){
\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
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
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
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
20601 restoreClick : function(){
\r
20602 this.ignoreNextClick = 0;
\r
20609 Ext.reg('button', Ext.Button);
\r
20611 // Private utility class used by Button
\r
20612 Ext.ButtonToggleMgr = function(){
\r
20615 function toggleGroup(btn, state){
\r
20617 var g = groups[btn.toggleGroup];
\r
20618 for(var i = 0, l = g.length; i < l; i++){
\r
20620 g[i].toggle(false);
\r
20627 register : function(btn){
\r
20628 if(!btn.toggleGroup){
\r
20631 var g = groups[btn.toggleGroup];
\r
20633 g = groups[btn.toggleGroup] = [];
\r
20636 btn.on("toggle", toggleGroup);
\r
20639 unregister : function(btn){
\r
20640 if(!btn.toggleGroup){
\r
20643 var g = groups[btn.toggleGroup];
\r
20646 btn.un("toggle", toggleGroup);
\r
20652 Ext.SplitButton = Ext.extend(Ext.Button, {
\r
20654 arrowSelector : 'button:last',
\r
20657 initComponent : function(){
\r
20658 Ext.SplitButton.superclass.initComponent.call(this);
\r
20660 this.addEvents("arrowclick");
\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> </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"> </button></td><td class="x-btn-right"><i> </i></td></tr>',
\r
20673 "</tbody></table></td></tr></table>"
\r
20675 var btn, targs = [this.text || ' ', this.type];
\r
20677 btn = tpl.insertBefore(position, targs, true);
\r
20679 btn = tpl.append(ct, targs, true);
\r
20681 var btnEl = btn.child(this.buttonSelector);
\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
20691 autoWidth : function(){
\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
20701 ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
\r
20704 if(this.minWidth){
\r
20705 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
\r
20706 tbl.setWidth(this.minWidth-tbl2.getWidth());
\r
20709 this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
\r
20714 setArrowHandler : function(handler, scope){
\r
20715 this.arrowHandler = handler;
\r
20716 this.scope = scope;
\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
20727 this.fireEvent("arrowclick", this, e);
\r
20728 if(this.arrowHandler){
\r
20729 this.arrowHandler.call(this.scope || this, this, e);
\r
20732 if(this.enableToggle){
\r
20735 this.fireEvent("click", this, e);
\r
20736 if(this.handler){
\r
20737 this.handler.call(this.scope || this, this, e);
\r
20744 getClickEl : function(e, isUp){
\r
20746 return (this.lastClickEl = e.getTarget("table", 10, true));
\r
20748 return this.lastClickEl;
\r
20752 onDisable : function(){
\r
20755 this.el.addClass("x-item-disabled");
\r
20757 this.el.child(this.buttonSelector).dom.disabled = true;
\r
20758 this.el.child(this.arrowSelector).dom.disabled = true;
\r
20760 this.disabled = true;
\r
20764 onEnable : function(){
\r
20767 this.el.removeClass("x-item-disabled");
\r
20769 this.el.child(this.buttonSelector).dom.disabled = false;
\r
20770 this.el.child(this.arrowSelector).dom.disabled = false;
\r
20772 this.disabled = false;
\r
20776 isMenuTriggerOver : function(e){
\r
20777 return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);
\r
20781 isMenuTriggerOut : function(e, internal){
\r
20782 return this.menu && !e.within(this.arrowBtnTable);
\r
20786 onDestroy : function(){
\r
20787 Ext.destroy(this.arrowBtnTable);
\r
20788 Ext.SplitButton.superclass.onDestroy.call(this);
\r
20792 // backwards compat
\r
20793 Ext.MenuButton = Ext.SplitButton;
\r
20796 Ext.reg('splitbutton', Ext.SplitButton);
\r
20798 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
\r
20806 getItemText : function(item){
\r
20807 if(item && this.showText === true){
\r
20809 if(this.prependText){
\r
20810 text += this.prependText;
\r
20812 text += item.text;
\r
20815 return undefined;
\r
20819 setActiveItem : function(item, suppressEvent){
\r
20820 if(typeof item != 'object'){
\r
20821 item = this.menu.items.get(item);
\r
20824 if(!this.rendered){
\r
20825 this.text = this.getItemText(item);
\r
20826 this.iconCls = item.iconCls;
\r
20828 var t = this.getItemText(item);
\r
20832 this.setIconClass(item.iconCls);
\r
20834 this.activeItem = item;
\r
20835 if(!item.checked){
\r
20836 item.setChecked(true, true);
\r
20838 if(this.forceIcon){
\r
20839 this.setIconClass(this.forceIcon);
\r
20841 if(!suppressEvent){
\r
20842 this.fireEvent('change', this, item);
\r
20848 getActiveItem : function(){
\r
20849 return this.activeItem;
\r
20853 initComponent : function(){
\r
20859 if(this.changeHandler){
\r
20860 this.on('change', this.changeHandler, this.scope||this);
\r
20861 delete this.changeHandler;
\r
20864 this.itemCount = this.items.length;
\r
20866 this.menu = {cls:'x-cycle-menu', items:[]};
\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
20880 this.setActiveItem(checked, true);
\r
20881 Ext.CycleButton.superclass.initComponent.call(this);
\r
20883 this.on('click', this.toggleSelected, this);
\r
20887 checkHandler : function(item, pressed){
\r
20889 this.setActiveItem(item);
\r
20894 toggleSelected : function(){
\r
20895 this.menu.render();
\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
20910 Ext.reg('cycle', Ext.CycleButton);
\r
20912 Ext.Toolbar = function(config){
\r
20913 if(Ext.isArray(config)){
\r
20914 config = {buttons:config};
\r
20916 Ext.Toolbar.superclass.constructor.call(this, config);
\r
20921 var T = Ext.Toolbar;
\r
20923 Ext.extend(T, Ext.BoxComponent, {
\r
20925 trackMenus : true,
\r
20928 initComponent : function(){
\r
20929 T.superclass.initComponent.call(this);
\r
20932 this.buttons = this.items;
\r
20935 this.items = new Ext.util.MixedCollection(false, function(o){
\r
20936 return o.itemId || o.id || Ext.id();
\r
20942 cls:'x-toolbar x-small-editor',
\r
20943 html:'<table cellspacing="0"><tr></tr></table>'
\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
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
20962 add : function(){
\r
20963 var a = arguments, l = a.length;
\r
20964 for(var i = 0; i < l; 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
20978 this.addText(el);
\r
20980 }else if(el.tagName){ // element
\r
20981 this.addElement(el);
\r
20982 }else if(typeof el == "object"){ // must be button config?
\r
20984 this.addField(Ext.ComponentMgr.create(el, 'button'));
\r
20986 this.addButton(el);
\r
20993 addSeparator : function(){
\r
20994 return this.addItem(new T.Separator());
\r
20998 addSpacer : function(){
\r
20999 return this.addItem(new T.Spacer());
\r
21003 addFill : function(){
\r
21004 return this.addItem(new T.Fill());
\r
21008 addElement : function(el){
\r
21009 return this.addItem(new T.Item(el));
\r
21013 addItem : function(item){
\r
21014 var td = this.nextBlock();
\r
21015 this.initMenuTracking(item);
\r
21017 this.items.add(item);
\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
21031 if(!(config instanceof T.Button)){
\r
21032 b = config.split ?
\r
21033 new T.SplitButton(config) :
\r
21034 new T.Button(config);
\r
21036 var td = this.nextBlock();
\r
21037 this.initMenuTracking(b);
\r
21039 this.items.add(b);
\r
21044 initMenuTracking : function(item){
\r
21045 if(this.trackMenus && item.menu){
\r
21047 'menutriggerover' : this.onButtonTriggerOver,
\r
21048 'menushow' : this.onButtonMenuShow,
\r
21049 'menuhide' : this.onButtonMenuHide,
\r
21056 addText : function(text){
\r
21057 return this.addItem(new T.TextItem(text));
\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
21069 if (!(item instanceof T.Button)){
\r
21070 item = new T.Button(item);
\r
21072 var td = document.createElement("td");
\r
21073 this.tr.insertBefore(td, this.tr.childNodes[index]);
\r
21074 this.initMenuTracking(item);
\r
21076 this.items.insert(index, item);
\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
21086 this.items.add(ti);
\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
21096 this.items.add(field);
\r
21101 nextBlock : function(){
\r
21102 var td = document.createElement("td");
\r
21103 this.tr.appendChild(td);
\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
21114 Ext.Element.uncache(this.tr);
\r
21119 onDisable : function(){
\r
21120 this.items.each(function(item){
\r
21121 if(item.disable){
\r
21128 onEnable : function(){
\r
21129 this.items.each(function(item){
\r
21137 onButtonTriggerOver : function(btn){
\r
21138 if(this.activeMenuBtn && this.activeMenuBtn != btn){
\r
21139 this.activeMenuBtn.hideMenu();
\r
21141 this.activeMenuBtn = btn;
\r
21146 onButtonMenuShow : function(btn){
\r
21147 this.activeMenuBtn = btn;
\r
21151 onButtonMenuHide : function(btn){
\r
21152 delete this.activeMenuBtn;
\r
21157 Ext.reg('toolbar', Ext.Toolbar);
\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
21166 T.Item.prototype = {
\r
21169 getEl : function(){
\r
21174 render : function(td){
\r
21176 td.appendChild(this.el);
\r
21180 destroy : function(){
\r
21182 var el = Ext.get(this.el);
\r
21185 Ext.removeNode(this.td);
\r
21189 show: function(){
\r
21190 this.hidden = false;
\r
21191 this.td.style.display = "";
\r
21195 hide: function(){
\r
21196 this.hidden = true;
\r
21197 this.td.style.display = "none";
\r
21201 setVisible: function(visible){
\r
21210 focus : function(){
\r
21211 Ext.fly(this.el).focus();
\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
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
21228 Ext.reg('tbitem', T.Item);
\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
21237 Ext.extend(T.Separator, T.Item, {
\r
21238 enable:Ext.emptyFn,
\r
21239 disable:Ext.emptyFn,
\r
21240 focus:Ext.emptyFn
\r
21242 Ext.reg('tbseparator', T.Separator);
\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
21250 Ext.extend(T.Spacer, T.Item, {
\r
21251 enable:Ext.emptyFn,
\r
21252 disable:Ext.emptyFn,
\r
21253 focus:Ext.emptyFn
\r
21256 Ext.reg('tbspacer', T.Spacer);
\r
21259 T.Fill = Ext.extend(T.Spacer, {
\r
21261 render : function(td){
\r
21262 td.style.width = '100%';
\r
21263 T.Fill.superclass.render.call(this, td);
\r
21266 Ext.reg('tbfill', T.Fill);
\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
21275 Ext.extend(T.TextItem, T.Item, {
\r
21276 enable:Ext.emptyFn,
\r
21277 disable:Ext.emptyFn,
\r
21278 focus:Ext.emptyFn
\r
21280 Ext.reg('tbtext', T.TextItem);
\r
21284 T.Button = Ext.extend(Ext.Button, {
\r
21285 hideParent : true,
\r
21287 onDestroy : function(){
\r
21288 T.Button.superclass.onDestroy.call(this);
\r
21289 if(this.container){
\r
21290 this.container.remove();
\r
21294 Ext.reg('tbbutton', T.Button);
\r
21297 T.SplitButton = Ext.extend(Ext.SplitButton, {
\r
21298 hideParent : true,
\r
21300 onDestroy : function(){
\r
21301 T.SplitButton.superclass.onDestroy.call(this);
\r
21302 if(this.container){
\r
21303 this.container.remove();
\r
21308 Ext.reg('tbsplit', T.SplitButton);
\r
21309 // backwards compat
\r
21310 T.MenuButton = T.SplitButton;
\r
21315 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
\r
21321 displayMsg : 'Displaying {0} - {1} of {2}',
\r
21323 emptyMsg : 'No data to display',
\r
21325 beforePageText : "Page",
\r
21327 afterPageText : "of {0}",
\r
21329 firstText : "First Page",
\r
21331 prevText : "Previous Page",
\r
21333 nextText : "Next Page",
\r
21335 lastText : "Last Page",
\r
21337 refreshText : "Refresh",
\r
21340 paramNames : {start: 'start', limit: 'limit'},
\r
21343 initComponent : function(){
\r
21350 Ext.PagingToolbar.superclass.initComponent.call(this);
\r
21352 this.bind(this.store);
\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
21362 handler: this.onClick.createDelegate(this, ["first"])
\r
21364 this.prev = this.addButton({
\r
21365 tooltip: this.prevText,
\r
21366 iconCls: "x-tbar-page-prev",
\r
21368 handler: this.onClick.createDelegate(this, ["prev"])
\r
21370 this.addSeparator();
\r
21371 this.add(this.beforePageText);
\r
21372 this.field = Ext.get(this.addDom({
\r
21377 cls: "x-tbar-page-number"
\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
21389 handler: this.onClick.createDelegate(this, ["next"])
\r
21391 this.last = this.addButton({
\r
21392 tooltip: this.lastText,
\r
21393 iconCls: "x-tbar-page-last",
\r
21395 handler: this.onClick.createDelegate(this, ["last"])
\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
21404 if(this.displayInfo){
\r
21405 this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
\r
21407 if(this.dsLoaded){
\r
21408 this.onLoad.apply(this, this.dsLoaded);
\r
21413 updateInfo : function(){
\r
21414 if(this.displayEl){
\r
21415 var count = this.store.getCount();
\r
21416 var msg = count == 0 ?
\r
21420 this.cursor+1, this.cursor+count, this.store.getTotalCount()
\r
21422 this.displayEl.update(msg);
\r
21427 onLoad : function(store, r, o){
\r
21428 if(!this.rendered){
\r
21429 this.dsLoaded = [store, r, o];
\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
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
21447 getPageData : function(){
\r
21448 var total = this.store.getTotalCount();
\r
21451 activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
\r
21452 pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
\r
21457 onLoadError : function(){
\r
21458 if(!this.rendered){
\r
21461 this.loading.enable();
\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
21475 onPagingBlur: function(e){
\r
21476 this.field.dom.value = this.getPageData().activePage;
\r
21480 onPagingKeydown : function(e){
\r
21481 var k = e.getKey(), d = this.getPageData(), pageNum;
\r
21482 if (k == e.RETURN) {
\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
21489 }else if (k == e.HOME || k == e.END){
\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
21495 if(pageNum = this.readPage(d)){
\r
21496 var increment = e.shiftKey ? 10 : 1;
\r
21497 if(k == e.DOWN || k == e.PAGEDOWN){
\r
21500 pageNum += increment;
\r
21501 if(pageNum >= 1 & pageNum <= d.pages){
\r
21502 this.field.dom.value = pageNum;
\r
21509 beforeLoad : function(){
\r
21510 if(this.rendered && this.loading){
\r
21511 this.loading.disable();
\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
21526 changePage: function(page){
\r
21527 this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
\r
21531 onClick : function(which){
\r
21532 var store = this.store;
\r
21538 this.doLoad(Math.max(0, this.cursor-this.pageSize));
\r
21541 this.doLoad(this.cursor+this.pageSize);
\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
21550 this.doLoad(this.cursor);
\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
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
21574 onDestroy : function(){
\r
21576 this.unbind(this.store);
\r
21578 Ext.PagingToolbar.superclass.onDestroy.call(this);
\r
21581 Ext.reg('paging', Ext.PagingToolbar);
\r
21583 Ext.Resizable = function(el, config){
\r
21584 this.el = Ext.get(el);
\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
21597 if(config.pinned && !config.adjustments){
\r
21598 config.adjustments = "auto";
\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
21607 Ext.apply(this, config);
\r
21610 this.disableTrackOver = true;
\r
21611 this.el.addClass("x-resizable-pinned");
\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
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
21624 if(this.handles == "all"){
\r
21625 this.handles = "n s e w ne nw se sw";
\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
21636 this.corner = this.southeast;
\r
21638 if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
\r
21639 this.updateBox = true;
\r
21642 this.activeHandle = null;
\r
21644 if(this.resizeChild){
\r
21645 if(typeof this.resizeChild == "boolean"){
\r
21646 this.resizeChild = Ext.get(this.el.dom.firstChild, true);
\r
21648 this.resizeChild = Ext.get(this.resizeChild, true);
\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
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
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
21678 if(this.width !== null && this.height !== null){
\r
21679 this.resizeTo(this.width, this.height);
\r
21681 this.updateChildSize();
\r
21684 this.el.dom.style.zoom = 1;
\r
21686 Ext.Resizable.superclass.constructor.call(this);
\r
21689 Ext.extend(Ext.Resizable, Ext.util.Observable, {
\r
21690 resizeChild : false,
\r
21691 adjustments : [0, 0],
\r
21694 maxWidth : 10000,
\r
21695 maxHeight : 10000,
\r
21701 multiDirectional : false,
\r
21702 disableTrackOver : false,
\r
21703 easing : 'easeOutStrong',
\r
21704 widthIncrement : 0,
\r
21705 heightIncrement : 0,
\r
21709 preserveRatio : false,
\r
21710 transparent: false,
\r
21713 draggable: false,
\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
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
21733 if(!this.overlay){
\r
21734 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: " "}, 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
21740 this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));
\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
21748 this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
\r
21749 this.overlay.show();
\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
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
21771 onMouseDown : function(handle, e){
\r
21772 if(this.enabled){
\r
21774 this.activeHandle = handle;
\r
21775 this.startSizing(e, handle);
\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
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
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
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
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
21821 newValue = value + (inc-m);
\r
21823 newValue = value - m;
\r
21826 return Math.max(min, newValue);
\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
21835 this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
\r
21837 this.updateChildSize();
\r
21838 if(!this.dynamic){
\r
21839 this.proxy.hide();
\r
21845 constrain : function(v, diff, m, mx){
\r
21846 if(v - diff < m){
\r
21848 }else if(v - diff > mx){
\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
21859 if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
\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
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
21878 var pos = this.activeHandle.position;
\r
21883 w = Math.min(Math.max(mw, w), mxw);
\r
21887 h = Math.min(Math.max(mh, h), mxh);
\r
21889 case "southeast":
\r
21892 w = Math.min(Math.max(mw, w), mxw);
\r
21893 h = Math.min(Math.max(mh, h), mxh);
\r
21896 diffY = this.constrain(h, diffY, mh, mxh);
\r
21901 diffX = this.constrain(w, diffX, mw, mxw);
\r
21905 case "northeast":
\r
21907 w = Math.min(Math.max(mw, w), mxw);
\r
21908 diffY = this.constrain(h, diffY, mh, mxh);
\r
21912 case "northwest":
\r
21913 diffX = this.constrain(w, diffX, mw, mxw);
\r
21914 diffY = this.constrain(h, diffY, mh, mxh);
\r
21920 case "southwest":
\r
21921 diffX = this.constrain(w, diffX, mw, mxw);
\r
21923 h = Math.min(Math.max(mh, h), mxh);
\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
21933 case "northeast":
\r
21939 case "southwest":
\r
21945 case "northwest":
\r
21954 if(this.preserveRatio){
\r
21956 case "southeast":
\r
21959 h = Math.min(Math.max(mh, h), mxh);
\r
21964 w = Math.min(Math.max(mw, w), mxw);
\r
21967 case "northeast":
\r
21969 w = Math.min(Math.max(mw, w), mxw);
\r
21975 w = Math.min(Math.max(mw, w), mxw);
\r
21977 x += (tw - w) / 2;
\r
21979 case "southwest":
\r
21981 h = Math.min(Math.max(mh, h), mxh);
\r
21989 h = Math.min(Math.max(mh, h), mxh);
\r
21990 y += (th - h) / 2;
\r
21995 case "northwest":
\r
21999 h = Math.min(Math.max(mh, h), mxh);
\r
22007 this.proxy.setBounds(x, y, w, h);
\r
22008 if(this.dynamic){
\r
22009 this.resizeElement();
\r
22016 handleOver : function(){
\r
22017 if(this.enabled){
\r
22018 this.el.addClass("x-resizable-over");
\r
22023 handleOut : function(){
\r
22024 if(!this.resizing){
\r
22025 this.el.removeClass("x-resizable-over");
\r
22030 getEl : function(){
\r
22035 getResizeChild : function(){
\r
22036 return this.resizeChild;
\r
22040 destroy : function(removeEl){
\r
22042 this.dd.destroy();
\r
22044 if(this.overlay){
\r
22045 Ext.destroy(this.overlay);
\r
22046 this.overlay = null;
\r
22048 Ext.destroy(this.proxy);
\r
22049 this.proxy = null;
\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
22058 this.el.update("");
\r
22059 Ext.destroy(this.el);
\r
22064 syncHandleHeight : function(){
\r
22065 var h = this.el.getHeight(true);
\r
22067 this.west.el.setHeight(h);
\r
22070 this.east.el.setHeight(h);
\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
22082 Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
\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
22089 Ext.Resizable.Handle.prototype.tpl = tpl;
\r
22091 this.position = pos;
\r
22093 this.el = this.tpl.append(rz.el.dom, [this.position], true);
\r
22094 this.el.unselectable();
\r
22096 this.el.setOpacity(0);
\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
22106 Ext.Resizable.Handle.prototype = {
\r
22108 afterResize : function(rz){
\r
22112 onMouseDown : function(e){
\r
22113 this.rz.onMouseDown(this, e);
\r
22116 onMouseOver : function(e){
\r
22117 this.rz.handleOver(this, e);
\r
22120 onMouseOut : function(e){
\r
22121 this.rz.handleOut(this, e);
\r
22124 destroy : function(){
\r
22125 Ext.destroy(this.el);
\r
22134 Ext.Editor = function(field, config){
\r
22135 this.field = field;
\r
22136 Ext.Editor.superclass.constructor.call(this, config);
\r
22139 Ext.extend(Ext.Editor, Ext.Component, {
\r
22147 alignment: "c-c?",
\r
22149 shadow : "frame",
\r
22151 constrain : false,
\r
22153 swallowKeys : true,
\r
22155 completeOnEnter : false,
\r
22157 cancelOnEsc : false,
\r
22159 updateEl : false,
\r
22161 initComponent : function(){
\r
22162 Ext.Editor.superclass.initComponent.call(this);
\r
22165 "beforestartedit",
\r
22169 "beforecomplete",
\r
22180 onRender : function(ct, position){
\r
22181 this.el = new Ext.Layer({
\r
22182 shadow: this.shadow,
\r
22185 shim : this.shim,
\r
22188 constrain: this.constrain
\r
22190 this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
\r
22191 if(this.field.msgTarget != 'title'){
\r
22192 this.field.msgTarget = 'qtip';
\r
22194 this.field.inEditor = true;
\r
22195 this.field.render(this.el);
\r
22197 this.field.el.dom.setAttribute('autocomplete', 'off');
\r
22199 this.field.on("specialkey", this.onSpecialKey, this);
\r
22200 if(this.swallowKeys){
\r
22201 this.field.el.swallowEvent(['keydown','keypress']);
\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
22211 onSpecialKey : function(field, e){
\r
22212 var key = e.getKey();
\r
22213 if(this.completeOnEnter && key == e.ENTER){
\r
22215 this.completeEdit();
\r
22216 }else if(this.cancelOnEsc && key == e.ESC){
\r
22217 this.cancelEdit();
\r
22219 this.fireEvent('specialkey', field, e);
\r
22221 if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
\r
22222 this.field.triggerBlur();
\r
22227 startEdit : function(el, value){
\r
22228 if(this.editing){
\r
22229 this.completeEdit();
\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
22236 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
\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
22248 doAutoSize : function(){
\r
22249 if(this.autoSize){
\r
22250 var sz = this.boundEl.getSize();
\r
22251 switch(this.autoSize){
\r
22253 this.setSize(sz.width, "");
\r
22256 this.setSize("", sz.height);
\r
22259 this.setSize(sz.width, sz.height);
\r
22265 setSize : function(w, h){
\r
22266 delete this.field.lastSize;
\r
22267 this.field.setSize(w, h);
\r
22269 if(Ext.isGecko2 || Ext.isOpera){
\r
22270 // prevent layer scrollbars
\r
22271 this.el.setSize(w, h);
\r
22278 realign : function(){
\r
22279 this.el.alignTo(this.boundEl, this.alignment);
\r
22283 completeEdit : function(remainVisible){
\r
22284 if(!this.editing){
\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
22292 if(String(v) === String(this.startValue) && this.ignoreNoChange){
\r
22293 this.editing = false;
\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
22302 if(remainVisible !== true){
\r
22305 this.fireEvent("complete", this, v, this.startValue);
\r
22310 onShow : function(){
\r
22312 if(this.hideEl !== false){
\r
22313 this.boundEl.hide();
\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
22320 this.field.focus();
\r
22322 this.fireEvent("startedit", this.boundEl, this.startValue);
\r
22325 deferredFocus : function(){
\r
22326 if(this.editing){
\r
22327 this.field.focus();
\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
22339 this.fireEvent("canceledit", this, v, this.startValue);
\r
22344 onBlur : function(){
\r
22345 if(this.allowBlur !== true && this.editing){
\r
22346 this.completeEdit();
\r
22351 onHide : function(){
\r
22352 if(this.editing){
\r
22353 this.completeEdit();
\r
22356 this.field.blur();
\r
22357 if(this.field.collapse){
\r
22358 this.field.collapse();
\r
22361 if(this.hideEl !== false){
\r
22362 this.boundEl.show();
\r
22367 setValue : function(v){
\r
22368 this.field.setValue(v);
\r
22372 getValue : function(){
\r
22373 return this.field.getValue();
\r
22376 beforeDestroy : function(){
\r
22377 Ext.destroy(this.field);
\r
22378 this.field = null;
\r
22381 Ext.reg('editor', Ext.Editor);
\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
22389 var handleButton = function(button){
\r
22390 if(dlg.isVisible()){
\r
22392 Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
\r
22397 var handleHide = function(){
\r
22398 if(opt && opt.cls){
\r
22399 dlg.el.removeClass(opt.cls);
\r
22401 progressBar.reset();
\r
22405 var handleEsc = function(d, k, e){
\r
22406 if(opt && opt.closable !== false){
\r
22415 var updateButtons = function(b){
\r
22418 buttons["ok"].hide();
\r
22419 buttons["cancel"].hide();
\r
22420 buttons["yes"].hide();
\r
22421 buttons["no"].hide();
\r
22424 dlg.footer.dom.style.display = '';
\r
22425 for(var k in buttons){
\r
22426 if(typeof buttons[k] != "function"){
\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
22432 buttons[k].hide();
\r
22441 getDialog : function(titleText){
\r
22443 dlg = new Ext.Window({
\r
22444 autoCreate : true,
\r
22448 constrainHeader:true,
\r
22449 minimizable : false,
\r
22450 maximizable : false,
\r
22454 buttonAlign:"center",
\r
22461 close : function(){
\r
22462 if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
\r
22463 handleButton("no");
\r
22465 handleButton("cancel");
\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
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
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
22497 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
\r
22498 textareaEl.enableDisplayMode();
\r
22499 progressBar = new Ext.ProgressBar({
\r
22502 bodyEl.createChild({cls:'x-clear'});
\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
22512 msgEl.update(text || ' ');
\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
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
22526 if(opt.prompt === true){
\r
22527 activeTextEl.setWidth(w-iw-fw-bw);
\r
22529 if(opt.progress === true || opt.wait === true){
\r
22530 progressBar.setSize(w-iw-fw-bw);
\r
22532 if(Ext.isIE && w == bwidth){
\r
22533 w += 4; //Add offset when the content width is smaller than the buttons.
\r
22535 dlg.setSize(w, 'auto').center();
\r
22540 updateProgress : function(value, progressText, msg){
\r
22541 progressBar.updateProgress(value, progressText);
\r
22543 this.updateText(msg);
\r
22549 isVisible : function(){
\r
22550 return dlg && dlg.isVisible();
\r
22554 hide : function(){
\r
22555 var proxy = dlg.activeGhost;
\r
22556 if(this.isVisible() || proxy) {
\r
22567 show : function(options){
\r
22568 if(this.isVisible()){
\r
22572 var d = this.getDialog(opt.title || " ");
\r
22574 d.setTitle(opt.title || " ");
\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
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
22587 textboxEl.show();
\r
22588 textareaEl.hide();
\r
22591 textboxEl.hide();
\r
22592 textareaEl.hide();
\r
22594 activeTextEl.dom.value = opt.value || "";
\r
22596 d.focusEl = activeTextEl;
\r
22598 var bs = opt.buttons;
\r
22601 db = buttons["ok"];
\r
22602 }else if(bs && bs.yes){
\r
22603 db = buttons["yes"];
\r
22610 d.setIconClass(opt.iconCls);
\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
22618 d.el.addClass(opt.cls);
\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
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
22635 d.keyMap.disable();
\r
22637 }, this, {single:true});
\r
22639 if(opt.wait === true){
\r
22640 progressBar.wait(opt.waitConfig);
\r
22646 setIcon : function(icon){
\r
22647 if(icon && icon != ''){
\r
22648 iconEl.removeClass('x-hidden');
\r
22649 iconEl.replaceClass(iconCls, icon);
\r
22652 iconEl.replaceClass(iconCls, 'x-hidden');
\r
22659 progress : function(title, msg, progressText){
\r
22666 minWidth: this.minProgressWidth,
\r
22667 progressText: progressText
\r
22673 wait : function(msg, title, config){
\r
22681 minWidth: this.minProgressWidth,
\r
22682 waitConfig: config
\r
22688 alert : function(title, msg, fn, scope){
\r
22692 buttons: this.OK,
\r
22700 confirm : function(title, msg, fn, scope){
\r
22704 buttons: this.YESNO,
\r
22707 icon: this.QUESTION
\r
22713 prompt : function(title, msg, fn, scope, multiline, value){
\r
22717 buttons: this.OKCANCEL,
\r
22722 multiline: multiline,
\r
22731 CANCEL : {cancel:true},
\r
22733 OKCANCEL : {ok:true, cancel:true},
\r
22735 YESNO : {yes:true, no:true},
\r
22737 YESNOCANCEL : {yes:true, no:true, cancel:true},
\r
22739 INFO : 'ext-mb-info',
\r
22741 WARNING : 'ext-mb-warning',
\r
22743 QUESTION : 'ext-mb-question',
\r
22745 ERROR : 'ext-mb-error',
\r
22748 defaultTextHeight : 75,
\r
22754 minProgressWidth : 250,
\r
22758 cancel : "Cancel",
\r
22766 Ext.Msg = Ext.MessageBox;
\r
22768 Ext.Tip = Ext.extend(Ext.Panel, {
\r
22776 shadow : "sides",
\r
22778 defaultAlign : "tl-bl?",
\r
22779 autoRender: true,
\r
22780 quickShowInterval : 250,
\r
22782 // private panel overrides
\r
22785 baseCls: 'x-tip',
\r
22786 floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
\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
22798 afterRender : function(){
\r
22799 Ext.Tip.superclass.afterRender.call(this);
\r
22800 if(this.closable){
\r
22803 handler: this.hide,
\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
22815 if(this.constrainPosition){
\r
22816 xy = this.el.adjustForConstraints(xy);
\r
22818 this.setPagePosition(xy[0], xy[1]);
\r
22822 doAutoWidth : function(){
\r
22823 var bw = this.body.getTextWidth();
\r
22825 bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
\r
22827 bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
\r
22828 this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
\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
22838 showBy : function(el, pos){
\r
22839 if(!this.rendered){
\r
22840 this.render(Ext.getBody());
\r
22842 this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
\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
22851 // private - custom Tip DD implementation
\r
22852 Ext.Tip.DD = function(tip, config){
\r
22853 Ext.apply(this, config);
\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
22860 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
\r
22863 headerOffsets:[100, 25],
\r
22864 startDrag : function(){
\r
22865 this.tip.el.disableShadow();
\r
22867 endDrag : function(e){
\r
22868 this.tip.el.enableShadow(true);
\r
22872 Ext.ToolTip = Ext.extend(Ext.Tip, {
\r
22880 dismissDelay: 5000,
\r
22882 mouseOffset: [15,18],
\r
22884 trackMouse : false,
\r
22885 constrainPosition: true,
\r
22888 initComponent: function(){
\r
22889 Ext.ToolTip.superclass.initComponent.call(this);
\r
22890 this.lastActive = new Date();
\r
22891 this.initTarget();
\r
22895 initTarget : function(){
\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
22905 onMouseMove : function(e){
\r
22906 this.targetXY = e.getXY();
\r
22907 if(!this.hidden && this.trackMouse){
\r
22908 this.setPagePosition(this.getTargetXY());
\r
22913 getTargetXY : function(){
\r
22914 return [this.targetXY[0]+this.mouseOffset[0], this.targetXY[1]+this.mouseOffset[1]];
\r
22918 onTargetOver : function(e){
\r
22919 if(this.disabled || e.within(this.target.dom, true)){
\r
22922 this.clearTimer('hide');
\r
22923 this.targetXY = e.getXY();
\r
22924 this.delayShow();
\r
22928 delayShow : function(){
\r
22929 if(this.hidden && !this.showTimer){
\r
22930 if(this.lastActive.getElapsed() < this.quickShowInterval){
\r
22933 this.showTimer = this.show.defer(this.showDelay, this);
\r
22935 }else if(!this.hidden && this.autoHide !== false){
\r
22941 onTargetOut : function(e){
\r
22942 if(this.disabled || e.within(this.target.dom, true)){
\r
22945 this.clearTimer('show');
\r
22946 if(this.autoHide !== false){
\r
22947 this.delayHide();
\r
22952 delayHide : function(){
\r
22953 if(!this.hidden && !this.hideTimer){
\r
22954 this.hideTimer = this.hide.defer(this.hideDelay, this);
\r
22959 hide: function(){
\r
22960 this.clearTimer('dismiss');
\r
22961 this.lastActive = new Date();
\r
22962 Ext.ToolTip.superclass.hide.call(this);
\r
22966 show : function(){
\r
22967 this.showAt(this.getTargetXY());
\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
22981 clearTimer : function(name){
\r
22982 name = name + 'Timer';
\r
22983 clearTimeout(this[name]);
\r
22984 delete this[name];
\r
22988 clearTimers : function(){
\r
22989 this.clearTimer('show');
\r
22990 this.clearTimer('dismiss');
\r
22991 this.clearTimer('hide');
\r
22995 onShow : function(){
\r
22996 Ext.ToolTip.superclass.onShow.call(this);
\r
22997 Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
\r
23001 onHide : function(){
\r
23002 Ext.ToolTip.superclass.onHide.call(this);
\r
23003 Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
\r
23007 onDocMouseDown : function(e){
\r
23008 if(this.autoHide !== false && !e.within(this.el.dom)){
\r
23010 this.enable.defer(100, this);
\r
23015 onDisable : function(){
\r
23016 this.clearTimers();
\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
23027 return {x : x, y: y};
\r
23031 onDestroy : function(){
\r
23032 Ext.ToolTip.superclass.onDestroy.call(this);
\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
23041 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
\r
23044 interceptTitles : false,
\r
23048 namespace : "ext",
\r
23049 attribute : "qtip",
\r
23050 width : "qwidth",
\r
23051 target : "target",
\r
23052 title : "qtitle",
\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
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
23070 var target = c.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
23077 this.targets[Ext.id(target)] = c;
\r
23084 unregister : function(el){
\r
23085 delete this.targets[Ext.id(el)];
\r
23089 onTargetOver : function(e){
\r
23090 if(this.disabled){
\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
23098 if(this.activeTarget && t == this.activeTarget.el){
\r
23099 this.clearTimer('hide');
\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
23109 var ttp, et = Ext.fly(t), cfg = this.tagConfig;
\r
23110 var ns = cfg.namespace;
\r
23111 if(this.interceptTitles && t.title){
\r
23114 t.removeAttribute("title");
\r
23115 e.preventDefault();
\r
23117 ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
\r
23120 var autoHide = et.getAttributeNS(ns, cfg.hide);
\r
23121 this.activeTarget = {
\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
23130 this.delayShow();
\r
23135 onTargetOut : function(e){
\r
23136 this.clearTimer('show');
\r
23137 if(this.autoHide !== false){
\r
23138 this.delayHide();
\r
23143 showAt : function(xy){
\r
23144 var t = this.activeTarget;
\r
23146 if(!this.rendered){
\r
23147 this.render(Ext.getBody());
\r
23148 this.activeTarget = t;
\r
23151 this.setWidth(t.width);
\r
23152 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
\r
23153 this.measureWidth = false;
\r
23155 this.measureWidth = true;
\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
23166 this.el.addClass(t.cls);
\r
23167 this.lastCls = t.cls;
\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
23173 this.constrainPosition = true;
\r
23176 Ext.QuickTip.superclass.showAt.call(this, xy);
\r
23180 hide: function(){
\r
23181 delete this.activeTarget;
\r
23182 Ext.QuickTip.superclass.hide.call(this);
\r
23186 Ext.QuickTips = function(){
\r
23187 var tip, locks = [];
\r
23190 init : function(autoRender){
\r
23192 if(!Ext.isReady){
\r
23193 Ext.onReady(function(){
\r
23194 Ext.QuickTips.init(autoRender);
\r
23198 tip = new Ext.QuickTip({elements:'header,body'});
\r
23199 if(autoRender !== false){
\r
23200 tip.render(Ext.getBody());
\r
23206 enable : function(){
\r
23209 if(locks.length < 1){
\r
23216 disable : function(){
\r
23224 isEnabled : function(){
\r
23225 return tip !== undefined && !tip.disabled;
\r
23229 getQuickTip : function(){
\r
23234 register : function(){
\r
23235 tip.register.apply(tip, arguments);
\r
23239 unregister : function(){
\r
23240 tip.unregister.apply(tip, arguments);
\r
23244 tips :function(){
\r
23245 tip.register.apply(tip, arguments);
\r
23250 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
\r
23251 rootVisible : true,
\r
23252 animate: Ext.enableFx,
\r
23254 enableDD : false,
\r
23255 hlDrop : Ext.enableFx,
\r
23256 pathSeparator: "/",
\r
23258 initComponent : function(){
\r
23259 Ext.tree.TreePanel.superclass.initComponent.call(this);
\r
23261 if(!this.eventModel){
\r
23262 this.eventModel = new Ext.tree.TreeEventModel(this);
\r
23265 // initialize the loader
\r
23266 var l = this.loader;
\r
23268 l = new Ext.tree.TreeLoader({
\r
23269 dataUrl: this.dataUrl
\r
23271 }else if(typeof l == 'object' && !l.load){
\r
23272 l = new Ext.tree.TreeLoader(l);
\r
23276 this.nodeHash = {};
\r
23280 this.setRootNode(this.root);
\r
23298 "beforemovenode",
\r
23309 "beforeexpandnode",
\r
23311 "beforecollapsenode",
\r
23315 "disabledchange",
\r
23329 "beforechildrenrendered",
\r
23337 "beforenodedrop",
\r
23343 if(this.singleExpand){
\r
23344 this.on("beforeexpandnode", this.restrictExpand, this);
\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
23353 // args inline for performance while bubbling events
\r
23354 return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
\r
23359 getRootNode : function(){
\r
23360 return this.root;
\r
23364 setRootNode : function(node){
\r
23365 if(!node.render){ // attributes passed
\r
23366 node = this.loader.createNode(node);
\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
23380 getNodeById : function(id){
\r
23381 return this.nodeHash[id];
\r
23385 registerNode : function(node){
\r
23386 this.nodeHash[node.id] = node;
\r
23390 unregisterNode : function(node){
\r
23391 delete this.nodeHash[node.id];
\r
23395 toString : function(){
\r
23396 return "[Tree"+(this.id?" "+this.id:"")+"]";
\r
23400 restrictExpand : function(node){
\r
23401 var p = node.parentNode;
\r
23403 if(p.expandedChild && p.expandedChild.parentNode == p){
\r
23404 p.expandedChild.collapse();
\r
23406 p.expandedChild = node;
\r
23411 getChecked : function(a, startNode){
\r
23412 startNode = startNode || this.root;
\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
23419 startNode.cascade(f);
\r
23424 getEl : function(){
\r
23429 getLoader : function(){
\r
23430 return this.loader;
\r
23434 expandAll : function(){
\r
23435 this.root.expand(true);
\r
23439 collapseAll : function(){
\r
23440 this.root.collapse(true);
\r
23444 getSelectionModel : function(){
\r
23445 if(!this.selModel){
\r
23446 this.selModel = new Ext.tree.DefaultSelectionModel();
\r
23448 return this.selModel;
\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
23458 callback(false, null);
\r
23463 var f = function(){
\r
23464 if(++index == keys.length){
\r
23466 callback(true, curNode);
\r
23470 var c = curNode.findChild(attr, keys[index]);
\r
23473 callback(false, curNode);
\r
23478 c.expand(false, false, f);
\r
23480 curNode.expand(false, false, f);
\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
23495 callback(true, n);
\r
23497 }else if(callback){
\r
23498 callback(false, n);
\r
23502 callback(false, n);
\r
23506 this.expandPath(keys.join(this.pathSeparator), attr, f);
\r
23508 this.root.select();
\r
23510 callback(true, this.root);
\r
23516 getTreeEl : function(){
\r
23517 return this.body;
\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
23530 initEvents : function(){
\r
23531 Ext.tree.TreePanel.superclass.initEvents.call(this);
\r
23533 if(this.containerScroll){
\r
23534 Ext.dd.ScrollManager.register(this.body);
\r
23536 if((this.enableDD || this.enableDrop) && !this.dropZone){
\r
23538 this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
\r
23539 ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
\r
23542 if((this.enableDD || this.enableDrag) && !this.dragZone){
\r
23544 this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
\r
23545 ddGroup: this.ddGroup || "TreeDD",
\r
23546 scroll: this.ddScroll
\r
23549 this.getSelectionModel().init(this);
\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
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
23568 if(this.dragZone){
\r
23569 this.dragZone.unreg();
\r
23572 this.root.destroy();
\r
23573 this.nodeHash = null;
\r
23574 Ext.tree.TreePanel.superclass.onDestroy.call(this);
\r
23625 Ext.tree.TreePanel.nodeTypes = {};
\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
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
23641 el.on('dblclick', this.delegateDblClick, this);
\r
23642 el.on('contextmenu', this.delegateContextMenu, this);
\r
23645 getNode : function(e){
\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
23650 return this.tree.getNodeById(id);
\r
23656 getNodeTarget : function(e){
\r
23657 var t = e.getTarget('.x-tree-node-icon', 1);
\r
23659 t = e.getTarget('.x-tree-node-el', 6);
\r
23664 delegateOut : function(e, t){
\r
23665 if(!this.beforeEvent(e)){
\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
23675 if((t = this.getNodeTarget(e)) && !e.within(t, true)){
\r
23676 this.onNodeOut(e, this.getNode(e));
\r
23680 delegateOver : function(e, t){
\r
23681 if(!this.beforeEvent(e)){
\r
23684 if(this.lastEcOver){ // prevent hung highlight
\r
23685 this.onIconOut(e, this.lastEcOver);
\r
23686 delete this.lastEcOver;
\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
23692 if(t = this.getNodeTarget(e)){
\r
23693 this.onNodeOver(e, this.getNode(e));
\r
23697 delegateClick : function(e, t){
\r
23698 if(!this.beforeEvent(e)){
\r
23702 if(e.getTarget('input[type=checkbox]', 1)){
\r
23703 this.onCheckboxClick(e, this.getNode(e));
\r
23705 else if(e.getTarget('.x-tree-ec-icon', 1)){
\r
23706 this.onIconClick(e, this.getNode(e));
\r
23708 else if(this.getNodeTarget(e)){
\r
23709 this.onNodeClick(e, this.getNode(e));
\r
23713 delegateDblClick : function(e, t){
\r
23714 if(this.beforeEvent(e) && this.getNodeTarget(e)){
\r
23715 this.onNodeDblClick(e, this.getNode(e));
\r
23719 delegateContextMenu : function(e, t){
\r
23720 if(this.beforeEvent(e) && this.getNodeTarget(e)){
\r
23721 this.onNodeContextMenu(e, this.getNode(e));
\r
23725 onNodeClick : function(e, node){
\r
23726 node.ui.onClick(e);
\r
23729 onNodeOver : function(e, node){
\r
23730 node.ui.onOver(e);
\r
23733 onNodeOut : function(e, node){
\r
23734 node.ui.onOut(e);
\r
23737 onIconOver : function(e, node){
\r
23738 node.ui.addClass('x-tree-ec-over');
\r
23741 onIconOut : function(e, node){
\r
23742 node.ui.removeClass('x-tree-ec-over');
\r
23745 onIconClick : function(e, node){
\r
23746 node.ui.ecClick(e);
\r
23749 onCheckboxClick : function(e, node){
\r
23750 node.ui.onCheckChange(e);
\r
23753 onNodeDblClick : function(e, node){
\r
23754 node.ui.onDblClick(e);
\r
23757 onNodeContextMenu : function(e, node){
\r
23758 node.ui.onContextMenu(e);
\r
23761 beforeEvent : function(e){
\r
23762 if(this.disabled){
\r
23769 disable: function(){
\r
23770 this.disabled = true;
\r
23773 enable: function(){
\r
23774 this.disabled = false;
\r
23778 Ext.tree.DefaultSelectionModel = function(config){
\r
23779 this.selNode = null;
\r
23783 "selectionchange",
\r
23789 Ext.apply(this, config);
\r
23790 Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
\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
23800 onNodeClick : function(node, e){
\r
23801 this.select(node);
\r
23805 select : function(node){
\r
23806 var last = this.selNode;
\r
23807 if(last != node && this.fireEvent('beforeselect', this, node, last) !== false){
\r
23809 last.ui.onSelectedChange(false);
\r
23811 this.selNode = node;
\r
23812 node.ui.onSelectedChange(true);
\r
23813 this.fireEvent("selectionchange", this, node, last);
\r
23819 unselect : function(node){
\r
23820 if(this.selNode == node){
\r
23821 this.clearSelections();
\r
23826 clearSelections : function(){
\r
23827 var n = this.selNode;
\r
23829 n.ui.onSelectedChange(false);
\r
23830 this.selNode = null;
\r
23831 this.fireEvent("selectionchange", this, null);
\r
23837 getSelectedNode : function(){
\r
23838 return this.selNode;
\r
23842 isSelected : function(node){
\r
23843 return this.selNode == node;
\r
23847 selectPrevious : function(){
\r
23848 var s = this.selNode || this.lastSelNode;
\r
23852 var ps = s.previousSibling;
\r
23854 if(!ps.isExpanded() || ps.childNodes.length < 1){
\r
23855 return this.select(ps);
\r
23857 var lc = ps.lastChild;
\r
23858 while(lc && lc.isExpanded() && lc.childNodes.length > 0){
\r
23859 lc = lc.lastChild;
\r
23861 return this.select(lc);
\r
23863 } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
\r
23864 return this.select(s.parentNode);
\r
23870 selectNext : function(){
\r
23871 var s = this.selNode || this.lastSelNode;
\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
23881 s.parentNode.bubble(function(){
\r
23882 if(this.nextSibling){
\r
23883 newS = this.getOwnerTree().selModel.select(this.nextSibling);
\r
23892 onKeyDown : function(e){
\r
23893 var s = this.selNode || this.lastSelNode;
\r
23894 // undesirable, but required
\r
23899 var k = e.getKey();
\r
23903 this.selectNext();
\r
23907 this.selectPrevious();
\r
23910 e.preventDefault();
\r
23911 if(s.hasChildNodes()){
\r
23912 if(!s.isExpanded()){
\r
23914 }else if(s.firstChild){
\r
23915 this.select(s.firstChild, e);
\r
23920 e.preventDefault();
\r
23921 if(s.hasChildNodes() && s.isExpanded()){
\r
23923 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
\r
23924 this.select(s.parentNode, e);
\r
23932 Ext.tree.MultiSelectionModel = function(config){
\r
23933 this.selNodes = [];
\r
23934 this.selMap = {};
\r
23937 "selectionchange"
\r
23939 Ext.apply(this, config);
\r
23940 Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
\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
23950 onNodeClick : function(node, e){
\r
23951 this.select(node, e, e.ctrlKey);
\r
23955 select : function(node, e, keepExisting){
\r
23956 if(keepExisting !== true){
\r
23957 this.clearSelections(true);
\r
23959 if(this.isSelected(node)){
\r
23960 this.lastSelNode = node;
\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
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
23978 this.selNodes.splice(index, 1);
\r
23980 delete this.selMap[node.id];
\r
23981 this.fireEvent("selectionchange", this, this.selNodes);
\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
23992 this.selNodes = [];
\r
23993 this.selMap = {};
\r
23994 if(suppressEvent !== true){
\r
23995 this.fireEvent("selectionchange", this, this.selNodes);
\r
24001 isSelected : function(node){
\r
24002 return this.selMap[node.id] ? true : false;
\r
24006 getSelectedNodes : function(){
\r
24007 return this.selNodes;
\r
24010 onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
\r
24012 selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
\r
24014 selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
\r
24017 Ext.tree.TreeNode = function(attributes){
\r
24018 attributes = attributes || {};
\r
24019 if(typeof attributes == "string"){
\r
24020 attributes = {text: attributes};
\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
24031 this.text = attributes.text;
\r
24033 this.disabled = attributes.disabled === true;
\r
24041 "beforecollapse",
\r
24045 "disabledchange",
\r
24059 "beforechildrenrendered"
\r
24062 var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
\r
24065 this.ui = new uiClass(this);
\r
24067 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
\r
24068 preventHScroll: true,
\r
24070 isExpanded : function(){
\r
24071 return this.expanded;
\r
24075 getUI : function(){
\r
24079 getLoader : function(){
\r
24081 return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());
\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
24091 if(this.rendered){
\r
24092 this.renderIndent(true, true);
\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
24103 if(this.rendered){
\r
24104 this.renderIndent(true, true);
\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
24114 var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
\r
24115 if(node && this.childrenRendered){
\r
24118 this.ui.updateExpandIcon();
\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
24130 if(this.childNodes.length < 1){
\r
24131 this.collapse(false, false);
\r
24133 this.ui.updateExpandIcon();
\r
24135 if(!this.firstChild && !this.isHiddenRoot()) {
\r
24136 this.childrenRendered = false;
\r
24141 // private override
\r
24142 insertBefore : function(node, refNode){
\r
24143 if(!node.render){
\r
24144 node = this.getLoader().createNode(node);
\r
24146 var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
\r
24147 if(newNode && refNode && this.childrenRendered){
\r
24150 this.ui.updateExpandIcon();
\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
24162 this.fireEvent("textchange", this, text, oldText);
\r
24166 select : function(){
\r
24167 this.getOwnerTree().getSelectionModel().select(this);
\r
24171 unselect : function(){
\r
24172 this.getOwnerTree().getSelectionModel().unselect(this);
\r
24176 isSelected : function(){
\r
24177 return this.getOwnerTree().getSelectionModel().isSelected(this);
\r
24181 expand : function(deep, anim, callback){
\r
24182 if(!this.expanded){
\r
24183 if(this.fireEvent("beforeexpand", this, deep, anim) === false){
\r
24186 if(!this.childrenRendered){
\r
24187 this.renderChildren();
\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
24196 if(deep === true){
\r
24197 this.expandChildNodes(true);
\r
24199 }.createDelegate(this));
\r
24202 this.ui.expand();
\r
24203 this.fireEvent("expand", this);
\r
24204 if(typeof callback == "function"){
\r
24209 if(typeof callback == "function"){
\r
24213 if(deep === true){
\r
24214 this.expandChildNodes(true);
\r
24218 isHiddenRoot : function(){
\r
24219 return this.isRoot && !this.getOwnerTree().rootVisible;
\r
24223 collapse : function(deep, anim){
\r
24224 if(this.expanded && !this.isHiddenRoot()){
\r
24225 if(this.fireEvent("beforecollapse", this, deep, anim) === false){
\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
24235 }.createDelegate(this));
\r
24238 this.ui.collapse();
\r
24239 this.fireEvent("collapse", this);
\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
24251 delayedExpand : function(delay){
\r
24252 if(!this.expandProcId){
\r
24253 this.expandProcId = this.expand.defer(delay, this);
\r
24258 cancelExpand : function(){
\r
24259 if(this.expandProcId){
\r
24260 clearTimeout(this.expandProcId);
\r
24262 this.expandProcId = false;
\r
24266 toggle : function(){
\r
24267 if(this.expanded){
\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
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
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
24301 disable : function(){
\r
24302 this.disabled = true;
\r
24304 if(this.rendered && this.ui.onDisableChange){ // event without subscribing
\r
24305 this.ui.onDisableChange(this, true);
\r
24307 this.fireEvent("disabledchange", this, true);
\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
24316 this.fireEvent("disabledchange", this, false);
\r
24320 renderChildren : function(suppressEvent){
\r
24321 if(suppressEvent !== false){
\r
24322 this.fireEvent("beforechildrenrendered", this);
\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
24328 this.childrenRendered = true;
\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
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
24357 renderIndent : function(deep, refresh){
\r
24359 this.ui.childIndent = null;
\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
24370 beginUpdate : function(){
\r
24371 this.childrenRendered = false;
\r
24374 endUpdate : function(){
\r
24375 if(this.expanded && this.rendered){
\r
24376 this.renderChildren();
\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
24385 this.childNodes = null;
\r
24387 if(this.ui.destroy){
\r
24388 this.ui.destroy();
\r
24393 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
\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
24400 this.addEvents('beforeload', 'load');
\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
24408 var f = function(){
\r
24409 if(!this.loading){ // done loading
\r
24410 clearInterval(timer);
\r
24411 this.expand(deep, anim, callback);
\r
24413 }.createDelegate(this);
\r
24414 timer = setInterval(f, 200);
\r
24417 if(!this.loaded){
\r
24418 if(this.fireEvent("beforeload", this) === false){
\r
24421 this.loading = true;
\r
24422 this.ui.beforeLoad(this);
\r
24423 var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
\r
24425 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
\r
24429 Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
\r
24433 isLoading : function(){
\r
24434 return this.loading;
\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
24446 isLoaded : function(){
\r
24447 return this.loaded;
\r
24450 hasChildNodes : function(){
\r
24451 if(!this.isLeaf() && !this.loaded){
\r
24454 return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
\r
24459 reload : function(callback){
\r
24460 this.collapse(false, false);
\r
24461 while(this.firstChild){
\r
24462 this.removeChild(this.firstChild).destroy();
\r
24464 this.childrenRendered = false;
\r
24465 this.loaded = false;
\r
24466 if(this.isHiddenRoot()){
\r
24467 this.expanded = false;
\r
24469 this.expand(false, false, callback);
\r
24473 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
\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
24484 Ext.tree.TreeNodeUI.prototype = {
\r
24486 removeChild : function(node){
\r
24487 if(this.rendered){
\r
24488 this.ctNode.removeChild(node.ui.getEl());
\r
24493 beforeLoad : function(){
\r
24494 this.addClass("x-tree-node-loading");
\r
24498 afterLoad : function(){
\r
24499 this.removeClass("x-tree-node-loading");
\r
24503 onTextChange : function(node, text, oldText){
\r
24504 if(this.rendered){
\r
24505 this.textNode.innerHTML = text;
\r
24510 onDisableChange : function(node, state){
\r
24511 this.disabled = state;
\r
24512 if (this.checkbox) {
\r
24513 this.checkbox.disabled = state;
\r
24516 this.addClass("x-tree-node-disabled");
\r
24518 this.removeClass("x-tree-node-disabled");
\r
24523 onSelectedChange : function(state){
\r
24526 this.addClass("x-tree-selected");
\r
24529 this.removeClass("x-tree-selected");
\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
24543 var insertBefore = refNode ? refNode.ui.getEl() : null;
\r
24544 if(insertBefore){
\r
24545 targetNode.insertBefore(this.wrap, insertBefore);
\r
24547 targetNode.appendChild(this.wrap);
\r
24549 this.node.renderIndent(true);
\r
24554 addClass : function(cls){
\r
24556 Ext.fly(this.elNode).addClass(cls);
\r
24561 removeClass : function(cls){
\r
24563 Ext.fly(this.elNode).removeClass(cls);
\r
24568 remove : function(){
\r
24569 if(this.rendered){
\r
24570 this.holder = document.createElement("div");
\r
24571 this.holder.appendChild(this.wrap);
\r
24576 fireEvent : function(){
\r
24577 return this.node.fireEvent.apply(this.node, arguments);
\r
24581 initEvents : function(){
\r
24582 this.node.on("move", this.onMove, this);
\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
24590 if(this.node.hidden){
\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
24598 handles: this.getDDHandles(),
\r
24605 getDDHandles : function(){
\r
24606 return [this.iconNode, this.textNode, this.elNode];
\r
24610 hide : function(){
\r
24611 this.node.hidden = true;
\r
24613 this.wrap.style.display = "none";
\r
24618 show : function(){
\r
24619 this.node.hidden = false;
\r
24621 this.wrap.style.display = "";
\r
24626 onContextMenu : function(e){
\r
24627 if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
\r
24628 e.preventDefault();
\r
24630 this.fireEvent("contextmenu", this.node, e);
\r
24635 onClick : function(e){
\r
24636 if(this.dropping){
\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
24645 }else if(a && e.ctrlKey){
\r
24648 e.preventDefault();
\r
24649 if(this.disabled){
\r
24653 if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
\r
24654 this.node.toggle();
\r
24657 this.fireEvent("click", this.node, e);
\r
24664 onDblClick : function(e){
\r
24665 e.preventDefault();
\r
24666 if(this.disabled){
\r
24669 if(this.checkbox){
\r
24670 this.toggleCheck();
\r
24672 if(!this.animating && this.node.isExpandable()){
\r
24673 this.node.toggle();
\r
24675 this.fireEvent("dblclick", this.node, e);
\r
24678 onOver : function(e){
\r
24679 this.addClass('x-tree-node-over');
\r
24682 onOut : function(e){
\r
24683 this.removeClass('x-tree-node-over');
\r
24687 onCheckChange : function(){
\r
24688 var checked = this.checkbox.checked;
\r
24690 this.checkbox.defaultChecked = checked;
\r
24691 this.node.attributes.checked = checked;
\r
24692 this.fireEvent('checkchange', this.node, checked);
\r
24696 ecClick : function(e){
\r
24697 if(!this.animating && this.node.isExpandable()){
\r
24698 this.node.toggle();
\r
24703 startDrop : function(){
\r
24704 this.dropping = true;
\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
24715 expand : function(){
\r
24716 this.updateExpandIcon();
\r
24717 this.ctNode.style.display = "";
\r
24721 focus : function(){
\r
24722 if(!this.node.preventHScroll){
\r
24723 try{this.anchor.focus();
\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
24736 toggleCheck : function(value){
\r
24737 var cb = this.checkbox;
\r
24739 cb.checked = (value === undefined ? !cb.checked : value);
\r
24740 this.onCheckChange();
\r
24745 blur : function(){
\r
24747 this.anchor.blur();
\r
24752 animExpand : function(callback){
\r
24753 var ct = Ext.get(this.ctNode);
\r
24755 if(!this.node.isExpandable()){
\r
24756 this.updateExpandIcon();
\r
24757 this.ctNode.style.display = "";
\r
24758 Ext.callback(callback);
\r
24761 this.animating = true;
\r
24762 this.updateExpandIcon();
\r
24764 ct.slideIn('t', {
\r
24765 callback : function(){
\r
24766 this.animating = false;
\r
24767 Ext.callback(callback);
\r
24770 duration: this.node.ownerTree.duration || .25
\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
24784 collapse : function(){
\r
24785 this.updateExpandIcon();
\r
24786 this.ctNode.style.display = "none";
\r
24790 animCollapse : function(callback){
\r
24791 var ct = Ext.get(this.ctNode);
\r
24792 ct.enableDisplayMode('block');
\r
24795 this.animating = true;
\r
24796 this.updateExpandIcon();
\r
24798 ct.slideOut('t', {
\r
24799 callback : function(){
\r
24800 this.animating = false;
\r
24801 Ext.callback(callback);
\r
24804 duration: this.node.ownerTree.duration || .25
\r
24809 getContainer : function(){
\r
24810 return this.ctNode;
\r
24814 getEl : function(){
\r
24815 return this.wrap;
\r
24819 appendDDGhost : function(ghostNode){
\r
24820 ghostNode.appendChild(this.elNode.cloneNode(true));
\r
24824 getDDRepairXY : function(){
\r
24825 return Ext.lib.Dom.getXY(this.iconNode);
\r
24829 onRender : function(){
\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
24839 if(!this.rendered){
\r
24840 this.rendered = true;
\r
24842 this.renderElements(n, a, targetNode, bulkRender);
\r
24845 if(this.textNode.setAttributeNS){
\r
24846 this.textNode.setAttributeNS("ext", "qtip", a.qtip);
\r
24848 this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
\r
24851 this.textNode.setAttribute("ext:qtip", a.qtip);
\r
24853 this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
\r
24856 }else if(a.qtipCfg){
\r
24857 a.qtipCfg.target = Ext.id(this.textNode);
\r
24858 Ext.QuickTips.register(a.qtipCfg);
\r
24860 this.initEvents();
\r
24861 if(!this.node.expanded){
\r
24862 this.updateExpandIcon(true);
\r
24865 if(bulkRender === true) {
\r
24866 targetNode.appendChild(this.wrap);
\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
24876 var cb = typeof a.checked == 'boolean';
\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
24890 if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
\r
24891 this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
\r
24893 this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
\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
24904 this.checkbox = cs[3];
\r
24906 this.checkbox.defaultChecked = this.checkbox.checked;
\r
24909 this.anchor = cs[index];
\r
24910 this.textNode = cs[index].firstChild;
\r
24914 getAnchor : function(){
\r
24915 return this.anchor;
\r
24919 getTextEl : function(){
\r
24920 return this.textNode;
\r
24924 getIconEl : function(){
\r
24925 return this.iconNode;
\r
24929 isChecked : function(){
\r
24930 return this.checkbox ? this.checkbox.checked : false;
\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
24941 c1 = "x-tree-node-collapsed";
\r
24942 c2 = "x-tree-node-expanded";
\r
24945 c1 = "x-tree-node-expanded";
\r
24946 c2 = "x-tree-node-collapsed";
\r
24948 if(this.wasLeaf){
\r
24949 this.removeClass("x-tree-node-leaf");
\r
24950 this.wasLeaf = false;
\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
24957 if(!this.wasLeaf){
\r
24958 Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
\r
24961 this.wasLeaf = true;
\r
24964 var ecc = "x-tree-ec-icon "+cls;
\r
24965 if(this.ecc != ecc){
\r
24966 this.ecNode.className = ecc;
\r
24973 getChildIndent : function(){
\r
24974 if(!this.childIndent){
\r
24976 var p = this.node;
\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
24982 buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
\r
24985 p = p.parentNode;
\r
24987 this.childIndent = buf.join("");
\r
24989 return this.childIndent;
\r
24993 renderIndent : function(){
\r
24994 if(this.rendered){
\r
24996 var p = this.node.parentNode;
\r
24998 indent = p.ui.getChildIndent();
\r
25000 if(this.indentMarkup != indent){ // don't rerender if not required
\r
25001 this.indentNode.innerHTML = indent;
\r
25002 this.indentMarkup = indent;
\r
25004 this.updateExpandIcon();
\r
25008 destroy : function(){
\r
25010 Ext.dd.Registry.unregister(this.elNode.id);
\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
25021 if (this.holder){
\r
25022 delete this.wrap;
\r
25023 Ext.removeNode(this.holder);
\r
25024 delete this.holder;
\r
25026 Ext.removeNode(this.wrap);
\r
25027 delete this.wrap;
\r
25033 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
\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
25043 collapse : Ext.emptyFn,
\r
25044 expand : Ext.emptyFn
\r
25047 Ext.tree.TreeLoader = function(config){
\r
25048 this.baseParams = {};
\r
25049 Ext.apply(this, config);
\r
25060 Ext.tree.TreeLoader.superclass.constructor.call(this);
\r
25063 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
\r
25071 uiProviders : {},
\r
25074 clearOnLoad : true,
\r
25077 load : function(node, callback){
\r
25078 if(this.clearOnLoad){
\r
25079 while(node.firstChild){
\r
25080 node.removeChild(node.firstChild);
\r
25083 if(this.doPreload(node)){ // preloaded json children
\r
25084 if(typeof callback == "function"){
\r
25087 }else if(this.dataUrl||this.url){
\r
25088 this.requestData(node, callback);
\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
25103 node.endUpdate();
\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
25118 buf.push("node=", encodeURIComponent(node.id));
\r
25119 return buf.join("");
\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
25130 argument: {callback: callback, node: node},
\r
25131 params: this.getParams(node)
\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
25142 isLoading : function(){
\r
25143 return !!this.transId;
\r
25146 abort : function(){
\r
25147 if(this.isLoading()){
\r
25148 Ext.Ajax.abort(this.transId);
\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
25158 if(this.applyLoader !== false){
\r
25159 attr.loader = this;
\r
25161 if(typeof attr.uiProvider == 'string'){
\r
25162 attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
\r
25164 if(attr.nodeType){
\r
25165 return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
\r
25167 return attr.leaf ?
\r
25168 new Ext.tree.TreeNode(attr) :
\r
25169 new Ext.tree.AsyncTreeNode(attr);
\r
25173 processResponse : function(response, node, callback){
\r
25174 var json = response.responseText;
\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
25181 node.appendChild(n);
\r
25184 node.endUpdate();
\r
25185 if(typeof callback == "function"){
\r
25186 callback(this, node);
\r
25189 this.handleFailure(response);
\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
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
25210 Ext.tree.TreeFilter = function(tree, config){
\r
25211 this.tree = tree;
\r
25212 this.filtered = {};
\r
25213 Ext.apply(this, config);
\r
25216 Ext.tree.TreeFilter.prototype = {
\r
25217 clearBlank:false,
\r
25223 filter : function(value, attr, startNode){
\r
25224 attr = attr || "text";
\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
25233 value = value.toLowerCase();
\r
25235 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
\r
25237 }else if(value.exec){ // regex?
\r
25239 return value.test(n.attributes[attr]);
\r
25242 throw 'Illegal filter type, must be string or regex';
\r
25244 this.filterBy(f, null, startNode);
\r
25248 filterBy : function(fn, scope, startNode){
\r
25249 startNode = startNode || this.tree.root;
\r
25250 if(this.autoClear){
\r
25253 var af = this.filtered, rv = this.reverse;
\r
25254 var f = function(n){
\r
25255 if(n == startNode){
\r
25261 var m = fn.call(scope || n, n);
\r
25269 startNode.cascade(f);
\r
25271 for(var id in af){
\r
25272 if(typeof id != "function"){
\r
25274 if(n && n.parentNode){
\r
25275 n.parentNode.removeChild(n);
\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
25294 this.filtered = {};
\r
25299 Ext.tree.TreeSorter = function(tree, config){
\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
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
25320 this.sortFn = function(n1, n2){
\r
25322 if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
\r
25325 if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
\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
25332 return dsc ? +1 : -1;
\r
25333 }else if(v1 > v2){
\r
25334 return dsc ? -1 : +1;
\r
25341 Ext.tree.TreeSorter.prototype = {
\r
25342 doSort : function(node){
\r
25343 node.sort(this.sortFn);
\r
25346 compareNodes : function(n1, n2){
\r
25347 return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
\r
25350 updateSort : function(tree, node){
\r
25351 if(node.childrenRendered){
\r
25352 this.doSort.defer(1, this, [node]);
\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
25364 if(Ext.dd.DropZone){
\r
25366 Ext.tree.TreeDropZone = function(tree, config){
\r
25368 this.allowParentInsert = false;
\r
25370 this.allowContainerDrop = false;
\r
25372 this.appendOnly = false;
\r
25373 Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);
\r
25375 this.tree = tree;
\r
25377 this.dragOverData = {};
\r
25379 this.lastInsertClass = "x-tree-no-status";
\r
25382 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
\r
25384 ddGroup : "TreeDD",
\r
25387 expandDelay : 1000,
\r
25390 expandNode : function(node){
\r
25391 if(node.hasChildNodes() && !node.isExpanded()){
\r
25392 node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
\r
25397 queueExpand : function(node){
\r
25398 this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
\r
25402 cancelExpand : function(){
\r
25403 if(this.expandProcId){
\r
25404 clearTimeout(this.expandProcId);
\r
25405 this.expandProcId = false;
\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
25418 if(pt == "append" && targetNode.allowChildren === false){
\r
25421 if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
\r
25424 if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
\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
25442 getDropPoint : function(e, n, dd){
\r
25445 return tn.allowChildren !== false ? "append" : false; // always append for root
\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
25454 var noBelow = false;
\r
25455 if(!this.allowParentInsert){
\r
25456 noBelow = tn.hasChildNodes() && tn.isExpanded();
\r
25458 var q = (b - t) / (noAppend ? 2 : 3);
\r
25459 if(y >= t && y < (t + q)){
\r
25461 }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
\r
25469 onNodeEnter : function(n, dd, e, data){
\r
25470 this.cancelExpand();
\r
25474 onNodeOver : function(n, dd, e, data){
\r
25475 var pt = this.getDropPoint(e, n, dd);
\r
25476 var node = n.node;
\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
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
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
25498 returnCls = "x-tree-drop-ok-append";
\r
25499 cls = "x-tree-drag-append";
\r
25501 if(this.lastInsertClass != cls){
\r
25502 Ext.fly(el).replaceClass(this.lastInsertClass, cls);
\r
25503 this.lastInsertClass = cls;
\r
25507 return returnCls;
\r
25511 onNodeOut : function(n, dd, e, data){
\r
25512 this.cancelExpand();
\r
25513 this.removeDropIndicators(n);
\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
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
25534 dropNode: dropNode,
\r
25535 cancel: !dropNode,
\r
25536 dropStatus: false
\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
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
25550 this.completeDrop(dropEvent);
\r
25556 completeDrop : function(de){
\r
25557 var ns = de.dropNode, p = de.point, t = de.target;
\r
25558 if(!Ext.isArray(ns)){
\r
25562 for(var i = 0, len = ns.length; i < len; 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
25569 t.appendChild(n);
\r
25573 if(Ext.enableFx && this.tree.hlDrop){
\r
25574 n.ui.highlight();
\r
25577 this.tree.fireEvent("nodedrop", de);
\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
25586 this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
\r
25590 getTree : function(){
\r
25591 return this.tree;
\r
25595 removeDropIndicators : function(n){
\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
25607 beforeDragDrop : function(target, e, id){
\r
25608 this.cancelExpand();
\r
25613 afterRepair : function(data){
\r
25614 if(data && Ext.enableFx){
\r
25615 data.node.ui.highlight();
\r
25617 this.hideProxy();
\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
25627 this.tree = tree;
\r
25630 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
\r
25632 ddGroup : "TreeDD",
\r
25635 onBeforeDrag : function(data, e){
\r
25636 var n = data.node;
\r
25637 return n && n.draggable && !n.disabled;
\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
25651 getRepairXY : function(e, data){
\r
25652 return data.node.ui.getDDRepairXY();
\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
25662 onValidDrop : function(dd, e, id){
\r
25663 this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
\r
25664 this.hideProxy();
\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
25676 afterRepair : function(){
\r
25677 if (Ext.enableFx && this.tree.hlDrop) {
\r
25678 Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
\r
25680 this.dragging = false;
\r
25685 Ext.tree.TreeEditor = function(tree, fc, config){
\r
25687 var field = fc.events ? fc : new Ext.form.TextField(fc);
\r
25688 Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
\r
25690 this.tree = tree;
\r
25692 if(!tree.rendered){
\r
25693 tree.on('render', this.initEditor, this);
\r
25695 this.initEditor(tree);
\r
25699 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
\r
25701 alignment: "l-l",
\r
25707 cls: "x-small-editor x-tree-editor",
\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
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
25732 var w = Math.min(
\r
25734 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
\r
25735 this.setSize(w, '');
\r
25739 triggerEdit : function(node, defer){
\r
25740 this.completeEdit();
\r
25741 if(node.attributes.editable !== false){
\r
25743 this.editNode = node;
\r
25744 if(this.tree.autoScroll){
\r
25745 node.ui.getEl().scrollIntoView(this.tree.body);
\r
25747 this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
\r
25753 bindScroll : function(){
\r
25754 this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
\r
25758 beforeNodeClick : function(node, e){
\r
25759 clearTimeout(this.autoEditTimer);
\r
25760 if(this.tree.getSelectionModel().isSelected(node)){
\r
25762 return this.triggerEdit(node);
\r
25766 onNodeDblClick : function(node, e){
\r
25767 clearTimeout(this.autoEditTimer);
\r
25771 updateNode : function(ed, value){
\r
25772 this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
\r
25773 this.editNode.setText(value);
\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
25785 onSpecialKey : function(field, e){
\r
25786 var k = e.getKey();
\r
25789 this.cancelEdit();
\r
25790 }else if(k == e.ENTER && !e.hasModifier()){
\r
25792 this.completeEdit();
\r
25797 Ext.menu.Menu = function(config){
\r
25798 if(Ext.isArray(config)){
\r
25799 config = {items:config};
\r
25801 Ext.apply(this, config);
\r
25802 this.id = this.id || Ext.id();
\r
25821 Ext.menu.MenuMgr.register(this);
\r
25822 Ext.menu.Menu.superclass.constructor.call(this);
\r
25823 var mis = this.items;
\r
25826 this.items = new Ext.util.MixedCollection();
\r
25828 this.add.apply(this, mis);
\r
25832 Ext.extend(Ext.menu.Menu, Ext.util.Observable, {
\r
25838 shadow : "sides",
\r
25840 subMenuAlign : "tl-tr?",
\r
25842 defaultAlign : "tl-bl?",
\r
25844 allowOtherMenus : false,
\r
25846 ignoreParentClicks : false,
\r
25852 createEl : function(){
\r
25853 return new Ext.Layer({
\r
25855 shadow:this.shadow,
\r
25856 constrain: false,
\r
25857 parentEl: this.parentEl || document.body,
\r
25863 render : function(){
\r
25867 var el = this.el = this.createEl();
\r
25869 if(!this.keyNav){
\r
25870 this.keyNav = new Ext.menu.MenuNav(this);
\r
25873 el.addClass("x-menu-plain");
\r
25876 el.addClass(this.cls);
\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
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
25893 this.autoWidth();
\r
25897 autoWidth : function(){
\r
25898 var el = this.el, ul = this.ul;
\r
25902 var w = this.width;
\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
25913 delayAutoWidth : function(){
\r
25915 if(!this.awTask){
\r
25916 this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);
\r
25918 this.awTask.delay(20);
\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
25931 onClick : function(e){
\r
25933 if(t = this.findTargetItem(e)){
\r
25934 if(t.menu && this.ignoreParentClicks){
\r
25938 this.fireEvent("click", this, t, e);
\r
25944 setActiveItem : function(item, autoExpand){
\r
25945 if(item != this.activeItem){
\r
25946 if(this.activeItem){
\r
25947 this.activeItem.deactivate();
\r
25949 this.activeItem = item;
\r
25950 item.activate(autoExpand);
\r
25951 }else if(autoExpand){
\r
25952 item.expandMenu();
\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
25970 onMouseOver : function(e){
\r
25972 if(t = this.findTargetItem(e)){
\r
25973 if(t.canActivate && !t.disabled){
\r
25974 this.setActiveItem(t, true);
\r
25977 this.over = true;
\r
25978 this.fireEvent("mouseover", this, e, t);
\r
25982 onMouseOut : function(e){
\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
25990 this.over = false;
\r
25991 this.fireEvent("mouseout", this, e, t);
\r
25995 isVisible : function(){
\r
25996 return this.el && !this.hidden;
\r
26000 show : function(el, pos, parentMenu){
\r
26001 this.parentMenu = parentMenu;
\r
26005 this.fireEvent("beforeshow", this);
\r
26006 this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
\r
26010 showAt : function(xy, parentMenu, _e){
\r
26011 this.parentMenu = parentMenu;
\r
26015 if(_e !== false){
\r
26016 this.fireEvent("beforeshow", this);
\r
26017 xy = this.el.adjustForConstraints(xy);
\r
26019 this.el.setXY(xy);
\r
26021 this.hidden = false;
\r
26023 this.fireEvent("show", this);
\r
26028 focus : function(){
\r
26029 if(!this.hidden){
\r
26030 this.doFocus.defer(50, this);
\r
26034 doFocus : function(){
\r
26035 if(!this.hidden){
\r
26036 this.focusEl.focus();
\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
26049 this.hidden = true;
\r
26050 this.fireEvent("hide", this);
\r
26052 if(deep === true && this.parentMenu){
\r
26053 this.parentMenu.hide(true);
\r
26058 add : function(){
\r
26059 var a = arguments, l = a.length, item;
\r
26060 for(var i = 0; i < l; 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
26068 item = this.addText(el);
\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
26081 getEl : function(){
\r
26089 addSeparator : function(){
\r
26090 return this.addItem(new Ext.menu.Separator());
\r
26094 addElement : function(el){
\r
26095 return this.addItem(new Ext.menu.BaseItem(el));
\r
26099 addItem : function(item){
\r
26100 this.items.add(item);
\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
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
26117 config = new Ext.menu.Item(config);
\r
26120 return this.addItem(config);
\r
26124 addText : function(text){
\r
26125 return this.addItem(new Ext.menu.TextItem(text));
\r
26129 insert : function(index, item){
\r
26130 this.items.insert(index, item);
\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
26142 remove : function(item){
\r
26143 this.items.removeKey(item.id);
\r
26148 removeAll : function(){
\r
26151 while(f = this.items.first()){
\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
26164 this.removeAll();
\r
26166 this.ul.removeAllListeners();
\r
26169 this.el.destroy();
\r
26174 beforeDestroy : Ext.emptyFn
\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
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
26191 return h.call(this.scope || this, e, this.menu);
\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
26200 down : function(e, m){
\r
26201 if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
\r
26202 m.tryActivate(0, 1);
\r
26206 right : function(e, m){
\r
26207 if(m.activeItem){
\r
26208 m.activeItem.expandMenu(true);
\r
26212 left : function(e, m){
\r
26214 if(m.parentMenu && m.parentMenu.activeItem){
\r
26215 m.parentMenu.activeItem.activate();
\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
26229 Ext.menu.MenuMgr = function(){
\r
26230 var menus, active, groups = {}, attached = false, lastShow = new Date();
\r
26232 // private - called when first menu is created
\r
26235 active = new Ext.util.MixedCollection();
\r
26236 Ext.getDoc().addKeyListener(27, function(){
\r
26237 if(active.length > 0){
\r
26244 function hideAll(){
\r
26245 if(active && active.length > 0){
\r
26246 var c = active.clone();
\r
26247 c.each(function(m){
\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
26263 function onShow(m){
\r
26264 var last = active.last();
\r
26265 lastShow = new Date();
\r
26268 Ext.getDoc().on("mousedown", onMouseDown);
\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
26280 function onBeforeHide(m){
\r
26281 if(m.activeChild){
\r
26282 m.activeChild.hide();
\r
26284 if(m.autoHideTimer){
\r
26285 clearTimeout(m.autoHideTimer);
\r
26286 delete m.autoHideTimer;
\r
26291 function onBeforeShow(m){
\r
26292 var pm = m.parentMenu;
\r
26293 if(!pm && !m.allowOtherMenus){
\r
26295 }else if(pm && pm.activeChild){
\r
26296 pm.activeChild.hide();
\r
26301 function onMouseDown(e){
\r
26302 if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
\r
26308 function onBeforeCheck(mi, state){
\r
26310 var g = groups[mi.group];
\r
26311 for(var i = 0, l = g.length; i < l; i++){
\r
26313 g[i].setChecked(false);
\r
26322 hideAll : function(){
\r
26327 register : function(menu){
\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
26341 groups[g].push(menu);
\r
26342 menu.on("checkchange", onCheck);
\r
26347 get : function(menu){
\r
26348 if(typeof menu == "string"){ // menu id
\r
26349 if(!menus){ // not initialized, no menus to return
\r
26352 return menus[menu];
\r
26353 }else if(menu.events){ // menu instance
\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
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
26377 registerCheckable : function(menuItem){
\r
26378 var g = menuItem.group;
\r
26383 groups[g].push(menuItem);
\r
26384 menuItem.on("beforecheckchange", onBeforeCheck);
\r
26389 unregisterCheckable : function(menuItem){
\r
26390 var g = menuItem.group;
\r
26392 groups[g].remove(menuItem);
\r
26393 menuItem.un("beforecheckchange", onBeforeCheck);
\r
26397 getCheckedItem : function(groupId){
\r
26398 var g = groups[groupId];
\r
26400 for(var i = 0, l = g.length; i < l; i++){
\r
26401 if(g[i].checked){
\r
26409 setCheckedItem : function(groupId, itemId){
\r
26410 var g = groups[groupId];
\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
26424 Ext.menu.BaseItem = function(config){
\r
26425 Ext.menu.BaseItem.superclass.constructor.call(this, config);
\r
26436 if(this.handler){
\r
26437 this.on("click", this.handler, this.scope);
\r
26441 Ext.extend(Ext.menu.BaseItem, Ext.Component, {
\r
26445 canActivate : false,
\r
26447 activeClass : "x-menu-item-active",
\r
26449 hideOnClick : true,
\r
26454 ctype: "Ext.menu.BaseItem",
\r
26457 actionMode : "container",
\r
26460 render : function(container, parentMenu){
\r
26462 this.parentMenu = parentMenu;
\r
26463 Ext.menu.BaseItem.superclass.render.call(this, container);
\r
26464 this.container.menuItemId = this.id;
\r
26468 onRender : function(container, position){
\r
26469 this.el = Ext.get(this.el);
\r
26471 this.el.id = this.id;
\r
26473 container.dom.appendChild(this.el.dom);
\r
26477 setHandler : function(handler, scope){
\r
26478 if(this.handler){
\r
26479 this.un("click", this.handler, this.scope);
\r
26481 this.on("click", this.handler = handler, this.scope = scope);
\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
26495 activate : function(){
\r
26496 if(this.disabled){
\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
26507 deactivate : function(){
\r
26508 this.container.removeClass(this.activeClass);
\r
26509 this.fireEvent("deactivate", this);
\r
26513 shouldDeactivate : function(e){
\r
26514 return !this.region || !this.region.contains(e.getPoint());
\r
26518 handleClick : function(e){
\r
26519 if(this.hideOnClick){
\r
26520 this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
\r
26525 expandMenu : function(autoActivate){
\r
26530 hideMenu : function(){
\r
26535 Ext.menu.TextItem = function(cfg){
\r
26536 if(typeof cfg == 'string'){
\r
26537 cfg = {text: cfg}
\r
26539 Ext.menu.TextItem.superclass.constructor.call(this, cfg);
\r
26542 Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {
\r
26545 hideOnClick : false,
\r
26547 itemCls : "x-menu-text",
\r
26550 onRender : function(){
\r
26551 var s = document.createElement("span");
\r
26552 s.className = this.itemCls;
\r
26553 s.innerHTML = this.text;
\r
26555 Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
\r
26559 Ext.menu.Separator = function(config){
\r
26560 Ext.menu.Separator.superclass.constructor.call(this, config);
\r
26563 Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {
\r
26565 itemCls : "x-menu-sep",
\r
26567 hideOnClick : false,
\r
26570 onRender : function(li){
\r
26571 var s = document.createElement("span");
\r
26572 s.className = this.itemCls;
\r
26573 s.innerHTML = " ";
\r
26575 li.addClass("x-menu-sep-li");
\r
26576 Ext.menu.Separator.superclass.onRender.apply(this, arguments);
\r
26580 Ext.menu.Item = function(config){
\r
26581 Ext.menu.Item.superclass.constructor.call(this, config);
\r
26583 this.menu = Ext.menu.MenuMgr.get(this.menu);
\r
26586 Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
\r
26594 itemCls : "x-menu-item",
\r
26596 canActivate : true,
\r
26599 // doc'd in BaseItem
\r
26603 ctype: "Ext.menu.Item",
\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
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
26619 Ext.menu.Item.superclass.onRender.call(this, container, position);
\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
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
26643 beforeDestroy: function(){
\r
26645 this.menu.destroy();
\r
26647 Ext.menu.Item.superclass.beforeDestroy.call(this);
\r
26651 handleClick : function(e){
\r
26652 if(!this.href){ // if no link defined, stop the event automatically
\r
26655 Ext.menu.Item.superclass.handleClick.apply(this, arguments);
\r
26659 activate : function(autoExpand){
\r
26660 if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
\r
26663 this.expandMenu();
\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
26681 deactivate : function(){
\r
26682 Ext.menu.Item.superclass.deactivate.apply(this, arguments);
\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
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
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
26718 deferHide : function(){
\r
26719 delete this.hideTimer;
\r
26720 if(this.menu.over){
\r
26721 this.parentMenu.setActiveItem(this, false);
\r
26723 this.menu.hide();
\r
26728 Ext.menu.CheckItem = function(config){
\r
26729 Ext.menu.CheckItem.superclass.constructor.call(this, config);
\r
26732 "beforecheckchange" ,
\r
26737 if(this.checkHandler){
\r
26738 this.on('checkchange', this.checkHandler, this.scope);
\r
26740 Ext.menu.MenuMgr.registerCheckable(this);
\r
26742 Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
\r
26745 itemCls : "x-menu-item x-menu-check-item",
\r
26747 groupClass : "x-menu-group-item",
\r
26753 ctype: "Ext.menu.CheckItem",
\r
26756 onRender : function(c){
\r
26757 Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
\r
26759 this.el.addClass(this.groupClass);
\r
26761 if(this.checked){
\r
26762 this.checked = false;
\r
26763 this.setChecked(true, true);
\r
26768 destroy : function(){
\r
26769 Ext.menu.MenuMgr.unregisterCheckable(this);
\r
26770 Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
\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
26779 this.checked = state;
\r
26780 if(suppressEvent !== true){
\r
26781 this.fireEvent("checkchange", this, state);
\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
26791 Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
\r
26795 Ext.menu.Adapter = function(component, config){
\r
26796 Ext.menu.Adapter.superclass.constructor.call(this, config);
\r
26797 this.component = component;
\r
26799 Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {
\r
26801 canActivate : true,
\r
26804 onRender : function(container, position){
\r
26805 this.component.render(container);
\r
26806 this.el = this.component.getEl();
\r
26810 activate : function(){
\r
26811 if(this.disabled){
\r
26814 this.component.focus();
\r
26815 this.fireEvent("activate", this);
\r
26820 deactivate : function(){
\r
26821 this.fireEvent("deactivate", this);
\r
26825 disable : function(){
\r
26826 this.component.disable();
\r
26827 Ext.menu.Adapter.superclass.disable.call(this);
\r
26831 enable : function(){
\r
26832 this.component.enable();
\r
26833 Ext.menu.Adapter.superclass.enable.call(this);
\r
26837 Ext.menu.DateItem = function(config){
\r
26838 Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);
\r
26840 this.picker = this.component;
\r
26841 this.addEvents('select');
\r
26843 this.picker.on("render", function(picker){
\r
26844 picker.getEl().swallowEvent("click");
\r
26845 picker.container.addClass("x-menu-date-item");
\r
26848 this.picker.on("select", this.onSelect, this);
\r
26851 Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {
\r
26853 onSelect : function(picker, date){
\r
26854 this.fireEvent("select", this, date, picker);
\r
26855 Ext.menu.DateItem.superclass.handleClick.call(this);
\r
26859 Ext.menu.ColorItem = function(config){
\r
26860 Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);
\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
26868 Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);
\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
26876 this.picker = di.picker;
\r
26878 this.relayEvents(di, ["select"]);
\r
26880 this.on('beforeshow', function(){
\r
26882 this.picker.hideMonthPicker(true);
\r
26886 Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {
\r
26887 cls:'x-date-menu',
\r
26890 beforeDestroy : function() {
\r
26891 this.picker.destroy();
\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
26901 this.palette = ci.palette;
\r
26903 this.relayEvents(ci, ["select"]);
\r
26905 Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu, {
\r
26907 beforeDestroy: function(){
\r
26908 this.palette.destroy();
\r
26912 Ext.form.Field = Ext.extend(Ext.BoxComponent, {
\r
26926 invalidClass : "x-form-invalid",
\r
26928 invalidText : "The value in this field is invalid",
\r
26930 focusClass : "x-form-focus",
\r
26932 validationEvent : "keyup",
\r
26934 validateOnBlur : true,
\r
26936 validationDelay : 250,
\r
26938 defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
\r
26940 fieldClass : "x-form-field",
\r
26942 msgTarget : 'qtip',
\r
26944 msgFx : 'normal',
\r
26946 readOnly : false,
\r
26948 disabled : false,
\r
26951 isFormField : true,
\r
26954 hasFocus : false,
\r
26957 initComponent : function(){
\r
26958 Ext.form.Field.superclass.initComponent.call(this);
\r
26976 getName: function(){
\r
26977 return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');
\r
26981 onRender : function(ct, position){
\r
26982 Ext.form.Field.superclass.onRender.call(this, ct, position);
\r
26984 var cfg = this.getAutoCreate();
\r
26986 cfg.name = this.name || this.id;
\r
26988 if(this.inputType){
\r
26989 cfg.type = this.inputType;
\r
26991 this.el = ct.createChild(cfg, position);
\r
26993 var type = this.el.dom.type;
\r
26995 if(type == 'password'){
\r
26998 this.el.addClass('x-form-'+type);
\r
27000 if(this.readOnly){
\r
27001 this.el.dom.readOnly = true;
\r
27003 if(this.tabIndex !== undefined){
\r
27004 this.el.dom.setAttribute('tabIndex', this.tabIndex);
\r
27007 this.el.addClass([this.fieldClass, this.cls]);
\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
27017 // reference to original value for reset
\r
27018 this.originalValue = this.getValue();
\r
27022 isDirty : function() {
\r
27023 if(this.disabled) {
\r
27026 return String(this.getValue()) !== String(this.originalValue);
\r
27030 afterRender : function(){
\r
27031 Ext.form.Field.superclass.afterRender.call(this);
\r
27032 this.initEvents();
\r
27033 this.initValue();
\r
27037 fireKey : function(e){
\r
27038 if(e.isSpecialKey()){
\r
27039 this.fireEvent("specialkey", this, e);
\r
27044 reset : function(){
\r
27045 this.setValue(this.originalValue);
\r
27046 this.clearInvalid();
\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
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
27060 onFocus : function(){
\r
27061 if(this.focusClass){
\r
27062 this.el.addClass(this.focusClass);
\r
27064 if(!this.hasFocus){
\r
27065 this.hasFocus = true;
\r
27066 this.startValue = this.getValue();
\r
27067 this.fireEvent("focus", this);
\r
27072 beforeBlur : Ext.emptyFn,
\r
27075 onBlur : function(){
\r
27076 this.beforeBlur();
\r
27077 if(this.focusClass){
\r
27078 this.el.removeClass(this.focusClass);
\r
27080 this.hasFocus = false;
\r
27081 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
\r
27084 var v = this.getValue();
\r
27085 if(String(v) !== String(this.startValue)){
\r
27086 this.fireEvent('change', this, v, this.startValue);
\r
27088 this.fireEvent("blur", this);
\r
27092 isValid : function(preventMark){
\r
27093 if(this.disabled){
\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
27104 validate : function(){
\r
27105 if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
\r
27106 this.clearInvalid();
\r
27112 // protected - should be overridden by subclasses if necessary to prepare raw values for validation
\r
27113 processValue : function(value){
\r
27118 // Subclasses should provide the validation implementation by overriding this
\r
27119 validateValue : function(value){
\r
27124 markInvalid : function(msg){
\r
27125 if(!this.rendered || this.preventMark){ // not rendered
\r
27128 this.el.addClass(this.invalidClass);
\r
27129 msg = msg || this.invalidText;
\r
27131 switch(this.msgTarget){
\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
27140 this.el.dom.title = msg;
\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
27149 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
\r
27150 this.errorEl.setWidth(elp.getWidth(true)-20);
\r
27152 this.errorEl.update(msg);
\r
27153 Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
\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
27162 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
\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
27171 var t = Ext.getDom(this.msgTarget);
\r
27172 t.innerHTML = msg;
\r
27173 t.style.display = this.msgDisplay;
\r
27176 this.fireEvent('invalid', this, msg);
\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
27186 alignErrorIcon : function(){
\r
27187 this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
\r
27191 clearInvalid : function(){
\r
27192 if(!this.rendered || this.preventMark){ // not rendered
\r
27195 this.el.removeClass(this.invalidClass);
\r
27196 switch(this.msgTarget){
\r
27198 this.el.dom.qtip = '';
\r
27201 this.el.dom.title = '';
\r
27204 if(this.errorEl){
\r
27205 Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
\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
27216 var t = Ext.getDom(this.msgTarget);
\r
27217 t.innerHTML = '';
\r
27218 t.style.display = 'none';
\r
27221 this.fireEvent('valid', this);
\r
27225 getRawValue : function(){
\r
27226 var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
\r
27227 if(v === this.emptyText){
\r
27234 getValue : function(){
\r
27235 if(!this.rendered) {
\r
27236 return this.value;
\r
27238 var v = this.el.getValue();
\r
27239 if(v === this.emptyText || v === undefined){
\r
27246 setRawValue : function(v){
\r
27247 return this.el.dom.value = (v === null || v === undefined ? '' : v);
\r
27251 setValue : function(v){
\r
27253 if(this.rendered){
\r
27254 this.el.dom.value = (v === null || v === undefined ? '' : v);
\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
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
27274 if(tag == 'input' && Ext.isStrict){
\r
27275 return w - (Ext.isIE6 ? 4 : 1);
\r
27277 if(tag == 'textarea' && Ext.isStrict){
\r
27280 }else if(Ext.isOpera && Ext.isStrict){
\r
27281 if(tag == 'input'){
\r
27284 if(tag == 'textarea'){
\r
27298 Ext.form.MessageTargets = {
\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
27307 clear: function(f){
\r
27308 this.el.dom.qtip = '';
\r
27312 mark: function(f){
\r
27313 this.el.dom.title = msg;
\r
27315 clear: function(f){
\r
27316 this.el.dom.title = '';
\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
27327 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
\r
27328 this.errorEl.setWidth(elp.getWidth(true)-20);
\r
27330 this.errorEl.update(msg);
\r
27331 Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
\r
27333 clear: function(f){
\r
27334 if(this.errorEl){
\r
27335 Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
\r
27337 this.el.dom.title = '';
\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
27349 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
\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
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
27363 this.el.dom.title = '';
\r
27368 mark: function(f){
\r
27371 clear: function(f){
\r
27378 // anything other than normal should be considered experimental
\r
27379 Ext.form.Field.msgFx = {
\r
27381 show: function(msgEl, f){
\r
27382 msgEl.setDisplayed('block');
\r
27385 hide : function(msgEl, f){
\r
27386 msgEl.setDisplayed(false).update('');
\r
27391 show: function(msgEl, f){
\r
27392 msgEl.slideIn('t', {stopFx:true});
\r
27395 hide : function(msgEl, f){
\r
27396 msgEl.slideOut('t', {stopFx:true,useDisplay:true});
\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
27407 hide : function(msgEl, f){
\r
27408 msgEl.slideOut('l', {stopFx:true,useDisplay:true});
\r
27412 Ext.reg('field', Ext.form.Field);
\r
27415 Ext.form.TextField = Ext.extend(Ext.form.Field, {
\r
27429 disableKeyFilter : false,
\r
27431 allowBlank : true,
\r
27435 maxLength : Number.MAX_VALUE,
\r
27437 minLengthText : "The minimum length for this field is {0}",
\r
27439 maxLengthText : "The maximum length for this field is {0}",
\r
27441 selectOnFocus : false,
\r
27443 blankText : "This field is required",
\r
27445 validator : null,
\r
27451 emptyText : null,
\r
27453 emptyClass : 'x-form-empty-field',
\r
27457 initComponent : function(){
\r
27458 Ext.form.TextField.superclass.initComponent.call(this);
\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
27479 else if(this.validationEvent !== false){
\r
27480 this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
\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
27491 if(this.emptyText){
\r
27492 this.on('blur', this.postBlur, this);
\r
27493 this.applyEmptyText();
\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
27500 this.el.on("keyup", this.onKeyUpBuffered, this, {buffer:50});
\r
27501 this.el.on("click", this.autoSize, this);
\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
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
27522 filterValidation : function(e){
\r
27523 if(!e.isNavKeyPress()){
\r
27524 this.validationTask.delay(this.validationDelay);
\r
27529 onDisable: function(){
\r
27530 Ext.form.TextField.superclass.onDisable.call(this);
\r
27532 this.el.dom.unselectable = 'on';
\r
27537 onEnable: function(){
\r
27538 Ext.form.TextField.superclass.onEnable.call(this);
\r
27540 this.el.dom.unselectable = '';
\r
27545 onKeyUpBuffered : function(e){
\r
27546 if(!e.isNavKeyPress()){
\r
27552 onKeyUp : function(e){
\r
27553 this.fireEvent('keyup', this, e);
\r
27557 onKeyDown : function(e){
\r
27558 this.fireEvent('keydown', this, e);
\r
27562 onKeyPress : function(e){
\r
27563 this.fireEvent('keypress', this, e);
\r
27567 reset : function(){
\r
27568 Ext.form.TextField.superclass.reset.call(this);
\r
27569 this.applyEmptyText();
\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
27580 preFocus : function(){
\r
27581 if(this.emptyText){
\r
27582 if(this.el.dom.value == this.emptyText){
\r
27583 this.setRawValue('');
\r
27585 this.el.removeClass(this.emptyClass);
\r
27587 if(this.selectOnFocus){
\r
27588 this.el.dom.select();
\r
27593 postBlur : function(){
\r
27594 this.applyEmptyText();
\r
27598 filterKeys : function(e){
\r
27602 var k = e.getKey();
\r
27603 if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
\r
27606 var c = e.getCharCode(), cc = String.fromCharCode(c);
\r
27607 if(!Ext.isGecko && e.isSpecialKey() && !cc){
\r
27610 if(!this.maskRe.test(cc)){
\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
27619 Ext.form.TextField.superclass.setValue.apply(this, arguments);
\r
27620 this.applyEmptyText();
\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
27631 this.markInvalid(this.blankText);
\r
27635 if(value.length < this.minLength){
\r
27636 this.markInvalid(String.format(this.minLengthText, this.minLength));
\r
27639 if(value.length > this.maxLength){
\r
27640 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
\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
27650 if(typeof this.validator == "function"){
\r
27651 var msg = this.validator(value);
\r
27652 if(msg !== true){
\r
27653 this.markInvalid(msg);
\r
27657 if(this.regex && !this.regex.test(value)){
\r
27658 this.markInvalid(this.regexText);
\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
27680 doFocus = Ext.isGecko || Ext.isOpera;
\r
27690 autoSize : function(){
\r
27691 if(!this.grow || !this.rendered){
\r
27694 if(!this.metrics){
\r
27695 this.metrics = Ext.util.TextMetrics.createInstance(this.el);
\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
27702 Ext.removeNode(d);
\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
27710 Ext.reg('textfield', Ext.form.TextField);
\r
27713 Ext.form.TriggerField = Ext.extend(Ext.form.TextField, {
\r
27716 defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
\r
27718 hideTrigger:false,
\r
27721 autoSize: Ext.emptyFn,
\r
27723 monitorTab : true,
\r
27725 deferHeight : true,
\r
27727 mimicing : false,
\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
27735 this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
\r
27739 adjustSize : Ext.BoxComponent.prototype.adjustSize,
\r
27742 getResizeEl : function(){
\r
27743 return this.wrap;
\r
27747 getPositionEl : function(){
\r
27748 return this.wrap;
\r
27752 alignErrorIcon : function(){
\r
27754 this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
\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
27767 this.initTrigger();
\r
27769 this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
\r
27773 afterRender : function(){
\r
27774 Ext.form.TriggerField.superclass.afterRender.call(this);
\r
27776 if(Ext.isIE && !this.hideTrigger && this.el.getY() != (y = this.trigger.getY())){
\r
27777 this.el.position();
\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
27790 onDestroy : function(){
\r
27791 if(this.trigger){
\r
27792 this.trigger.removeAllListeners();
\r
27793 this.trigger.remove();
\r
27796 this.wrap.remove();
\r
27798 Ext.form.TriggerField.superclass.onDestroy.call(this);
\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
27815 checkTab : function(e){
\r
27816 if(e.getKey() == e.TAB){
\r
27817 this.triggerBlur();
\r
27822 onBlur : function(){
\r
27827 mimicBlur : function(e){
\r
27828 if(!this.wrap.contains(e.target) && this.validateBlur(e)){
\r
27829 this.triggerBlur();
\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
27840 this.beforeBlur();
\r
27842 this.wrap.removeClass('x-trigger-wrap-focus');
\r
27844 Ext.form.TriggerField.superclass.onBlur.call(this);
\r
27847 beforeBlur : Ext.emptyFn,
\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
27856 onDisable : function(){
\r
27857 Ext.form.TriggerField.superclass.onDisable.call(this);
\r
27859 this.wrap.addClass(this.disabledClass);
\r
27860 this.el.removeClass(this.disabledClass);
\r
27865 onEnable : function(){
\r
27866 Ext.form.TriggerField.superclass.onEnable.call(this);
\r
27868 this.wrap.removeClass(this.disabledClass);
\r
27873 onShow : function(){
\r
27875 this.wrap.dom.style.display = '';
\r
27876 this.wrap.dom.style.visibility = 'visible';
\r
27881 onHide : function(){
\r
27882 this.wrap.dom.style.display = 'none';
\r
27886 onTriggerClick : Ext.emptyFn
\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
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
27907 getTrigger : function(index){
\r
27908 return this.triggers[index];
\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
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
27926 var triggerIndex = 'Trigger'+(index+1);
\r
27928 if(this['hide'+triggerIndex]){
\r
27929 t.dom.style.display = 'none';
\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
27935 this.triggers = ts.elements;
\r
27938 onTrigger1Click : Ext.emptyFn,
\r
27939 onTrigger2Click : Ext.emptyFn
\r
27941 Ext.reg('trigger', Ext.form.TriggerField);
\r
27943 Ext.form.TextArea = Ext.extend(Ext.form.TextField, {
\r
27948 growAppend : ' \n ',
\r
27951 enterIsSpecial : false,
\r
27954 preventScrollbars: false,
\r
27958 onRender : function(ct, position){
\r
27960 this.defaultAutoCreate = {
\r
27962 style:"width:100px;height:60px;",
\r
27963 autocomplete: "off"
\r
27966 Ext.form.TextArea.superclass.onRender.call(this, ct, position);
\r
27968 this.textSizeEl = Ext.DomHelper.append(document.body, {
\r
27969 tag: "pre", cls: "x-form-grow-sizer"
\r
27971 if(this.preventScrollbars){
\r
27972 this.el.setStyle("overflow", "hidden");
\r
27974 this.el.setHeight(this.growMin);
\r
27978 onDestroy : function(){
\r
27979 if(this.textSizeEl){
\r
27980 Ext.removeNode(this.textSizeEl);
\r
27982 Ext.form.TextArea.superclass.onDestroy.call(this);
\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
27992 onKeyUp : function(e){
\r
27993 if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
\r
27996 Ext.form.TextArea.superclass.onKeyUp.call(this, e);
\r
28000 autoSize : function(){
\r
28001 if(!this.grow || !this.textSizeEl){
\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
28011 Ext.fly(ts).setWidth(this.el.getWidth());
\r
28012 if(v.length < 1){
\r
28013 v = "  ";
\r
28016 v = v.replace(/\n/g, '<p> </p>');
\r
28018 v += this.growAppend;
\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
28029 Ext.reg('textarea', Ext.form.TextArea);
\r
28031 Ext.form.NumberField = Ext.extend(Ext.form.TextField, {
\r
28034 fieldClass: "x-form-field x-form-num-field",
\r
28036 allowDecimals : true,
\r
28038 decimalSeparator : ".",
\r
28040 decimalPrecision : 2,
\r
28042 allowNegative : true,
\r
28044 minValue : Number.NEGATIVE_INFINITY,
\r
28046 maxValue : Number.MAX_VALUE,
\r
28048 minText : "The minimum value for this field is {0}",
\r
28050 maxText : "The maximum value for this field is {0}",
\r
28052 nanText : "{0} is not a valid number",
\r
28054 baseChars : "0123456789",
\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
28063 if(this.allowNegative){
\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
28072 var c = e.getCharCode();
\r
28073 if(allowed.indexOf(String.fromCharCode(c)) === -1){
\r
28077 this.el.on("keypress", keyPress, this);
\r
28081 validateValue : function(value){
\r
28082 if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){
\r
28085 if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
\r
28088 value = String(value).replace(this.decimalSeparator, ".");
\r
28089 if(isNaN(value)){
\r
28090 this.markInvalid(String.format(this.nanText, value));
\r
28093 var num = this.parseValue(value);
\r
28094 if(num < this.minValue){
\r
28095 this.markInvalid(String.format(this.minText, this.minValue));
\r
28098 if(num > this.maxValue){
\r
28099 this.markInvalid(String.format(this.maxText, this.maxValue));
\r
28105 getValue : function(){
\r
28106 return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
\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
28116 parseValue : function(value){
\r
28117 value = parseFloat(String(value).replace(this.decimalSeparator, "."));
\r
28118 return isNaN(value) ? '' : value;
\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
28127 return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
\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
28137 Ext.reg('numberfield', Ext.form.NumberField);
\r
28139 Ext.form.DateField = Ext.extend(Ext.form.TriggerField, {
\r
28141 format : "m/d/Y",
\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
28145 disabledDaysText : "Disabled",
\r
28147 disabledDatesText : "Disabled",
\r
28149 minText : "The date in this field must be equal to or after {0}",
\r
28151 maxText : "The date in this field must be equal to or before {0}",
\r
28153 invalidText : "{0} is not a valid date - it must be in the format {1}",
\r
28155 triggerClass : 'x-form-date-trigger',
\r
28157 showToday : true,
\r
28165 defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
\r
28167 initComponent : function(){
\r
28168 Ext.form.DateField.superclass.initComponent.call(this);
\r
28175 if(typeof this.minValue == "string"){
\r
28176 this.minValue = this.parseDate(this.minValue);
\r
28178 if(typeof this.maxValue == "string"){
\r
28179 this.maxValue = this.parseDate(this.maxValue);
\r
28181 this.disabledDatesRE = null;
\r
28182 this.initDisabledDays();
\r
28186 initDisabledDays : function(){
\r
28187 if(this.disabledDates){
\r
28188 var dd = this.disabledDates;
\r
28190 for(var i = 0; i < dd.length; i++){
\r
28192 if(i != dd.length-1) re += "|";
\r
28194 this.disabledDatesRE = new RegExp(re + ")");
\r
28199 setDisabledDates : function(dd){
\r
28200 this.disabledDates = dd;
\r
28201 this.initDisabledDays();
\r
28203 this.menu.picker.setDisabledDates(this.disabledDatesRE);
\r
28208 setDisabledDays : function(dd){
\r
28209 this.disabledDays = dd;
\r
28211 this.menu.picker.setDisabledDays(dd);
\r
28216 setMinValue : function(dt){
\r
28217 this.minValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
\r
28219 this.menu.picker.setMinDate(this.minValue);
\r
28224 setMaxValue : function(dt){
\r
28225 this.maxValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
\r
28227 this.menu.picker.setMaxDate(this.maxValue);
\r
28232 validateValue : function(value){
\r
28233 value = this.formatDate(value);
\r
28234 if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
\r
28237 if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
\r
28240 var svalue = value;
\r
28241 value = this.parseDate(value);
\r
28243 this.markInvalid(String.format(this.invalidText, svalue, this.format));
\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
28251 if(this.maxValue && time > this.maxValue.getTime()){
\r
28252 this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
\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
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
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
28279 getValue : function(){
\r
28280 return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
\r
28284 setValue : function(date){
\r
28285 Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
\r
28289 parseDate : function(value){
\r
28290 if(!value || Ext.isDate(value)){
\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
28298 for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
\r
28299 v = Date.parseDate(value, this.altFormatsArray[i]);
\r
28306 onDestroy : function(){
\r
28308 this.menu.destroy();
\r
28311 this.wrap.remove();
\r
28313 Ext.form.DateField.superclass.onDestroy.call(this);
\r
28317 formatDate : function(date){
\r
28318 return Ext.isDate(date) ? date.dateFormat(this.format) : date;
\r
28322 menuListeners : {
\r
28323 select: function(m, d){
\r
28324 this.setValue(d);
\r
28325 this.fireEvent('select', this, d);
\r
28327 show : function(){ // retain focus styling
\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
28341 // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker
\r
28342 onTriggerClick : function(){
\r
28343 if(this.disabled){
\r
28346 if(this.menu == null){
\r
28347 this.menu = new Ext.menu.DateMenu();
\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
28361 this.menu.on(Ext.apply({}, this.menuListeners, {
\r
28364 this.menu.picker.setValue(this.getValue() || new Date());
\r
28365 this.menu.show(this.el, "tl-bl?");
\r
28369 beforeBlur : function(){
\r
28370 var v = this.parseDate(this.getRawValue());
\r
28372 this.setValue(v);
\r
28381 Ext.reg('datefield', Ext.form.DateField);
\r
28383 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
\r
28391 defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
\r
28400 selectedClass: 'x-combo-selected',
\r
28402 triggerClass : 'x-form-arrow-trigger',
\r
28406 listAlign: 'tl-bl?',
\r
28412 triggerAction: 'query',
\r
28416 typeAhead: false,
\r
28422 selectOnFocus:false,
\r
28424 queryParam: 'query',
\r
28426 loadingText: 'Loading...',
\r
28428 resizable: false,
\r
28430 handleHeight : 8,
\r
28438 minListWidth : 70,
\r
28440 forceSelection:false,
\r
28442 typeAheadDelay : 250,
\r
28451 initComponent : function(){
\r
28452 Ext.form.ComboBox.superclass.initComponent.call(this);
\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
28472 this.mode = 'local';
\r
28473 var d = [], opts = s.options;
\r
28474 for(var i = 0, len = opts.length;i < len; i++){
\r
28476 var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
\r
28478 this.value = value;
\r
28480 d.push([value, o.text]);
\r
28482 this.store = new Ext.data.SimpleStore({
\r
28484 fields: ['value', 'text'],
\r
28487 this.valueField = 'value';
\r
28488 this.displayField = 'text';
\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
28497 Ext.removeNode(s); // remove it
\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
28507 this.valueField = 'value';
\r
28509 this.store = new Ext.data.SimpleStore({
\r
28510 fields: ['text'],
\r
28511 data: this.store,
\r
28514 this.valueField = 'text';
\r
28516 this.displayField = 'text';
\r
28517 this.mode = 'local';
\r
28520 this.selectedIndex = -1;
\r
28521 if(this.mode == 'local'){
\r
28522 if(this.initialConfig.queryDelay === undefined){
\r
28523 this.queryDelay = 10;
\r
28525 if(this.initialConfig.minChars === undefined){
\r
28526 this.minChars = 0;
\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
28538 // prevent input submission
\r
28539 this.el.dom.removeAttribute('name');
\r
28542 this.el.dom.setAttribute('autocomplete', 'off');
\r
28545 if(!this.lazyInit){
\r
28548 this.on('focus', this.initList, this, {single: true});
\r
28551 if(!this.editable){
\r
28552 this.editable = true;
\r
28553 this.setEditable(false);
\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
28568 initList : function(){
\r
28570 var cls = 'x-combo-list';
\r
28572 this.list = new Ext.Layer({
\r
28573 shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
\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
28582 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
\r
28583 this.assetHeight += this.header.getHeight();
\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
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
28598 this.assetHeight += this.footer.getHeight();
\r
28603 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
\r
28608 this.view = new Ext.DataView({
\r
28609 applyTo: this.innerList,
\r
28611 singleSelect: true,
\r
28612 selectedClass: this.selectedClass,
\r
28613 itemSelector: this.itemSelector || '.' + cls + '-item'
\r
28616 this.view.on('click', this.onViewClick, this);
\r
28618 this.bindStore(this.store, true);
\r
28620 if(this.resizable){
\r
28621 this.resizer = new Ext.Resizable(this.list, {
\r
28622 pinned:true, handles:'se'
\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
28630 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
\r
28636 getStore : function(){
\r
28637 return this.store;
\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
28647 this.store = null;
\r
28649 this.view.setStore(null);
\r
28654 this.store = Ext.StoreMgr.lookup(store);
\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
28661 this.view.setStore(store);
\r
28667 initEvents : function(){
\r
28668 Ext.form.ComboBox.superclass.initEvents.call(this);
\r
28670 this.keyNav = new Ext.KeyNav(this.el, {
\r
28671 "up" : function(e){
\r
28672 this.inKeyMode = true;
\r
28673 this.selectPrev();
\r
28676 "down" : function(e){
\r
28677 if(!this.isExpanded()){
\r
28678 this.onTriggerClick();
\r
28680 this.inKeyMode = true;
\r
28681 this.selectNext();
\r
28685 "enter" : function(e){
\r
28686 this.onViewClick();
\r
28687 this.delayedCheck = true;
\r
28688 this.unsetDelayCheck.defer(10, this);
\r
28691 "esc" : function(e){
\r
28695 "tab" : function(e){
\r
28696 this.onViewClick(false);
\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
28709 forceKeyDown : true
\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
28717 if(this.editable !== false){
\r
28718 this.el.on("keyup", this.onKeyUp, this);
\r
28720 if(this.forceSelection){
\r
28721 this.on('blur', this.doForce, this);
\r
28726 onDestroy : function(){
\r
28728 Ext.destroy(this.view);
\r
28731 if(this.innerList){
\r
28732 this.innerList.un('mouseover', this.onViewOver, this);
\r
28733 this.innerList.un('mousemove', this.onViewMove, this);
\r
28735 this.list.destroy();
\r
28737 if (this.dqTask){
\r
28738 this.dqTask.cancel();
\r
28739 this.dqTask = null;
\r
28741 this.bindStore(null);
\r
28742 Ext.form.ComboBox.superclass.onDestroy.call(this);
\r
28746 unsetDelayCheck : function(){
\r
28747 delete this.delayedCheck;
\r
28751 fireKey : function(e){
\r
28752 if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){
\r
28753 this.fireEvent("specialkey", this, e);
\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
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
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
28784 setEditable : function(value){
\r
28785 if(value == this.editable){
\r
28788 this.editable = 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
28794 this.el.dom.removeAttribute('readOnly');
\r
28795 this.el.un('mousedown', this.onTriggerClick, this);
\r
28796 this.el.removeClass('x-combo-noedit');
\r
28801 onBeforeLoad : function(){
\r
28802 if(!this.hasFocus){
\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
28812 onLoad : function(){
\r
28813 if(!this.hasFocus){
\r
28816 if(this.store.getCount() > 0){
\r
28818 this.restrictHeight();
\r
28819 if(this.lastQuery == this.allQuery){
\r
28820 if(this.editable){
\r
28821 this.el.dom.select();
\r
28823 if(!this.selectByValue(this.value, true)){
\r
28824 this.select(0, true);
\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
28833 this.onEmptyResults();
\r
28835 //this.el.focus();
\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
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
28857 this.fireEvent('select', this, record, index);
\r
28862 getValue : function(){
\r
28863 if(this.valueField){
\r
28864 return typeof this.value != 'undefined' ? this.value : '';
\r
28866 return Ext.form.ComboBox.superclass.getValue.call(this);
\r
28871 clearValue : function(){
\r
28872 if(this.hiddenField){
\r
28873 this.hiddenField.value = '';
\r
28875 this.setRawValue('');
\r
28876 this.lastSelectionText = '';
\r
28877 this.applyEmptyText();
\r
28882 setValue : function(v){
\r
28884 if(this.valueField){
\r
28885 var r = this.findRecord(this.valueField, v);
\r
28887 text = r.data[this.displayField];
\r
28888 }else if(this.valueNotFoundText !== undefined){
\r
28889 text = this.valueNotFoundText;
\r
28892 this.lastSelectionText = text;
\r
28893 if(this.hiddenField){
\r
28894 this.hiddenField.value = v;
\r
28896 Ext.form.ComboBox.superclass.setValue.call(this, text);
\r
28901 findRecord : function(prop, value){
\r
28903 if(this.store.getCount() > 0){
\r
28904 this.store.each(function(r){
\r
28905 if(r.data[prop] == value){
\r
28915 onViewMove : function(e, t){
\r
28916 this.inKeyMode = false;
\r
28920 onViewOver : function(e, t){
\r
28921 if(this.inKeyMode){ // prevent key nav and mouse over conflicts
\r
28924 var item = this.view.findItemFromChild(t);
\r
28926 var index = this.view.indexOf(item);
\r
28927 this.select(index, false);
\r
28932 onViewClick : function(doFocus){
\r
28933 var index = this.view.getSelectedIndexes()[0];
\r
28934 var r = this.store.getAt(index);
\r
28936 this.onSelect(r, index);
\r
28938 if(doFocus !== false){
\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
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
28962 onEmptyResults : function(){
\r
28967 isExpanded : function(){
\r
28968 return this.list && this.list.isVisible();
\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
28976 this.select(this.store.indexOf(r), scrollIntoView);
\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
28990 this.innerList.scrollChildIntoView(el, false);
\r
28996 selectNext : function(){
\r
28997 var ct = this.store.getCount();
\r
28999 if(this.selectedIndex == -1){
\r
29001 }else if(this.selectedIndex < ct-1){
\r
29002 this.select(this.selectedIndex+1);
\r
29008 selectPrev : function(){
\r
29009 var ct = this.store.getCount();
\r
29011 if(this.selectedIndex == -1){
\r
29013 }else if(this.selectedIndex != 0){
\r
29014 this.select(this.selectedIndex-1);
\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
29028 validateBlur : function(){
\r
29029 return !this.list || !this.list.isVisible();
\r
29033 initQuery : function(){
\r
29034 this.doQuery(this.getRawValue());
\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
29047 doQuery : function(q, forceAll){
\r
29048 if(q === undefined || q === null){
\r
29053 forceAll: forceAll,
\r
29057 if(this.fireEvent('beforequery', qe)===false || qe.cancel){
\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
29068 this.store.clearFilter();
\r
29070 this.store.filter(this.displayField, q);
\r
29074 this.store.baseParams[this.queryParam] = q;
\r
29075 this.store.load({
\r
29076 params: this.getParams(q)
\r
29081 this.selectedIndex = -1;
\r
29088 getParams : function(q){
\r
29090 //p[this.queryParam] = q;
\r
29091 if(this.pageSize){
\r
29093 p.limit = this.pageSize;
\r
29099 collapse : function(){
\r
29100 if(!this.isExpanded()){
\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
29110 collapseIf : function(e){
\r
29111 if(!e.within(this.wrap) && !e.within(this.list)){
\r
29117 expand : function(){
\r
29118 if(this.isExpanded() || !this.hasFocus){
\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
29131 // Implements the default empty TriggerField.onTriggerClick function
\r
29132 onTriggerClick : function(){
\r
29133 if(this.disabled){
\r
29136 if(this.isExpanded()){
\r
29140 this.onFocus({});
\r
29141 if(this.triggerAction == 'all') {
\r
29142 this.doQuery(this.allQuery, true);
\r
29144 this.doQuery(this.getRawValue());
\r
29156 Ext.reg('combo', Ext.form.ComboBox);
\r
29158 Ext.form.Checkbox = Ext.extend(Ext.form.Field, {
\r
29160 checkedCls: 'x-form-check-checked',
\r
29162 focusCls: 'x-form-check-focus',
\r
29164 overCls: 'x-form-check-over',
\r
29166 mouseDownCls: 'x-form-check-down',
\r
29172 defaultAutoCreate: {tag: 'input', type: 'checkbox', autocomplete: 'off'},
\r
29180 baseCls: 'x-form-check',
\r
29183 initComponent : function(){
\r
29184 Ext.form.Checkbox.superclass.initComponent.call(this);
\r
29192 initEvents : function(){
\r
29193 Ext.form.Checkbox.superclass.initEvents.call(this);
\r
29194 this.initCheckEvents();
\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
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
29212 this.el.addClass('x-hidden');
\r
29214 this.innerWrap = this.el.wrap({
\r
29215 tabIndex: this.tabIndex,
\r
29216 cls: this.baseCls+'-wrap-inner'
\r
29218 this.wrap = this.innerWrap.wrap({cls: this.baseCls+'-wrap'});
\r
29220 if(this.boxLabel){
\r
29221 this.labelEl = this.innerWrap.createChild({
\r
29223 htmlFor: this.el.id,
\r
29224 cls: 'x-form-cb-label',
\r
29225 html: this.boxLabel
\r
29229 this.imageEl = this.innerWrap.createChild({
\r
29231 src: Ext.BLANK_IMAGE_URL,
\r
29232 cls: this.baseCls
\r
29235 if(this.checked){
\r
29236 this.setValue(true);
\r
29238 this.checked = this.el.dom.checked;
\r
29240 this.originalValue = this.checked;
\r
29244 afterRender : function(){
\r
29245 Ext.form.Checkbox.superclass.afterRender.call(this);
\r
29246 this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);
\r
29250 onDestroy : function(){
\r
29251 if(this.rendered){
\r
29252 Ext.destroy(this.imageEl, this.labelEl, this.innerWrap, this.wrap);
\r
29254 Ext.form.Checkbox.superclass.onDestroy.call(this);
\r
29258 onFocus: function(e) {
\r
29259 Ext.form.Checkbox.superclass.onFocus.call(this, e);
\r
29260 this.el.addClass(this.focusCls);
\r
29264 onBlur: function(e) {
\r
29265 Ext.form.Checkbox.superclass.onBlur.call(this, e);
\r
29266 this.el.removeClass(this.focusCls);
\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
29278 onKeyUp : function(e){
\r
29279 if(e.getKey() == Ext.EventObject.SPACE){
\r
29285 onClick : function(e){
\r
29286 if (!this.disabled && !this.readOnly) {
\r
29287 this.toggleValue();
\r
29293 onEnable : function(){
\r
29294 Ext.form.Checkbox.superclass.onEnable.call(this);
\r
29295 this.initCheckEvents();
\r
29299 onDisable : function(){
\r
29300 Ext.form.Checkbox.superclass.onDisable.call(this);
\r
29301 this.innerWrap.removeAllListeners();
\r
29304 toggleValue : function(){
\r
29305 this.setValue(!this.checked);
\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
29313 return this.resizeEl;
\r
29317 getPositionEl : function(){
\r
29318 return this.wrap;
\r
29322 getActionEl : function(){
\r
29323 return this.wrap;
\r
29327 markInvalid : Ext.emptyFn,
\r
29329 clearInvalid : Ext.emptyFn,
\r
29332 initValue : Ext.emptyFn,
\r
29335 getValue : function(){
\r
29336 if(this.rendered){
\r
29337 return this.el.dom.checked;
\r
29339 return this.checked;
\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
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
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
29365 Ext.reg('checkbox', Ext.form.Checkbox);
\r
29368 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
\r
29371 columns : 'auto',
\r
29373 vertical : false,
\r
29375 allowBlank : true,
\r
29377 blankText : "You must select at least one item in this group",
\r
29380 defaultType : 'checkbox',
\r
29383 groupCls: 'x-form-check-group',
\r
29386 onRender : function(ct, position){
\r
29389 cls: this.groupCls,
\r
29390 layout: 'column',
\r
29395 defaultType: this.defaultType,
\r
29404 if(this.items[0].items){
\r
29406 // The container has standard ColumnLayout configs, so pass them in directly
\r
29408 Ext.apply(panelCfg, {
\r
29409 layoutConfig: {columns: this.items.length},
\r
29410 defaults: this.defaults,
\r
29411 items: this.items
\r
29413 for(var i=0, len=this.items.length; i<len; i++){
\r
29414 Ext.applyIf(this.items[i], colCfg);
\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
29422 var numCols, cols = [];
\r
29424 if(typeof this.columns == 'string'){ // 'auto' so create a col per item
\r
29425 this.columns = this.items.length;
\r
29427 if(!Ext.isArray(this.columns)){
\r
29429 for(var i=0; i<this.columns; i++){
\r
29430 cs.push((100/this.columns)*.01); // distribute by even %
\r
29432 this.columns = cs;
\r
29435 numCols = this.columns.length;
\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
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
29454 if(this.items[i].fieldLabel){
\r
29455 this.items[i].hideLabel = false;
\r
29457 cols[ri].items.push(this.items[i]);
\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
29465 cols[ci].items.push(this.items[i]);
\r
29469 Ext.apply(panelCfg, {
\r
29470 layoutConfig: {columns: numCols},
\r
29475 this.panel = new Ext.Panel(panelCfg);
\r
29476 this.el = this.panel.getEl();
\r
29478 if(this.forId && this.itemCls){
\r
29479 var l = this.el.up(this.itemCls).child('label', true);
\r
29481 l.setAttribute('htmlFor', this.forId);
\r
29485 var fields = this.panel.findBy(function(c){
\r
29486 return c.isFormField;
\r
29489 this.items = new Ext.util.MixedCollection();
\r
29490 this.items.addAll(fields);
\r
29492 Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
\r
29496 validateValue : function(value){
\r
29497 if(!this.allowBlank){
\r
29498 var blank = true;
\r
29499 this.items.each(function(f){
\r
29501 return blank = false;
\r
29505 this.markInvalid(this.blankText);
\r
29513 onDisable : function(){
\r
29514 this.items.each(function(item){
\r
29520 onEnable : function(){
\r
29521 this.items.each(function(item){
\r
29527 onResize : function(w, h){
\r
29528 this.panel.setSize(w, h);
\r
29529 this.panel.doLayout();
\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
29544 initValue : Ext.emptyFn,
\r
29546 getValue : Ext.emptyFn,
\r
29548 getRawValue : Ext.emptyFn,
\r
29550 setValue : Ext.emptyFn,
\r
29552 setRawValue : Ext.emptyFn
\r
29556 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
\r
29559 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
\r
29561 inputType: 'radio',
\r
29563 baseCls: 'x-form-radio',
\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
29572 getParent : function(){
\r
29573 return this.el.up('form') || Ext.getBody();
\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
29584 Ext.getCmp(el.dom.id).setValue(false);
\r
29591 setValue : function(v){
\r
29592 if(typeof v=='boolean') {
\r
29593 Ext.form.Radio.superclass.setValue.call(this, v);
\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
29603 markInvalid : Ext.emptyFn,
\r
29605 clearInvalid : Ext.emptyFn
\r
29608 Ext.reg('radio', Ext.form.Radio);
\r
29611 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
\r
29613 allowBlank : true,
\r
29615 blankText : "You must select one item in this group",
\r
29618 defaultType : 'radio',
\r
29621 groupCls: 'x-form-radio-group'
\r
29624 Ext.reg('radiogroup', Ext.form.RadioGroup);
\r
29627 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
\r
29629 inputType : 'hidden',
\r
29632 onRender : function(){
\r
29633 Ext.form.Hidden.superclass.onRender.apply(this, arguments);
\r
29637 initEvents : function(){
\r
29638 this.originalValue = this.getValue();
\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
29650 Ext.reg('hidden', Ext.form.Hidden);
\r
29652 Ext.form.BasicForm = function(el, config){
\r
29653 Ext.apply(this, config);
\r
29655 this.items = new Ext.util.MixedCollection(false, function(o){
\r
29656 return o.id || (o.id = Ext.id());
\r
29670 Ext.form.BasicForm.superclass.constructor.call(this);
\r
29673 Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
\r
29684 activeAction : null,
\r
29687 trackResetOnLoad : false,
\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
29699 this.el.addClass('x-form');
\r
29703 getEl: function(){
\r
29708 onSubmit : function(e){
\r
29713 destroy: function() {
\r
29714 this.items.each(function(f){
\r
29718 this.el.removeAllListeners();
\r
29719 this.el.remove();
\r
29721 this.purgeListeners();
\r
29725 isValid : function(){
\r
29726 var valid = true;
\r
29727 this.items.each(function(f){
\r
29728 if(!f.validate()){
\r
29736 isDirty : function(){
\r
29737 var dirty = false;
\r
29738 this.items.each(function(f){
\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
29752 if(this.fireEvent('beforeaction', this, action) !== false){
\r
29753 this.beforeAction(action);
\r
29754 action.run.defer(100, action);
\r
29760 submit : function(options){
\r
29761 if(this.standardSubmit){
\r
29762 var v = this.isValid();
\r
29764 this.el.dom.submit();
\r
29768 this.doAction('submit', options);
\r
29773 load : function(options){
\r
29774 this.doAction('load', options);
\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
29785 record.set(f.name, field.getValue());
\r
29788 record.endEdit();
\r
29793 loadRecord : function(record){
\r
29794 this.setValues(record.data);
\r
29799 beforeAction : function(action){
\r
29800 var o = action.options;
\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
29808 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
\r
29814 afterAction : function(action, success){
\r
29815 this.activeAction = null;
\r
29816 var o = action.options;
\r
29818 if(this.waitMsgTarget === true){
\r
29819 this.el.unmask();
\r
29820 }else if(this.waitMsgTarget){
\r
29821 this.waitMsgTarget.unmask();
\r
29823 Ext.MessageBox.updateProgress(1);
\r
29824 Ext.MessageBox.hide();
\r
29831 Ext.callback(o.success, o.scope, [this, action]);
\r
29832 this.fireEvent('actioncomplete', this, action);
\r
29834 Ext.callback(o.failure, o.scope, [this, action]);
\r
29835 this.fireEvent('actionfailed', this, action);
\r
29840 findField : function(id){
\r
29841 var field = this.items.get(id);
\r
29843 this.items.each(function(f){
\r
29844 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
\r
29850 return field || null;
\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
29861 f.markInvalid(fieldError.msg);
\r
29866 for(id in errors){
\r
29867 if(typeof errors[id] != 'function' && (field = this.findField(id))){
\r
29868 field.markInvalid(errors[id]);
\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
29882 f.setValue(v.value);
\r
29883 if(this.trackResetOnLoad){
\r
29884 f.originalValue = f.getValue();
\r
29888 }else{ // object hash
\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
29903 getValues : function(asString){
\r
29904 var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
\r
29905 if(asString === true){
\r
29908 return Ext.urlDecode(fs);
\r
29912 clearInvalid : function(){
\r
29913 this.items.each(function(f){
\r
29914 f.clearInvalid();
\r
29920 reset : function(){
\r
29921 this.items.each(function(f){
\r
29928 add : function(){
\r
29929 this.items.addAll(Array.prototype.slice.call(arguments, 0));
\r
29935 remove : function(field){
\r
29936 this.items.remove(field);
\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
29951 applyToFields : function(o){
\r
29952 this.items.each(function(f){
\r
29959 applyIfToFields : function(o){
\r
29960 this.items.each(function(f){
\r
29961 Ext.applyIf(f, o);
\r
29968 Ext.BasicForm = Ext.form.BasicForm;
\r
29970 Ext.FormPanel = Ext.extend(Ext.Panel, {
\r
29976 buttonAlign:'center',
\r
29979 minButtonWidth:75,
\r
29982 labelAlign:'left',
\r
29985 monitorValid : false,
\r
29988 monitorPoll : 200,
\r
29994 initComponent :function(){
\r
29995 this.form = this.createForm();
\r
29999 cls: this.baseCls + '-body',
\r
30000 method : this.method || 'POST',
\r
30001 id : this.formId || Ext.id()
\r
30003 if(this.fileUpload) {
\r
30004 this.bodyCfg.enctype = 'multipart/form-data';
\r
30007 Ext.FormPanel.superclass.initComponent.call(this);
\r
30009 this.initItems();
\r
30013 'clientvalidation'
\r
30016 this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
\r
30020 createForm: function(){
\r
30021 delete this.initialConfig.listeners;
\r
30022 return new Ext.form.BasicForm(null, this.initialConfig);
\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
30032 }else if(c.doLayout && c != formPanel){
\r
30034 labelAlign: c.ownerCt.labelAlign,
\r
30035 labelWidth: c.ownerCt.labelWidth,
\r
30036 itemCls: c.ownerCt.itemCls
\r
30039 c.items.each(fn);
\r
30043 this.items.each(fn);
\r
30047 getLayoutTarget : function(){
\r
30048 return this.form.el;
\r
30052 getForm : function(){
\r
30053 return this.form;
\r
30057 onRender : function(ct, position){
\r
30058 this.initFields();
\r
30060 Ext.FormPanel.superclass.onRender.call(this, ct, position);
\r
30061 this.form.initEl(this.body);
\r
30065 beforeDestroy: function(){
\r
30066 Ext.FormPanel.superclass.beforeDestroy.call(this);
\r
30067 this.stopMonitoring();
\r
30068 Ext.destroy(this.form);
\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
30082 onAdd : function(ct, c) {
\r
30083 if (c.isFormField) {
\r
30084 this.form.add(c);
\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
30097 startMonitoring : function(){
\r
30099 this.bound = true;
\r
30100 Ext.TaskMgr.start({
\r
30101 run : this.bindHandler,
\r
30102 interval : this.monitorPoll || 200,
\r
30109 stopMonitoring : function(){
\r
30110 this.bound = false;
\r
30114 load : function(){
\r
30115 this.form.load.apply(this.form, arguments);
\r
30119 onDisable : function(){
\r
30120 Ext.FormPanel.superclass.onDisable.call(this);
\r
30122 this.form.items.each(function(){
\r
30129 onEnable : function(){
\r
30130 Ext.FormPanel.superclass.onEnable.call(this);
\r
30132 this.form.items.each(function(){
\r
30139 bindHandler : function(){
\r
30141 return false; // stops binding
\r
30143 var valid = true;
\r
30144 this.form.items.each(function(f){
\r
30145 if(!f.isValid(true)){
\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
30158 this.fireEvent('clientvalidation', this, valid);
\r
30161 Ext.reg('form', Ext.FormPanel);
\r
30163 Ext.form.FormPanel = Ext.FormPanel;
\r
30167 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
\r
30173 baseCls:'x-fieldset',
\r
30177 animCollapse: false,
\r
30180 onRender : function(ct, position){
\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
30189 Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
\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
30202 onCollapse : function(doAnim, animArg){
\r
30203 if(this.checkbox){
\r
30204 this.checkbox.dom.checked = false;
\r
30206 Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
\r
30211 onExpand : function(doAnim, animArg){
\r
30212 if(this.checkbox){
\r
30213 this.checkbox.dom.checked = true;
\r
30215 Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
\r
30219 onCheckClick : function(){
\r
30220 this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
\r
30224 beforeDestroy : function(){
\r
30225 if(this.checkbox){
\r
30226 this.checkbox.un('click', this.onCheckClick, this);
\r
30228 Ext.form.FieldSet.superclass.beforeDestroy.call(this);
\r
30269 Ext.reg('fieldset', Ext.form.FieldSet);
\r
30274 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
\r
30276 enableFormat : true,
\r
30278 enableFontSize : true,
\r
30280 enableColors : true,
\r
30282 enableAlignments : true,
\r
30284 enableLists : true,
\r
30286 enableSourceEdit : true,
\r
30288 enableLinks : true,
\r
30290 enableFont : true,
\r
30292 createLinkText : 'Please enter the URL for the link:',
\r
30294 defaultLinkValue : 'http:/'+'/',
\r
30300 'Times New Roman',
\r
30303 defaultFont: 'tahoma',
\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
30313 hideMode:'offsets',
\r
30314 defaultAutoCreate : {
\r
30316 style:"width:500px;height:300px;",
\r
30317 autocomplete: "off"
\r
30321 initComponent : function(){
\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
30345 lc = ff.toLowerCase();
\r
30347 '<option value="',lc,'" style="font-family:',ff,';"',
\r
30348 (this.defaultFont == lc ? ' selected="true">' : '>'),
\r
30353 return buf.join('');
\r
30357 createToolbar : function(editor){
\r
30359 var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
\r
30361 function btn(id, toggle, handler){
\r
30364 cls : 'x-btn-icon x-edit-'+id,
\r
30365 enableToggle:toggle !== false,
\r
30367 handler:handler||editor.relayBtnCmd,
\r
30368 clickEvent:'mousedown',
\r
30369 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
\r
30374 // build the toolbar
\r
30375 var tb = new Ext.Toolbar({
\r
30376 renderTo:this.wrap.dom.firstChild
\r
30379 // stop form submits
\r
30380 tb.el.on('click', function(e){
\r
30381 e.preventDefault();
\r
30384 if(this.enableFont && !Ext.isSafari2){
\r
30385 this.fontSelect = tb.el.createChild({
\r
30387 cls:'x-font-select',
\r
30388 html: this.createFontOptions()
\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
30396 this.fontSelect.dom,
\r
30401 if(this.enableFormat){
\r
30409 if(this.enableFontSize){
\r
30412 btn('increasefontsize', false, this.adjustFont),
\r
30413 btn('decreasefontsize', false, this.adjustFont)
\r
30417 if(this.enableColors){
\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
30425 menu : new Ext.menu.ColorMenu({
\r
30426 allowReselect: true,
\r
30427 focus: Ext.emptyFn,
\r
30430 selectHandler: function(cp, color){
\r
30431 this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
\r
30432 this.deferFocus();
\r
30435 clickEvent:'mousedown'
\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
30443 menu : new Ext.menu.ColorMenu({
\r
30444 focus: Ext.emptyFn,
\r
30447 allowReselect: true,
\r
30448 selectHandler: function(cp, color){
\r
30450 this.execCmd('useCSS', false);
\r
30451 this.execCmd('hilitecolor', color);
\r
30452 this.execCmd('useCSS', true);
\r
30453 this.deferFocus();
\r
30455 this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
\r
30456 this.deferFocus();
\r
30460 clickEvent:'mousedown'
\r
30466 if(this.enableAlignments){
\r
30469 btn('justifyleft'),
\r
30470 btn('justifycenter'),
\r
30471 btn('justifyright')
\r
30475 if(!Ext.isSafari2){
\r
30476 if(this.enableLinks){
\r
30479 btn('createlink', false, this.createLink)
\r
30483 if(this.enableLists){
\r
30486 btn('insertorderedlist'),
\r
30487 btn('insertunorderedlist')
\r
30490 if(this.enableSourceEdit){
\r
30493 btn('sourceedit', true, function(btn){
\r
30494 this.toggleSourceEdit(btn.pressed);
\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
30509 getEditorBody : function(){
\r
30510 return this.doc.body || this.doc.documentElement;
\r
30514 getDoc : function(){
\r
30515 return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
\r
30519 getWin : function(){
\r
30520 return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
\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
30532 this.wrap = this.el.wrap({
\r
30533 cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
\r
30536 this.createToolbar(this);
\r
30538 this.tb.items.each(function(item){
\r
30539 if(item.itemId != 'sourceedit'){
\r
30544 var iframe = document.createElement('iframe');
\r
30545 iframe.name = Ext.id();
\r
30546 iframe.frameBorder = '0';
\r
30548 iframe.src = Ext.isIE ? Ext.SSL_SECURE_URL : "javascript:;";
\r
30550 this.wrap.dom.appendChild(iframe);
\r
30552 this.iframe = iframe;
\r
30554 this.initFrame();
\r
30556 if(this.autoMonitorDesignMode !== false){
\r
30557 this.monitorTask = Ext.TaskMgr.start({
\r
30558 run: this.checkDesignMode,
\r
30565 var sz = this.el.getSize();
\r
30566 this.setSize(sz.width, this.height || sz.height);
\r
30570 initFrame : function(){
\r
30571 this.doc = this.getDoc();
\r
30572 this.win = this.getWin();
\r
30575 this.doc.write(this.getDocMarkup());
\r
30576 this.doc.close();
\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
30590 Ext.TaskMgr.start(task);
\r
30594 checkDesignMode : function(){
\r
30595 if(this.wrap && this.wrap.dom.offsetWidth){
\r
30596 var doc = this.getDoc();
\r
30600 if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){
\r
30601 this.initFrame();
\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
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
30620 this.getEditorBody().style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
\r
30627 toggleSourceEdit : function(sourceEditMode){
\r
30628 if(sourceEditMode === undefined){
\r
30629 sourceEditMode = !this.sourceEditMode;
\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
30637 if(this.sourceEditMode){
\r
30638 this.tb.items.each(function(item){
\r
30639 if(item.itemId != 'sourceedit'){
\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
30649 if(this.initialized){
\r
30650 this.tb.items.each(function(item){
\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
30660 var lastSize = this.lastSize;
\r
30662 delete this.lastSize;
\r
30663 this.setSize(lastSize);
\r
30665 this.fireEvent('editmodechange', this, this.sourceEditMode);
\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
30676 // private (for BoxComponent)
\r
30677 adjustSize : Ext.BoxComponent.prototype.adjustSize,
\r
30679 // private (for BoxComponent)
\r
30680 getResizeEl : function(){
\r
30681 return this.wrap;
\r
30684 // private (for BoxComponent)
\r
30685 getPositionEl : function(){
\r
30686 return this.wrap;
\r
30690 initEvents : function(){
\r
30691 this.originalValue = this.getValue();
\r
30695 markInvalid : Ext.emptyFn,
\r
30698 clearInvalid : Ext.emptyFn,
\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
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
30714 if(html == ' '){
\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
30729 html = '<div style="'+m[0]+'">' + html + '</div>';
\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
30740 //docs inherit from Field
\r
30741 getValue : function() {
\r
30742 this.syncValue();
\r
30743 return Ext.form.HtmlEditor.superclass.getValue.call(this);
\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
30754 if(this.fireEvent('beforepush', this, v) !== false){
\r
30755 this.getEditorBody().innerHTML = v;
\r
30756 this.fireEvent('push', this, v);
\r
30762 deferFocus : function(){
\r
30763 this.focus.defer(10, this);
\r
30766 // docs inherit from Field
\r
30767 focus : function(){
\r
30768 if(this.win && !this.sourceEditMode){
\r
30769 this.win.focus();
\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
30782 Ext.DomHelper.applyStyles(dbody, ss);
\r
30786 Ext.EventManager.removeAll(this.doc);
\r
30790 this.doc = this.getDoc();
\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
30802 Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
\r
30804 if(Ext.isIE || Ext.isSafari || Ext.isOpera){
\r
30805 Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
\r
30807 this.initialized = true;
\r
30809 this.fireEvent('initialize', this);
\r
30811 this.doc.editorInitialized = true;
\r
30813 this.pushValue();
\r
30817 onDestroy : function(){
\r
30818 if(this.monitorTask){
\r
30819 Ext.TaskMgr.stop(this.monitorTask);
\r
30821 if(this.rendered){
\r
30822 this.tb.items.each(function(item){
\r
30824 item.menu.removeAll();
\r
30825 if(item.menu.el){
\r
30826 item.menu.el.destroy();
\r
30831 this.wrap.dom.innerHTML = '';
\r
30832 this.wrap.remove();
\r
30837 onFirstFocus : function(){
\r
30838 this.activated = true;
\r
30839 this.tb.items.each(function(item){
\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
30852 this.execCmd('useCSS', true);
\r
30853 this.execCmd('styleWithCSS', false);
\r
30856 this.fireEvent('activate', this);
\r
30860 adjustFont: function(btn){
\r
30861 var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;
\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
30869 }else if(v <= 13){
\r
30871 }else if(v <= 16){
\r
30873 }else if(v <= 18){
\r
30875 }else if(v <= 24){
\r
30880 v = v.constrain(1, 6);
\r
30882 if(Ext.isSafari){ // safari
\r
30885 v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
\r
30887 this.execCmd('FontSize', v);
\r
30891 onEditorEvent : function(e){
\r
30892 this.updateToolbar();
\r
30897 updateToolbar: function(){
\r
30899 if(!this.activated){
\r
30900 this.onFirstFocus();
\r
30904 var btns = this.tb.items.map, doc = this.doc;
\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
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
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
30922 if(!Ext.isSafari2 && this.enableLists){
\r
30923 btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
\r
30924 btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
\r
30927 Ext.menu.MenuMgr.hideAll();
\r
30929 this.syncValue();
\r
30933 relayBtnCmd : function(btn){
\r
30934 this.relayCmd(btn.itemId);
\r
30938 relayCmd : function(cmd, value){
\r
30941 this.execCmd(cmd, value);
\r
30942 this.updateToolbar();
\r
30943 }).defer(10, this);
\r
30947 execCmd : function(cmd, value){
\r
30948 this.doc.execCommand(cmd, false, value === undefined ? null : value);
\r
30949 this.syncValue();
\r
30953 applyCommand : function(e){
\r
30955 var c = e.getCharCode(), cmd;
\r
30957 c = String.fromCharCode(c);
\r
30966 cmd = 'underline';
\r
30970 this.win.focus();
\r
30971 this.execCmd(cmd);
\r
30972 this.deferFocus();
\r
30973 e.preventDefault();
\r
30980 insertAtCursor : function(text){
\r
30981 if(!this.activated){
\r
30985 this.win.focus();
\r
30986 var r = this.doc.selection.createRange();
\r
30988 r.collapse(true);
\r
30989 r.pasteHTML(text);
\r
30990 this.syncValue();
\r
30991 this.deferFocus();
\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
31004 fixKeys : function(){ // load time branching for fastest keydown performance
\r
31006 return function(e){
\r
31007 var k = e.getKey(), r;
\r
31010 r = this.doc.selection.createRange();
\r
31012 r.collapse(true);
\r
31013 r.pasteHTML(' ');
\r
31014 this.deferFocus();
\r
31016 }else if(k == e.ENTER){
\r
31017 r = this.doc.selection.createRange();
\r
31019 var target = r.parentElement();
\r
31020 if(!target || target.tagName.toLowerCase() != 'li'){
\r
31022 r.pasteHTML('<br />');
\r
31023 r.collapse(false);
\r
31029 }else if(Ext.isOpera){
\r
31030 return function(e){
\r
31031 var k = e.getKey();
\r
31034 this.win.focus();
\r
31035 this.execCmd('InsertHTML',' ');
\r
31036 this.deferFocus();
\r
31039 }else if(Ext.isSafari){
\r
31040 return function(e){
\r
31041 var k = e.getKey();
\r
31044 this.execCmd('InsertText','\t');
\r
31045 this.deferFocus();
\r
31052 getToolbar : function(){
\r
31059 title: 'Bold (Ctrl+B)',
\r
31060 text: 'Make the selected text bold.',
\r
31061 cls: 'x-html-editor-tip'
\r
31064 title: 'Italic (Ctrl+I)',
\r
31065 text: 'Make the selected text italic.',
\r
31066 cls: 'x-html-editor-tip'
\r
31069 title: 'Underline (Ctrl+U)',
\r
31070 text: 'Underline the selected text.',
\r
31071 cls: 'x-html-editor-tip'
\r
31073 increasefontsize : {
\r
31074 title: 'Grow Text',
\r
31075 text: 'Increase the font size.',
\r
31076 cls: 'x-html-editor-tip'
\r
31078 decreasefontsize : {
\r
31079 title: 'Shrink Text',
\r
31080 text: 'Decrease the font size.',
\r
31081 cls: 'x-html-editor-tip'
\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
31089 title: 'Font Color',
\r
31090 text: 'Change the color of the selected text.',
\r
31091 cls: 'x-html-editor-tip'
\r
31094 title: 'Align Text Left',
\r
31095 text: 'Align text to the left.',
\r
31096 cls: 'x-html-editor-tip'
\r
31098 justifycenter : {
\r
31099 title: 'Center Text',
\r
31100 text: 'Center text in the editor.',
\r
31101 cls: 'x-html-editor-tip'
\r
31104 title: 'Align Text Right',
\r
31105 text: 'Align text to the right.',
\r
31106 cls: 'x-html-editor-tip'
\r
31108 insertunorderedlist : {
\r
31109 title: 'Bullet List',
\r
31110 text: 'Start a bulleted list.',
\r
31111 cls: 'x-html-editor-tip'
\r
31113 insertorderedlist : {
\r
31114 title: 'Numbered List',
\r
31115 text: 'Start a numbered list.',
\r
31116 cls: 'x-html-editor-tip'
\r
31119 title: 'Hyperlink',
\r
31120 text: 'Make the selected text a hyperlink.',
\r
31121 cls: 'x-html-editor-tip'
\r
31124 title: 'Source Edit',
\r
31125 text: 'Switch to source editing mode.',
\r
31126 cls: 'x-html-editor-tip'
\r
31130 // hide stuff that is not compatible
\r
31165 Ext.reg('htmleditor', Ext.form.HtmlEditor);
\r
31167 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
\r
31173 minText : "The time in this field must be equal to or after {0}",
\r
31175 maxText : "The time in this field must be equal to or before {0}",
\r
31177 invalidText : "{0} is not a valid time",
\r
31179 format : "g:i A",
\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
31185 // private override
\r
31187 // private override
\r
31188 triggerAction: 'all',
\r
31189 // private override
\r
31190 typeAhead: false,
\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
31198 initComponent : function(){
\r
31199 Ext.form.TimeField.superclass.initComponent.call(this);
\r
31201 if(typeof this.minValue == "string"){
\r
31202 this.minValue = this.parseDate(this.minValue);
\r
31204 if(typeof this.maxValue == "string"){
\r
31205 this.maxValue = this.parseDate(this.maxValue);
\r
31209 var min = this.parseDate(this.minValue);
\r
31211 min = new Date(this.initDate).clearTime();
\r
31213 var max = this.parseDate(this.maxValue);
\r
31215 max = new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);
\r
31218 while(min <= max){
\r
31219 times.push([min.dateFormat(this.format)]);
\r
31220 min = min.add('mi', this.increment);
\r
31222 this.store = new Ext.data.SimpleStore({
\r
31223 fields: ['text'],
\r
31226 this.displayField = 'text';
\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
31236 // inherited docs
\r
31237 setValue : function(value){
\r
31238 Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
\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
31247 beforeBlur : function(){
\r
31248 var v = this.parseDate(this.getRawValue());
\r
31250 this.setValue(v.dateFormat(this.format));
\r
31259 Ext.reg('timefield', Ext.form.TimeField);
\r
31261 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
\r
31267 onRender : function(ct, position){
\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
31273 this.el.setAttribute('for', this.forId);
\r
31276 Ext.form.Label.superclass.onRender.call(this, ct, position);
\r
31280 setText: function(t, encode){
\r
31282 if(this.rendered){
\r
31283 this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
\r
31289 Ext.reg('label', Ext.form.Label);
\r
31291 Ext.form.Action = function(form, options){
\r
31292 this.form = form;
\r
31293 this.options = options || {};
\r
31297 Ext.form.Action.CLIENT_INVALID = 'client';
\r
31299 Ext.form.Action.SERVER_INVALID = 'server';
\r
31301 Ext.form.Action.CONNECT_FAILURE = 'connect';
\r
31303 Ext.form.Action.LOAD_FAILURE = 'load';
\r
31305 Ext.form.Action.prototype = {
\r
31318 type : 'default',
\r
31321 // interface method
\r
31322 run : function(options){
\r
31326 // interface method
\r
31327 success : function(response){
\r
31331 // interface method
\r
31332 handleResponse : function(response){
\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
31344 processResponse : function(response){
\r
31345 this.response = response;
\r
31346 if(!response.responseText){
\r
31349 this.result = this.handleResponse(response);
\r
31350 return this.result;
\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
31359 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
\r
31366 getMethod : function(){
\r
31367 return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
\r
31371 getParams : function(){
\r
31372 var bp = this.form.baseParams;
\r
31373 var p = this.options.params;
\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
31381 p = Ext.urlEncode(bp);
\r
31387 createCallback : function(opts){
\r
31388 var opts = opts || {};
\r
31390 success: this.success,
\r
31391 failure: this.failure,
\r
31393 timeout: (opts.timeout*1000) || (this.form.timeout*1000),
\r
31394 upload: this.form.fileUpload ? this.success : undefined
\r
31400 Ext.form.Action.Submit = function(form, options){
\r
31401 Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
\r
31404 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
\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
31419 headers: o.headers,
\r
31420 params:!isGet ? this.getParams() : null,
\r
31421 isUpload: this.form.fileUpload
\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
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
31436 if(result.errors){
\r
31437 this.form.markInvalid(result.errors);
\r
31438 this.failureType = Ext.form.Action.SERVER_INVALID;
\r
31440 this.form.afterAction(this, false);
\r
31444 handleResponse : function(response){
\r
31445 if(this.form.errorReader){
\r
31446 var rs = this.form.errorReader.read(response);
\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
31454 if(errors.length < 1){
\r
31458 success : rs.success,
\r
31462 return Ext.decode(response.responseText);
\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
31473 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
\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
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
31496 this.form.clearInvalid();
\r
31497 this.form.setValues(result.data);
\r
31498 this.form.afterAction(this, true);
\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
31507 success : rs.success,
\r
31511 return Ext.decode(response.responseText);
\r
31515 Ext.form.Action.ACTION_TYPES = {
\r
31516 'load' : Ext.form.Action.Load,
\r
31517 'submit' : Ext.form.Action.Submit
\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
31528 // All these messages and functions are configurable
\r
31531 'email' : function(v){
\r
31532 return email.test(v);
\r
31535 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
\r
31537 'emailMask' : /[a-z0-9_\.\-@]/i,
\r
31540 'url' : function(v){
\r
31541 return url.test(v);
\r
31544 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
\r
31547 'alpha' : function(v){
\r
31548 return alpha.test(v);
\r
31551 'alphaText' : 'This field should only contain letters and _',
\r
31553 'alphaMask' : /[a-z_]/i,
\r
31556 'alphanum' : function(v){
\r
31557 return alphanum.test(v);
\r
31560 'alphanumText' : 'This field should only contain letters, numbers and _',
\r
31562 'alphanumMask' : /[a-z0-9_]/i
\r
31566 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
\r
31581 ddText : "{0} selected row{1}",
\r
31583 minColumnWidth : 25,
\r
31585 trackMouseOver : true,
\r
31587 enableDragDrop : false,
\r
31589 enableColumnMove : true,
\r
31591 enableColumnHide : true,
\r
31593 enableHdMenu : true,
\r
31595 stripeRows : false,
\r
31597 autoExpandColumn : false,
\r
31599 autoExpandMin : 50,
\r
31601 autoExpandMax : 1000,
\r
31605 loadMask : false,
\r
31608 deferRowRender : true,
\r
31611 rendered : false,
\r
31613 viewReady: false,
\r
31615 stateEvents: ["columnmove", "columnresize", "sortchange"],
\r
31618 initComponent : function(){
\r
31619 Ext.grid.GridPanel.superclass.initComponent.call(this);
\r
31621 // override any provided value since it isn't valid
\r
31622 this.autoScroll = false;
\r
31623 this.autoWidth = false;
\r
31625 if(Ext.isArray(this.columns)){
\r
31626 this.colModel = new Ext.grid.ColumnModel(this.columns);
\r
31627 delete this.columns;
\r
31630 // check and correct shorthanded configs
\r
31632 this.store = this.ds;
\r
31636 this.colModel = this.cm;
\r
31640 this.selModel = this.sm;
\r
31643 this.store = Ext.StoreMgr.lookup(this.store);
\r
31672 "headermousedown",
\r
31685 "headerdblclick",
\r
31687 "rowcontextmenu",
\r
31689 "cellcontextmenu",
\r
31691 "headercontextmenu",
\r
31704 onRender : function(ct, position){
\r
31705 Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
\r
31707 var c = this.body;
\r
31709 this.el.addClass('x-grid-panel');
\r
31711 var view = this.getView();
\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
31720 this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);
\r
31722 this.getSelectionModel().init(this);
\r
31723 this.view.render();
\r
31727 initEvents : function(){
\r
31728 Ext.grid.GridPanel.superclass.initEvents.call(this);
\r
31730 if(this.loadMask){
\r
31731 this.loadMask = new Ext.LoadMask(this.bwrap,
\r
31732 Ext.apply({store:this.store}, this.loadMask));
\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
31741 applyState : function(state){
\r
31742 var cm = this.colModel;
\r
31743 var cs = state.columns;
\r
31745 for(var i = 0, len = cs.length; i < len; i++){
\r
31747 var c = cm.getColumnById(s.id);
\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
31759 this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
\r
31763 getState : function(){
\r
31764 var o = {columns: []};
\r
31765 for(var i = 0, c; c = this.colModel.config[i]; i++){
\r
31771 o.columns[i].hidden = true;
\r
31774 var ss = this.store.getSortState();
\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
31788 this.view.afterRender();
\r
31790 this.viewReady = true;
\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
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
31809 onKeyDown : function(e){
\r
31810 this.fireEvent("keydown", e);
\r
31814 onDestroy : function(){
\r
31815 if(this.rendered){
\r
31816 if(this.loadMask){
\r
31817 this.loadMask.destroy();
\r
31819 var c = this.body;
\r
31820 c.removeAllListeners();
\r
31821 this.view.destroy();
\r
31824 this.colModel.purgeListeners();
\r
31825 Ext.grid.GridPanel.superclass.onDestroy.call(this);
\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
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
31849 onClick : function(e){
\r
31850 this.processEvent("click", e);
\r
31854 onMouseDown : function(e){
\r
31855 this.processEvent("mousedown", e);
\r
31859 onContextMenu : function(e, t){
\r
31860 this.processEvent("contextmenu", e);
\r
31864 onDblClick : function(e){
\r
31865 this.processEvent("dblclick", e);
\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
31883 if(fn.call(scope || this, row, col, cm) === true){
\r
31884 return [row, col];
\r
31895 while(row < rlen){
\r
31900 while(col < clen){
\r
31901 if(fn.call(scope || this, row, col, cm) === true){
\r
31902 return [row, col];
\r
31913 getSelections : function(){
\r
31914 return this.selModel.getSelections();
\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
31926 getGridEl : function(){
\r
31927 return this.body;
\r
31930 // private for compatibility, overridden by editor grid
\r
31931 stopEditing : Ext.emptyFn,
\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
31939 return this.selModel;
\r
31943 getStore : function(){
\r
31944 return this.store;
\r
31948 getColumnModel : function(){
\r
31949 return this.colModel;
\r
31953 getView : function(){
\r
31955 this.view = new Ext.grid.GridView(this.viewConfig);
\r
31957 return this.view;
\r
31960 getDragDropText : function(){
\r
31961 var count = this.selModel.getCount();
\r
31962 return String.format(this.ddText, count, count == 1 ? '' : 's');
\r
32015 Ext.reg('grid', Ext.grid.GridPanel);
\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
32022 "beforerowremoved",
\r
32024 "beforerowsinserted",
\r
32036 Ext.grid.GridView.superclass.constructor.call(this);
\r
32039 Ext.extend(Ext.grid.GridView, Ext.util.Observable, {
\r
32045 deferEmptyText: true,
\r
32047 scrollOffset: 19,
\r
32053 sortClasses : ["sort-asc", "sort-desc"],
\r
32055 sortAscText : "Sort Ascending",
\r
32057 sortDescText : "Sort Descending",
\r
32059 columnsText : "Columns",
\r
32063 tdClass: 'x-grid3-cell',
\r
32064 hdCls: 'x-grid3-hd',
\r
32067 cellSelectorDepth: 4,
\r
32069 rowSelectorDepth: 10,
\r
32072 cellSelector: 'td.x-grid3-cell',
\r
32074 rowSelector: 'div.x-grid3-row',
\r
32079 initTemplates : function(){
\r
32080 var ts = this.templates || {};
\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
32088 '<div class="x-grid3-resize-marker"> </div>',
\r
32089 '<div class="x-grid3-resize-proxy"> </div>',
\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
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
32111 ts.body = new Ext.Template('{rows}');
\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
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
32131 for(var k in ts){
\r
32133 if(t && typeof t.compile == 'function' && !t.compiled){
\r
32134 t.disableFormats = true;
\r
32139 this.templates = ts;
\r
32140 this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");
\r
32144 fly : function(el){
\r
32145 if(!this._flyweight){
\r
32146 this._flyweight = new Ext.Element.Flyweight(document.body);
\r
32148 this._flyweight.dom = el;
\r
32149 return this._flyweight;
\r
32153 getEditorParent : function(){
\r
32154 return this.scroller.dom;
\r
32158 initElements : function(){
\r
32159 var E = Ext.Element;
\r
32161 var el = this.grid.getGridEl().dom.firstChild;
\r
32162 var cs = el.childNodes;
\r
32164 this.el = new E(el);
\r
32166 this.mainWrap = new E(cs[0]);
\r
32167 this.mainHd = new E(this.mainWrap.dom.firstChild);
\r
32169 if(this.grid.hideHeaders){
\r
32170 this.mainHd.setDisplayed(false);
\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
32179 this.mainBody = new E(this.scroller.dom.firstChild);
\r
32181 this.focusEl = new E(this.scroller.dom.childNodes[1]);
\r
32182 this.focusEl.swallowEvent("click", true);
\r
32184 this.resizeMarker = new E(cs[1]);
\r
32185 this.resizeProxy = new E(cs[2]);
\r
32189 getRows : function(){
\r
32190 return this.hasRows() ? this.mainBody.dom.childNodes : [];
\r
32193 // finder methods, used with delegation
\r
32196 findCell : function(el){
\r
32200 return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
\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
32213 getCellIndex : function(el){
\r
32215 var m = el.className.match(this.colRe);
\r
32217 return this.cm.getIndexById(m[1]);
\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
32230 findHeaderIndex : function(el){
\r
32231 return this.findCellIndex(el, this.hdCls);
\r
32235 findRow : function(el){
\r
32239 return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
\r
32243 findRowIndex : function(el){
\r
32244 var r = this.findRow(el);
\r
32245 return r ? r.rowIndex : false;
\r
32248 // getter methods for fetching elements dynamically in the grid
\r
32251 getRow : function(row){
\r
32252 return this.getRows()[row];
\r
32256 getCell : function(row, col){
\r
32257 return this.getRow(row).getElementsByTagName('td')[col];
\r
32261 getHeaderCell : function(index){
\r
32262 return this.mainHd.dom.getElementsByTagName('td')[index];
\r
32265 // manipulating elements
\r
32267 // private - use getRowClass to apply custom row classes
\r
32268 addRowClass : function(row, cls){
\r
32269 var r = this.getRow(row);
\r
32271 this.fly(r).addClass(cls);
\r
32276 removeRowClass : function(row, cls){
\r
32277 var r = this.getRow(row);
\r
32279 this.fly(r).removeClass(cls);
\r
32284 removeRow : function(row){
\r
32285 Ext.removeNode(this.getRow(row));
\r
32286 this.syncFocusEl(row);
\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
32295 this.syncFocusEl(firstRow);
\r
32298 // scrolling stuff
\r
32301 getScrollState : function(){
\r
32302 var sb = this.scroller.dom;
\r
32303 return {left: sb.scrollLeft, top: sb.scrollTop};
\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
32314 scrollToTop : function(){
\r
32315 this.scroller.dom.scrollTop = 0;
\r
32316 this.scroller.dom.scrollLeft = 0;
\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
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
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
32341 updateAllColumnWidths : function(){
\r
32342 var tw = this.getTotalWidth();
\r
32343 var clen = this.cm.getColumnCount();
\r
32345 for(var i = 0; i < clen; i++){
\r
32346 ws[i] = this.getColumnWidth(i);
\r
32349 this.innerHd.firstChild.firstChild.style.width = tw;
\r
32351 for(var i = 0; i < clen; i++){
\r
32352 var hd = this.getHeaderCell(i);
\r
32353 hd.style.width = ws[i];
\r
32356 var ns = this.getRows(), row, trow;
\r
32357 for(var i = 0, len = ns.length; i < len; 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
32369 this.onAllColumnWidthsUpdated(ws, tw);
\r
32373 updateColumnWidth : function(col, width){
\r
32374 var w = this.getColumnWidth(col);
\r
32375 var tw = this.getTotalWidth();
\r
32377 this.innerHd.firstChild.firstChild.style.width = tw;
\r
32378 var hd = this.getHeaderCell(col);
\r
32379 hd.style.width = w;
\r
32381 var ns = this.getRows(), row;
\r
32382 for(var i = 0, len = ns.length; i < len; 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
32391 this.onColumnWidthUpdated(col, w, tw);
\r
32395 updateColumnHidden : function(col, hidden){
\r
32396 var tw = this.getTotalWidth();
\r
32398 this.innerHd.firstChild.firstChild.style.width = tw;
\r
32400 var display = hidden ? 'none' : '';
\r
32402 var hd = this.getHeaderCell(col);
\r
32403 hd.style.display = display;
\r
32405 var ns = this.getRows(), row;
\r
32406 for(var i = 0, len = ns.length; i < len; 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
32415 this.onColumnHiddenUpdated(col, hidden, tw);
\r
32417 delete this.lastViewWidth; // force recalc
\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
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
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 = " ";
\r
32438 if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
\r
32439 p.css += ' x-grid3-dirty-cell';
\r
32441 cb[cb.length] = ct.apply(p);
\r
32444 if(stripe && ((rowIndex+1) % 2 == 0)){
\r
32445 alt[0] = "x-grid3-row-alt";
\r
32448 alt[1] = " x-grid3-dirty-row";
\r
32450 rp.cols = colCount;
\r
32451 if(this.getRowClass){
\r
32452 alt[2] = this.getRowClass(r, rowIndex, rp, ds);
\r
32454 rp.alt = alt.join(" ");
\r
32455 rp.cells = cb.join("");
\r
32456 buf[buf.length] = rt.apply(rp);
\r
32458 return buf.join("");
\r
32462 processRows : function(startRow, skipStripe){
\r
32463 if(this.ds.getCount() < 1){
\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
32476 var isAlt = ((i+1) % 2 == 0);
\r
32477 var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;
\r
32478 if(isAlt == hasAlt){
\r
32482 row.className += " x-grid3-row-alt";
\r
32484 row.className = row.className.replace("x-grid3-row-alt", "");
\r
32490 afterRender: function(){
\r
32491 this.mainBody.dom.innerHTML = this.renderRows();
\r
32492 this.processRows(0, true);
\r
32494 if(this.deferEmptyText !== true){
\r
32495 this.applyEmptyText();
\r
32500 renderUI : function(){
\r
32502 var header = this.renderHeaders();
\r
32503 var body = this.templates.body.apply({rows:''});
\r
32506 var html = this.templates.master.apply({
\r
32511 var g = this.grid;
\r
32513 g.getGridEl().dom.innerHTML = html;
\r
32515 this.initElements();
\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
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
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
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
32539 this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});
\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
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
32549 this.hmenu.on("itemclick", this.handleHdMenuClick, this);
\r
32551 //g.on("headercontextmenu", this.handleHdCtx, this);
\r
32554 if(g.trackMouseOver){
\r
32555 this.mainBody.on("mouseover", this.onRowOver, this);
\r
32556 this.mainBody.on("mouseout", this.onRowOut, this);
\r
32558 if(g.enableDragDrop || g.enableDrag){
\r
32559 this.dragZone = new Ext.grid.GridDragZone(g, {
\r
32560 ddGroup : g.ddGroup || 'GridDD'
\r
32564 this.updateHeaderSortState();
\r
32569 layout : function(){
\r
32570 if(!this.mainBody){
\r
32571 return; // not rendered
\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
32578 if(vw < 20 || csize.height < 20){ // display: none?
\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
32588 this.el.setSize(csize.width, csize.height);
\r
32590 var hdHeight = this.mainHd.getHeight();
\r
32591 var vh = csize.height - (hdHeight);
\r
32593 this.scroller.setSize(vw, vh);
\r
32594 if(this.innerHd){
\r
32595 this.innerHd.style.width = (vw)+'px';
\r
32598 if(this.forceFit){
\r
32599 if(this.lastViewWidth != vw){
\r
32600 this.fitColumns(false, false);
\r
32601 this.lastViewWidth = vw;
\r
32604 this.autoExpand();
\r
32605 this.syncHeaderScroll();
\r
32607 this.onLayout(vw, vh);
\r
32610 // template functions for subclasses and plugins
\r
32611 // these functions include precalculated values
\r
32612 onLayout : function(vw, vh){
\r
32616 onColumnWidthUpdated : function(col, w, tw){
\r
32617 //template method
\r
32618 this.focusEl.setWidth(tw);
\r
32621 onAllColumnWidthsUpdated : function(ws, tw){
\r
32622 //template method
\r
32623 this.focusEl.setWidth(tw);
\r
32626 onColumnHiddenUpdated : function(col, hidden, tw){
\r
32627 // template method
\r
32628 this.focusEl.setWidth(tw);
\r
32631 updateColumnText : function(col, text){
\r
32632 // template method
\r
32635 afterMove : function(colIndex){
\r
32636 // template method
\r
32641 init: function(grid){
\r
32642 this.grid = grid;
\r
32644 this.initTemplates();
\r
32645 this.initData(grid.store, grid.colModel);
\r
32646 this.initUI(grid);
\r
32650 getColumnId : function(index){
\r
32651 return this.cm.getColumnId(index);
\r
32655 renderHeaders : function(){
\r
32656 var cm = this.cm, ts = this.templates;
\r
32657 var ct = ts.hcell;
\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
32673 cb[cb.length] = ct.apply(p);
\r
32675 return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});
\r
32679 getColumnTooltip : function(i){
\r
32680 var tt = this.cm.getColumnTooltip(i);
\r
32682 if(Ext.QuickTips.isEnabled()){
\r
32683 return 'ext:qtip="'+tt+'"';
\r
32685 return 'title="'+tt+'"';
\r
32692 beforeUpdate : function(){
\r
32693 this.grid.stopEditing(true);
\r
32697 updateHeaders : function(){
\r
32698 this.innerHd.firstChild.innerHTML = this.renderHeaders();
\r
32702 focusRow : function(row){
\r
32703 this.focusCell(row, 0, false);
\r
32707 focusCell : function(row, col, hscroll){
\r
32708 this.syncFocusEl(this.ensureVisible(row, col, hscroll));
\r
32710 this.focusEl.focus();
\r
32712 this.focusEl.focus.defer(1, this.focusEl);
\r
32716 resolveCell : function(row, col, hscroll){
\r
32717 if(typeof row != "number"){
\r
32718 row = row.rowIndex;
\r
32723 if(row < 0 || row >= this.ds.getCount()){
\r
32726 col = (col !== undefined ? col : 0);
\r
32728 var rowEl = this.getRow(row), cellEl;
\r
32729 if(!(hscroll === false && col === 0)){
\r
32730 while(this.cm.isHidden(col)){
\r
32733 cellEl = this.getCell(row, col);
\r
32736 return {row: rowEl, cell: cellEl};
\r
32739 getResolvedXY : function(resolved){
\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
32747 syncFocusEl : function(row, col, hscroll){
\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
32753 this.focusEl.setXY(xy||this.scroller.getXY());
\r
32756 ensureVisible : function(row, col, hscroll){
\r
32757 var resolved = this.resolveCell(row, col, hscroll);
\r
32758 if(!resolved || !resolved.row){
\r
32762 var rowEl = resolved.row, cellEl = resolved.cell;
\r
32764 var c = this.scroller.dom;
\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
32772 ctop -= this.mainHd.dom.offsetHeight;
\r
32774 var cbot = ctop + rowEl.offsetHeight;
\r
32776 var ch = c.clientHeight;
\r
32777 var stop = parseInt(c.scrollTop, 10);
\r
32778 var sbot = stop + ch;
\r
32781 c.scrollTop = ctop;
\r
32782 }else if(cbot > sbot){
\r
32783 c.scrollTop = cbot-ch;
\r
32786 if(hscroll !== false){
\r
32787 var cleft = parseInt(cellEl.offsetLeft, 10);
\r
32788 var cright = cleft + cellEl.offsetWidth;
\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
32798 return this.getResolvedXY(resolved);
\r
32802 insertRows : function(dm, firstRow, lastRow, isUpdate){
\r
32803 if(!isUpdate && firstRow === 0 && lastRow >= dm.getCount()-1){
\r
32807 this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
\r
32809 var html = this.renderRows(firstRow, lastRow);
\r
32810 var before = this.getRow(firstRow);
\r
32812 Ext.DomHelper.insertHtml('beforeBegin', before, html);
\r
32814 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
\r
32817 this.fireEvent("rowsinserted", this, firstRow, lastRow);
\r
32818 this.processRows(firstRow);
\r
32821 this.syncFocusEl(firstRow);
\r
32825 deleteRows : function(dm, firstRow, lastRow){
\r
32826 if(dm.getRowCount()<1){
\r
32829 this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);
\r
32831 this.removeRows(firstRow, lastRow);
\r
32833 this.processRows(firstRow);
\r
32834 this.fireEvent("rowsdeleted", this, firstRow, lastRow);
\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
32845 var align = this.cm.config[col].align;
\r
32847 style += 'text-align:'+align+';';
\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
32862 getTotalWidth : function(){
\r
32863 return this.cm.getTotalWidth()+'px';
\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
32872 if(aw < 20){ // not initialized, so don't screw up the default widths
\r
32875 var extra = aw - tw;
\r
32881 var vc = cm.getColumnCount(true);
\r
32882 var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);
\r
32885 omitColumn = undefined;
\r
32887 var colCount = cm.getColumnCount();
\r
32889 var extraCol = 0;
\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
32901 var frac = (aw - cm.getTotalWidth())/width;
\r
32902 while (cols.length){
\r
32905 cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
\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
32914 if(preventRefresh !== true){
\r
32915 this.updateAllColumnWidths();
\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
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
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
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
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
32964 if(ds.getCount() < 1){
\r
32968 var cs = this.getColumnData();
\r
32970 startRow = startRow || 0;
\r
32971 endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;
\r
32973 // records to render
\r
32974 var rs = ds.getRange(startRow, endRow);
\r
32976 return this.doRender(cs, rs, ds, startRow, colCount, stripe);
\r
32980 renderBody : function(){
\r
32981 var markup = this.renderRows();
\r
32982 return this.templates.body.apply({rows: markup});
\r
32986 refreshRow : function(record){
\r
32987 var ds = this.ds, index;
\r
32988 if(typeof record == 'number'){
\r
32990 record = ds.getAt(index);
\r
32992 index = ds.indexOf(record);
\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
33002 refresh : function(headersToo){
\r
33003 this.fireEvent("beforerefresh", this);
\r
33004 this.grid.stopEditing(true);
\r
33006 var result = this.renderBody();
\r
33007 this.mainBody.update(result);
\r
33009 if(headersToo === true){
\r
33010 this.updateHeaders();
\r
33011 this.updateHeaderSortState();
\r
33013 this.processRows(0, true);
\r
33015 this.applyEmptyText();
\r
33016 this.fireEvent("refresh", this);
\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
33027 updateHeaderSortState : function(){
\r
33028 var state = this.ds.getSortState();
\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
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
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
33051 Ext.menu.MenuMgr.unregister(this.hmenu);
\r
33052 this.hmenu.destroy();
\r
33053 delete this.hmenu;
\r
33055 if(this.grid.enableColumnMove){
\r
33056 var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
\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
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
33068 if(Ext.dd.DDM.locationCache[dd]){
\r
33069 delete Ext.dd.DDM.locationCache[dd];
\r
33072 delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
\r
33076 if(this.dragZone){
\r
33077 this.dragZone.unreg();
\r
33080 Ext.fly(this.innerHd).removeAllListeners();
\r
33081 Ext.removeNode(this.innerHd);
\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
33087 this.initData(null, null);
\r
33088 Ext.EventManager.removeResizeListener(this.onWindowResize, this);
\r
33089 this.purgeListeners();
\r
33093 onDenyColumnHide : function(){
\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
33107 this.fitColumns(true, true);
\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
33120 initData : function(ds, cm){
\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
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
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
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
33160 onDataChange : function(){
\r
33162 this.updateHeaderSortState();
\r
33163 this.syncFocusEl(0);
\r
33167 onClear : function(){
\r
33169 this.syncFocusEl(0);
\r
33173 onUpdate : function(ds, record){
\r
33174 this.refreshRow(record);
\r
33178 onAdd : function(ds, records, index){
\r
33179 this.insertRows(ds, index, index + (records.length-1));
\r
33183 onRemove : function(ds, record, index, isUpdate){
\r
33184 if(isUpdate !== true){
\r
33185 this.fireEvent("beforerowremoved", this, index, record);
\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
33196 onLoad : function(){
\r
33197 this.scrollToTop();
\r
33201 onColWidthChange : function(cm, col, width){
\r
33202 this.updateColumnWidth(col, width);
\r
33206 onHeaderChange : function(cm, col, text){
\r
33207 this.updateHeaders();
\r
33211 onHiddenChange : function(cm, col, hidden){
\r
33212 this.updateColumnHidden(col, hidden);
\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
33225 onColConfigChange : function(){
\r
33226 delete this.lastViewWidth;
\r
33227 this.indexMap = null;
\r
33228 this.refresh(true);
\r
33233 initUI : function(grid){
\r
33234 grid.on("headerclick", this.onHeaderClick, this);
\r
33238 initEvents : function(){
\r
33243 onHeaderClick : function(g, index){
\r
33244 if(this.headersDisabled || !this.cm.isSortable(index)){
\r
33247 g.stopEditing(true);
\r
33248 g.store.sort(this.cm.getDataIndex(index));
\r
33252 onRowOver : function(e, t){
\r
33254 if((row = this.findRowIndex(t)) !== false){
\r
33255 this.addRowClass(row, "x-grid3-row-over");
\r
33260 onRowOut : function(e, t){
\r
33262 if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
\r
33263 this.removeRowClass(row, "x-grid3-row-over");
\r
33268 handleWheel : function(e){
\r
33269 e.stopPropagation();
\r
33273 onRowSelect : function(row){
\r
33274 this.addRowClass(row, "x-grid3-row-selected");
\r
33278 onRowDeselect : function(row){
\r
33279 this.removeRowClass(row, "x-grid3-row-selected");
\r
33283 onCellSelect : function(row, col){
\r
33284 var cell = this.getCell(row, col);
\r
33286 this.fly(cell).addClass("x-grid3-cell-selected");
\r
33291 onCellDeselect : function(row, col){
\r
33292 var cell = this.getCell(row, col);
\r
33294 this.fly(cell).removeClass("x-grid3-cell-selected");
\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
33304 if(this.forceFit){
\r
33305 this.fitColumns(true, false, i);
\r
33306 this.updateAllColumnWidths();
\r
33308 this.updateColumnWidth(i, w);
\r
33309 this.syncHeaderScroll();
\r
33312 this.grid.fireEvent("columnresize", i, w);
\r
33316 handleHdMenuClick : function(item){
\r
33317 var index = this.hdCtxIndex;
\r
33318 var cm = this.cm, ds = this.ds;
\r
33321 ds.sort(cm.getDataIndex(index), "ASC");
\r
33324 ds.sort(cm.getDataIndex(index), "DESC");
\r
33327 index = cm.getIndexById(item.id.substr(4));
\r
33329 if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
\r
33330 this.onDenyColumnHide();
\r
33333 cm.setHidden(index, item.checked);
\r
33340 isHideableColumn : function(c){
\r
33341 return !c.hidden && !c.fixed;
\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
33362 handleHdDown : function(e, t){
\r
33363 if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
\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
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
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
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
33425 hasRows : function(){
\r
33426 var fc = this.mainBody.dom.firstChild;
\r
33427 return fc && fc.className != 'x-grid-empty';
\r
33431 bind : function(d, c){
\r
33432 this.initData(d, c);
\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
33448 this.scroll = false;
\r
33449 this.hw = this.view.splitHandleWidth || 5;
\r
33451 Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
\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
33472 handleMouseDown : function(e){
\r
33473 var t = this.view.findHeaderCell(e.getTarget());
\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
33480 }else if((x+w) - ex <= this.hw){
\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
33490 while(this.cm.isHidden(ci+adjust)){
\r
33492 if(ci+adjust < 0){
\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
33502 }else if(this.view.columnDrag){
\r
33503 this.view.columnDrag.callHandleMouseDown(e);
\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
33519 autoOffset : function(){
\r
33520 this.setDelta(0,0);
\r
33525 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
\r
33527 hideGroupedColumn:false,
\r
33529 showGroupName:true,
\r
33531 startCollapsed:false,
\r
33533 enableGrouping:true,
\r
33535 enableGroupingMenu:true,
\r
33537 enableNoGroups:true,
\r
33539 emptyGroupText : '(None)',
\r
33541 ignoreAdd: false,
\r
33543 groupTextTpl : '{text}',
\r
33551 initTemplates : function(){
\r
33552 Ext.grid.GroupingView.superclass.initTemplates.call(this);
\r
33555 var sm = this.grid.getSelectionModel();
\r
33556 sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
\r
33557 this.onBeforeRowSelect, this);
\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
33566 this.startGroup.compile();
\r
33567 this.endGroup = '</div></div>';
\r
33571 findGroup : function(el){
\r
33572 return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
\r
33576 getGroups : function(){
\r
33577 return this.hasRows() ? this.mainBody.dom.childNodes : [];
\r
33581 onAdd : function(){
\r
33582 if(this.enableGrouping && !this.ignoreAdd){
\r
33583 var ss = this.getScrollState();
\r
33585 this.restoreScroll(ss);
\r
33586 }else if(!this.enableGrouping){
\r
33587 Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
\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
33598 this.applyEmptyText();
\r
33602 refreshRow : function(record){
\r
33603 if(this.ds.getCount()==1){
\r
33606 this.isUpdating = true;
\r
33607 Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
\r
33608 this.isUpdating = false;
\r
33613 beforeMenuShow : function(){
\r
33614 var field = this.getGroupField();
\r
33615 var g = this.hmenu.items.get('groupBy');
\r
33617 g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
\r
33619 var s = this.hmenu.items.get('showGroups');
\r
33621 s.setDisabled(!field && this.cm.config[this.hdCtxIndex].groupable === false);
\r
33622 s.setChecked(!!field, true);
\r
33627 renderUI : function(){
\r
33628 Ext.grid.GroupingView.superclass.renderUI.call(this);
\r
33629 this.mainBody.on('mousedown', this.interceptMouse, this);
\r
33631 if(this.enableGroupingMenu && this.hmenu){
\r
33632 this.hmenu.add('-',{
\r
33634 text: this.groupByText,
\r
33635 handler: this.onGroupByClick,
\r
33637 iconCls:'x-group-by-icon'
\r
33639 if(this.enableNoGroups){
\r
33642 text: this.showGroupsText,
\r
33644 checkHandler: this.onShowGroupsClick,
\r
33648 this.hmenu.on('beforeshow', this.beforeMenuShow, this);
\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
33659 onShowGroupsClick : function(mi, checked){
\r
33661 this.onGroupByClick();
\r
33663 this.grid.store.clearGrouping();
\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
33675 this.state[gel.dom.id] = expanded;
\r
33676 gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
\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
33688 expandAllGroups : function(){
\r
33689 this.toggleAllGroups(true);
\r
33693 collapseAllGroups : function(){
\r
33694 this.toggleAllGroups(false);
\r
33698 interceptMouse : function(e){
\r
33699 var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
\r
33702 this.toggleGroup(hd.parentNode);
\r
33707 getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
\r
33708 var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
\r
33710 g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
\r
33716 getGroupField : function(){
\r
33717 return this.grid.store.getGroupState();
\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
33742 return Ext.grid.GroupingView.superclass.renderRows.apply(
\r
33743 this, arguments);
\r
33747 doRender : function(cs, rs, ds, startRow, colCount, stripe){
\r
33748 if(rs.length < 1){
\r
33751 var groupField = this.getGroupField();
\r
33752 var colIndex = this.cm.findColumnIndex(groupField);
\r
33754 this.enableGrouping = !!groupField;
\r
33756 if(!this.enableGrouping || this.isUpdating){
\r
33757 return Ext.grid.GroupingView.superclass.doRender.apply(
\r
33758 this, arguments);
\r
33760 var gstyle = 'width:'+this.getTotalWidth()+';';
\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
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
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
33783 text: prefix + g,
\r
33785 startRow: rowIndex,
\r
33790 groups.push(curGroup);
\r
33792 curGroup.rs.push(r);
\r
33794 r._groupId = gid;
\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
33804 this.doGroupEnd(buf, g, cs, ds, colCount);
\r
33806 return buf.join('');
\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
33821 doGroupStart : function(buf, g, cs, ds, colCount){
\r
33822 buf[buf.length] = this.startGroup.apply(g);
\r
33826 doGroupEnd : function(buf, g, cs, ds, colCount){
\r
33827 buf[buf.length] = this.endGroup;
\r
33831 getRows : function(){
\r
33832 if(!this.enableGrouping){
\r
33833 return Ext.grid.GroupingView.superclass.getRows.call(this);
\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
33847 updateGroupWidths : function(){
\r
33848 if(!this.enableGrouping || !this.hasRows()){
\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
33859 onColumnWidthUpdated : function(col, w, tw){
\r
33860 Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
\r
33861 this.updateGroupWidths();
\r
33865 onAllColumnWidthsUpdated : function(ws, tw){
\r
33866 Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
\r
33867 this.updateGroupWidths();
\r
33871 onColumnHiddenUpdated : function(col, hidden, tw){
\r
33872 Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
\r
33873 this.updateGroupWidths();
\r
33877 onLayout : function(){
\r
33878 this.updateGroupWidths();
\r
33882 onBeforeRowSelect : function(sm, rowIndex){
\r
33883 if(!this.enableGrouping){
\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
33894 groupByText: 'Group By This Field',
\r
33896 showGroupsText: 'Show in Groups'
\r
33899 Ext.grid.GroupingView.GROUP_ID = 1000;
\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
33908 this.setHandleElId(Ext.id(hd));
\r
33909 this.setOuterHandleElId(Ext.id(hd2));
\r
33911 this.scroll = false;
\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
33919 return {ddel: h.firstChild, header:h};
\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
33933 afterValidDrop : function(){
\r
33934 var v = this.view;
\r
33935 setTimeout(function(){
\r
33936 v.headersDisabled = false;
\r
33940 afterInvalidDrop : function(){
\r
33941 var v = this.view;
\r
33942 setTimeout(function(){
\r
33943 v.headersDisabled = false;
\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:" "
\r
33957 this.proxyBottom = Ext.DomHelper.append(document.body, {
\r
33958 cls:"col-move-bottom", html:" "
\r
33960 this.proxyTop.hide = this.proxyBottom.hide = function(){
\r
33961 this.setLeftTop(-100,-100);
\r
33962 this.setStyle("visibility", "hidden");
\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
33969 Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
\r
33970 proxyOffsets : [-4, -9],
\r
33971 fly: Ext.Element.fly,
\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
33981 nextVisible : function(h){
\r
33982 var v = this.view, cm = this.grid.colModel;
\r
33983 h = h.nextSibling;
\r
33985 if(!cm.isHidden(v.getCellIndex(h))){
\r
33988 h = h.nextSibling;
\r
33993 prevVisible : function(h){
\r
33994 var v = this.view, cm = this.grid.colModel;
\r
33995 h = h.prevSibling;
\r
33997 if(!cm.isHidden(v.getCellIndex(h))){
\r
34000 h = h.prevSibling;
\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
34016 var oldIndex = this.view.getCellIndex(h);
\r
34017 var newIndex = this.view.getCellIndex(n);
\r
34019 if(this.grid.colModel.isFixed(newIndex)){
\r
34023 var locked = this.grid.colModel.isLocked(newIndex);
\r
34025 if(pt == "after"){
\r
34028 if(oldIndex < newIndex){
\r
34031 if(oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))){
\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
34040 this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
\r
34041 this.proxyBottom.show();
\r
34045 onNodeEnter : function(n, dd, e, data){
\r
34046 if(data.header != n){
\r
34047 this.positionIndicator(data.header, n, e);
\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
34057 this.proxyTop.hide();
\r
34058 this.proxyBottom.hide();
\r
34060 return result ? this.dropAllowed : this.dropNotAllowed;
\r
34063 onNodeOut : function(n, dd, e, data){
\r
34064 this.proxyTop.hide();
\r
34065 this.proxyBottom.hide();
\r
34068 onNodeDrop : function(n, dd, e, data){
\r
34069 var h = data.header;
\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
34081 if(oldIndex < newIndex){
\r
34084 if(oldIndex == newIndex && (locked == cm.isLocked(oldIndex))){
\r
34087 cm.setLocked(oldIndex, locked, true);
\r
34088 cm.moveColumn(oldIndex, newIndex);
\r
34089 this.grid.fireEvent("columnmove", oldIndex, newIndex);
\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
34102 Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
\r
34103 handleMouseDown : function(e){
\r
34107 callHandleMouseDown : function(e){
\r
34108 Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
\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
34121 this.setHandleElId(Ext.id(hd));
\r
34122 this.setOuterHandleElId(Ext.id(hd2));
\r
34123 this.scroll = false;
\r
34125 Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
\r
34126 fly: Ext.Element.fly,
\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
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
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
34163 autoOffset : function(){
\r
34164 this.setDelta(0,0);
\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
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
34181 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
\r
34182 ddGroup : "GridDD",
\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
34193 return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
\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
34207 afterRepair : function(){
\r
34208 this.dragging = false;
\r
34212 getRepairXY : function(e, data){
\r
34216 onEndDrag : function(data, e){
\r
34217 // fire end drag?
\r
34220 onValidDrop : function(dd, e, id){
\r
34221 // fire drag drop?
\r
34222 this.hideProxy();
\r
34225 beforeInvalidDrop : function(e, id){
\r
34231 Ext.grid.ColumnModel = function(config){
\r
34233 this.defaultWidth = 100;
\r
34236 this.defaultSortable = false;
\r
34239 if(config.columns){
\r
34240 Ext.apply(this, config);
\r
34241 this.setConfig(config.columns, true);
\r
34243 this.setConfig(config, true);
\r
34254 // deprecated - to be removed
\r
34255 "columnlockchange",
\r
34259 Ext.grid.ColumnModel.superclass.constructor.call(this);
\r
34261 Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
\r
34279 getColumnId : function(index){
\r
34280 return this.config[index].id;
\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
34290 c.editor.destroy();
\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
34302 if(typeof c.id == "undefined"){
\r
34305 if(c.editor && c.editor.isFormField){
\r
34306 c.editor = new Ext.grid.GridEditor(c.editor);
\r
34308 this.lookup[c.id] = c;
\r
34311 this.fireEvent('configchange', this);
\r
34316 getColumnById : function(id){
\r
34317 return this.lookup[id];
\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
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
34339 // deprecated - to be removed
\r
34340 isLocked : function(colIndex){
\r
34341 return this.config[colIndex].locked === true;
\r
34344 // deprecated - to be removed
\r
34345 setLocked : function(colIndex, value, suppressEvent){
\r
34346 if(this.isLocked(colIndex) == value){
\r
34349 this.config[colIndex].locked = value;
\r
34350 if(!suppressEvent){
\r
34351 this.fireEvent("columnlockchange", this, colIndex, value);
\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
34363 return totalWidth;
\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
34376 getColumnCount : function(visibleOnly){
\r
34377 if(visibleOnly === true){
\r
34379 for(var i = 0, len = this.config.length; i < len; i++){
\r
34380 if(!this.isHidden(i)){
\r
34386 return this.config.length;
\r
34390 getColumnsBy : function(fn, scope){
\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
34402 isSortable : function(col){
\r
34403 if(typeof this.config[col].sortable == "undefined"){
\r
34404 return this.defaultSortable;
\r
34406 return this.config[col].sortable;
\r
34410 isMenuDisabled : function(col){
\r
34411 return !!this.config[col].menuDisabled;
\r
34415 getRenderer : function(col){
\r
34416 if(!this.config[col].renderer){
\r
34417 return Ext.grid.ColumnModel.defaultRenderer;
\r
34419 return this.config[col].renderer;
\r
34423 setRenderer : function(col, fn){
\r
34424 this.config[col].renderer = fn;
\r
34428 getColumnWidth : function(col){
\r
34429 return this.config[col].width || this.defaultWidth;
\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
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
34451 return this.totalWidth;
\r
34455 getColumnHeader : function(col){
\r
34456 return this.config[col].header;
\r
34460 setColumnHeader : function(col, header){
\r
34461 this.config[col].header = header;
\r
34462 this.fireEvent("headerchange", this, col, header);
\r
34466 getColumnTooltip : function(col){
\r
34467 return this.config[col].tooltip;
\r
34470 setColumnTooltip : function(col, tooltip){
\r
34471 this.config[col].tooltip = tooltip;
\r
34475 getDataIndex : function(col){
\r
34476 return this.config[col].dataIndex;
\r
34480 setDataIndex : function(col, dataIndex){
\r
34481 this.config[col].dataIndex = dataIndex;
\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
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
34501 getCellEditor : function(colIndex, rowIndex){
\r
34502 return this.config[colIndex].editor;
\r
34506 setEditable : function(col, editable){
\r
34507 this.config[col].editable = editable;
\r
34512 isHidden : function(colIndex){
\r
34513 return this.config[colIndex].hidden;
\r
34518 isFixed : function(colIndex){
\r
34519 return this.config[colIndex].fixed;
\r
34523 isResizable : function(colIndex){
\r
34524 return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
\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
34537 setEditor : function(col, editor){
\r
34538 this.config[col].editor = editor;
\r
34543 Ext.grid.ColumnModel.defaultRenderer = function(value){
\r
34544 if(typeof value == "string" && value.length < 1){
\r
34550 // Alias for backwards compatibility
\r
34551 Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;
\r
34553 Ext.grid.AbstractSelectionModel = function(){
\r
34554 this.locked = false;
\r
34555 Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
\r
34558 Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable, {
\r
34560 init : function(grid){
\r
34561 this.grid = grid;
\r
34562 this.initEvents();
\r
34566 lock : function(){
\r
34567 this.locked = true;
\r
34571 unlock : function(){
\r
34572 this.locked = false;
\r
34576 isLocked : function(){
\r
34577 return this.locked;
\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
34587 this.last = false;
\r
34588 this.lastActive = false;
\r
34592 "selectionchange",
\r
34594 "beforerowselect",
\r
34601 Ext.grid.RowSelectionModel.superclass.constructor.call(this);
\r
34604 Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel, {
\r
34606 singleSelect : false,
\r
34610 initEvents : function(){
\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
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
34635 this.selectFirstRow();
\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
34649 this.selectFirstRow();
\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
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
34668 if((index = ds.indexOfId(r.id)) != -1){
\r
34669 this.selectRow(index, true);
\r
34672 if(s.length != this.selections.getCount()){
\r
34673 this.fireEvent("selectionchange", this);
\r
34678 onRemove : function(v, index, r){
\r
34679 if(this.selections.remove(r) !== false){
\r
34680 this.fireEvent('selectionchange', this);
\r
34685 onRowUpdated : function(v, index, r){
\r
34686 if(this.isSelected(r)){
\r
34687 v.onRowSelect(index);
\r
34692 selectRecords : function(records, keepExisting){
\r
34693 if(!keepExisting){
\r
34694 this.clearSelections();
\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
34703 getCount : function(){
\r
34704 return this.selections.length;
\r
34708 selectFirstRow : function(){
\r
34709 this.selectRow(0);
\r
34713 selectLastRow : function(keepExisting){
\r
34714 this.selectRow(this.grid.store.getCount() - 1, keepExisting);
\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
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
34738 hasNext : function(){
\r
34739 return this.last !== false && (this.last+1) < this.grid.store.getCount();
\r
34743 hasPrevious : function(){
\r
34744 return !!this.last;
\r
34749 getSelections : function(){
\r
34750 return [].concat(this.selections.items);
\r
34754 getSelected : function(){
\r
34755 return this.selections.itemAt(0);
\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
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
34780 this.selections.clear();
\r
34782 this.last = false;
\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
34796 hasSelection : function(){
\r
34797 return this.selections.length > 0;
\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
34807 isIdSelected : function(id){
\r
34808 return (this.selections.key(id) ? true : false);
\r
34812 handleMouseDown : function(g, rowIndex, e){
\r
34813 if(e.button !== 0 || this.isLocked()){
\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
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
34834 selectRows : function(rows, keepExisting){
\r
34835 if(!keepExisting){
\r
34836 this.clearSelections();
\r
34838 for(var i = 0, len = rows.length; i < len; i++){
\r
34839 this.selectRow(rows[i], true);
\r
34844 selectRange : function(startRow, endRow, keepExisting){
\r
34845 if(this.isLocked()) return;
\r
34846 if(!keepExisting){
\r
34847 this.clearSelections();
\r
34849 if(startRow <= endRow){
\r
34850 for(var i = startRow; i <= endRow; i++){
\r
34851 this.selectRow(i, true);
\r
34854 for(var i = startRow; i >= endRow; i--){
\r
34855 this.selectRow(i, true);
\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
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
34876 this.selections.add(r);
\r
34877 this.last = this.lastActive = index;
\r
34878 if(!preventViewNotify){
\r
34879 this.grid.getView().onRowSelect(index);
\r
34881 this.fireEvent("rowselect", this, index, r);
\r
34882 this.fireEvent("selectionchange", this);
\r
34887 deselectRow : function(index, preventViewNotify){
\r
34888 if(this.isLocked()) return;
\r
34889 if(this.last == index){
\r
34890 this.last = false;
\r
34892 if(this.lastActive == index){
\r
34893 this.lastActive = false;
\r
34895 var r = this.grid.store.getAt(index);
\r
34897 this.selections.remove(r);
\r
34898 if(!preventViewNotify){
\r
34899 this.grid.getView().onRowDeselect(index);
\r
34901 this.fireEvent("rowdeselect", this, index, r);
\r
34902 this.fireEvent("selectionchange", this);
\r
34907 restoreLast : function(){
\r
34909 this.last = this._last;
\r
34914 acceptsNav : function(row, col, cm){
\r
34915 return !cm.isHidden(col) && cm.isCellEditable(col, row);
\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
34924 ed.completeEdit();
\r
34926 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
\r
34928 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
\r
34930 }else if(k == e.ENTER){
\r
34932 ed.completeEdit();
\r
34933 if(this.moveEditorOnEnter !== false){
\r
34935 newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
\r
34937 newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
\r
34940 }else if(k == e.ESC){
\r
34944 g.startEditing(newCell[0], newCell[1]);
\r
34949 Ext.grid.CellSelectionModel = function(config){
\r
34950 Ext.apply(this, config);
\r
34952 this.selection = null;
\r
34956 "beforecellselect",
\r
34960 "selectionchange"
\r
34963 Ext.grid.CellSelectionModel.superclass.constructor.call(this);
\r
34966 Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel, {
\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
34983 beforeEdit : function(e){
\r
34984 this.select(e.row, e.column, false, true, e.record);
\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
34995 onViewChange : function(){
\r
34996 this.clearSelections(true);
\r
35000 getSelectedCell : function(){
\r
35001 return this.selection ? this.selection.cell : null;
\r
35005 clearSelections : function(preventNotify){
\r
35006 var s = this.selection;
\r
35008 if(preventNotify !== true){
\r
35009 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
\r
35011 this.selection = null;
\r
35012 this.fireEvent("selectionchange", this, null);
\r
35017 hasSelection : function(){
\r
35018 return this.selection ? true : false;
\r
35022 handleMouseDown : function(g, row, cell, e){
\r
35023 if(e.button !== 0 || this.isLocked()){
\r
35026 this.select(row, cell);
\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
35036 cell : [rowIndex, colIndex]
\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
35045 this.fireEvent("cellselect", this, rowIndex, colIndex);
\r
35046 this.fireEvent("selectionchange", this, this.selection);
\r
35051 isSelectable : function(rowIndex, colIndex, cm){
\r
35052 return !cm.isHidden(colIndex);
\r
35056 handleKeyDown : function(e){
\r
35057 if(!e.isNavKeyPress()){
\r
35060 var g = this.grid, s = this.selection;
\r
35063 var cell = g.walkCells(0, 0, 1, this.isSelectable, this);
\r
35065 this.select(cell[0], cell[1]);
\r
35070 var walk = function(row, col, step){
\r
35071 return g.walkCells(row, col, step, sm.isSelectable, sm);
\r
35073 var k = e.getKey(), r = s.cell[0], c = s.cell[1];
\r
35079 newCell = walk(r, c-1, -1);
\r
35081 newCell = walk(r, c+1, 1);
\r
35085 newCell = walk(r+1, c, 1);
\r
35088 newCell = walk(r-1, c, -1);
\r
35091 newCell = walk(r, c+1, 1);
\r
35094 newCell = walk(r, c-1, -1);
\r
35097 if(g.isEditor && !g.editing){
\r
35098 g.startEditing(r, c);
\r
35105 this.select(newCell[0], newCell[1]);
\r
35110 acceptsNav : function(row, col, cm){
\r
35111 return !cm.isHidden(col) && cm.isCellEditable(col, row);
\r
35114 onEditorKey : function(field, e){
\r
35115 var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
\r
35118 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
\r
35120 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
\r
35123 }else if(k == e.ENTER){
\r
35124 ed.completeEdit();
\r
35126 }else if(k == e.ESC){
\r
35131 g.startEditing(newCell[0], newCell[1]);
\r
35136 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
\r
35143 detectEdit: false,
\r
35146 autoEncode : false,
\r
35150 trackMouseOver: false, // causes very odd FF errors
\r
35153 initComponent : function(){
\r
35154 Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
\r
35156 if(!this.selModel){
\r
35158 this.selModel = new Ext.grid.CellSelectionModel();
\r
35161 this.activeEditor = null;
\r
35174 initEvents : function(){
\r
35175 Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
\r
35177 this.on("bodyscroll", this.stopEditing, this, [true]);
\r
35178 this.on("columnresize", this.stopEditing, this, [true]);
\r
35180 if(this.clicksToEdit == 1){
\r
35181 this.on("cellclick", this.onCellDblClick, this);
\r
35183 if(this.clicksToEdit == 'auto' && this.view.mainBody){
\r
35184 this.view.mainBody.on("mousedown", this.onAutoEditClick, this);
\r
35186 this.on("celldblclick", this.onCellDblClick, this);
\r
35191 onCellDblClick : function(g, row, col){
\r
35192 this.startEditing(row, col);
\r
35196 onAutoEditClick : function(e, t){
\r
35197 if(e.button !== 0){
\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
35210 if(this.selModel.isSelected(row)){
\r
35211 this.startEditing(row, col);
\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
35230 originalValue: startValue,
\r
35236 if(this.fireEvent("validateedit", e) !== false && !e.cancel){
\r
35237 r.set(field, e.value);
\r
35239 this.fireEvent("afteredit", e);
\r
35242 this.view.focusCell(ed.row, ed.col);
\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
35256 value: r.data[field],
\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
35267 (function(){ // complex but required for focus issues in safari, ie and opera
\r
35271 ed.on("complete", this.onEditComplete, this, {single: true});
\r
35272 ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
\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
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
35289 postEditValue : function(value, originalValue, r, field){
\r
35290 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
\r
35294 stopEditing : function(cancel){
\r
35295 if(this.activeEditor){
\r
35296 this.activeEditor[cancel === true ? 'cancelEdit' : 'completeEdit']();
\r
35298 this.activeEditor = null;
\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
35307 Ext.destroy(c.editor);
\r
35310 Ext.grid.EditorGridPanel.superclass.onDestroy.call(this);
\r
35313 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
\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
35321 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
\r
35322 alignment: "tl-tl",
\r
35323 autoSize: "width",
\r
35325 cls: "x-small-editor x-grid-editor",
\r
35330 Ext.grid.PropertyRecord = Ext.data.Record.create([
\r
35331 {name:'name',type:'string'}, 'value'
\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
35340 this.store.on('update', this.onUpdate, this);
\r
35342 this.setSource(source);
\r
35344 Ext.grid.PropertyStore.superclass.constructor.call(this);
\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
35350 this.store.removeAll();
\r
35353 if(this.isEditableValue(o[k])){
\r
35354 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
\r
35357 this.store.loadRecords({records: data}, {}, true);
\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
35368 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
\r
35376 getProperty : function(row){
\r
35377 return this.store.getAt(row);
\r
35381 isEditableValue: function(val){
\r
35382 if(Ext.isDate(val)){
\r
35384 }else if(typeof val == 'object' || typeof val == 'function'){
\r
35391 setValue : function(prop, value){
\r
35392 this.source[prop] = value;
\r
35393 this.store.getById(prop).set('value', value);
\r
35396 // protected - should only be called by the grid. Use grid.getSource instead.
\r
35397 getSource : function(){
\r
35398 return this.source;
\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
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
35417 var f = Ext.form;
\r
35419 var bfield = new f.Field({
\r
35421 bselect : this.bselect,
\r
35423 getValue : function(){
\r
35424 return this.bselect.value == 'true';
\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
35433 this.renderCellDelegate = this.renderCell.createDelegate(this);
\r
35434 this.renderPropDelegate = this.renderProp.createDelegate(this);
\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
35444 renderDate : function(dateVal){
\r
35445 return dateVal.dateFormat(this.dateFormat);
\r
35449 renderBool : function(bVal){
\r
35450 return bVal ? 'true' : 'false';
\r
35454 isCellEditable : function(colIndex, rowIndex){
\r
35455 return colIndex == 1;
\r
35459 getRenderer : function(col){
\r
35460 return col == 1 ?
\r
35461 this.renderCellDelegate : this.renderPropDelegate;
\r
35465 renderProp : function(v){
\r
35466 return this.getPropertyName(v);
\r
35470 renderCell : function(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
35477 return Ext.util.Format.htmlEncode(rv);
\r
35481 getPropertyName : function(name){
\r
35482 var pn = this.grid.propertyNames;
\r
35483 return pn && pn[name] ? pn[name] : name;
\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
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
35500 return this.editors['string'];
\r
35506 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
\r
35511 // private config overrides
\r
35512 enableColumnMove:false,
\r
35513 stripeRows:false,
\r
35514 trackMouseOver: false,
\r
35516 enableHdMenu : false,
\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
35531 'beforepropertychange',
\r
35536 this.ds = store.store;
\r
35537 Ext.grid.PropertyGrid.superclass.initComponent.call(this);
\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
35548 onRender : function(){
\r
35549 Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
\r
35551 this.getGridEl().addClass('x-props-grid');
\r
35555 afterRender: function(){
\r
35556 Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
\r
35558 this.setSource(this.source);
\r
35563 setSource : function(source){
\r
35564 this.propStore.setSource(source);
\r
35568 getSource : function(){
\r
35569 return this.propStore.getSource();
\r
35572 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
\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
35582 Ext.grid.RowNumberer.prototype = {
\r
35592 menuDisabled:true,
\r
35595 rowspan: undefined,
\r
35598 renderer : function(v, p, record, rowIndex){
\r
35599 if(this.rowspan){
\r
35600 p.cellAttr = 'rowspan="'+this.rowspan+'"';
\r
35602 return rowIndex+1;
\r
35606 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
\r
35608 header: '<div class="x-grid3-hd-checker"> </div>',
\r
35615 menuDisabled:true,
\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
35632 onMouseDown : function(e, t){
\r
35633 if(e.button === 0 && t.className == 'x-grid3-row-checker'){ // Only fire if left-click
\r
35635 var row = e.getTarget('.x-grid3-row');
\r
35637 var index = row.rowIndex;
\r
35638 if(this.isSelected(index)){
\r
35639 this.deselectRow(index);
\r
35641 this.selectRow(index, true);
\r
35648 onHdMouseDown : function(e, t){
\r
35649 if(t.className == 'x-grid3-hd-checker'){
\r
35651 var hd = Ext.fly(t.parentNode);
\r
35652 var isChecked = hd.hasClass('x-grid3-hd-checker-on');
\r
35654 hd.removeClass('x-grid3-hd-checker-on');
\r
35655 this.clearSelections();
\r
35657 hd.addClass('x-grid3-hd-checker-on');
\r
35658 this.selectAll();
\r
35664 renderer : function(v, p, record){
\r
35665 return '<div class="x-grid3-row-checker"> </div>';
\r
35669 Ext.LoadMask = function(el, config){
\r
35670 this.el = Ext.get(el);
\r
35671 Ext.apply(this, config);
\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
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
35687 Ext.LoadMask.prototype = {
\r
35691 msg : 'Loading...',
\r
35693 msgCls : 'x-mask-loading',
\r
35699 disable : function(){
\r
35700 this.disabled = true;
\r
35704 enable : function(){
\r
35705 this.disabled = false;
\r
35709 onLoad : function(){
\r
35710 this.el.unmask(this.removeMask);
\r
35714 onBeforeLoad : function(){
\r
35715 if(!this.disabled){
\r
35716 this.el.mask(this.msg, this.msgCls);
\r
35721 show: function(){
\r
35722 this.onBeforeLoad();
\r
35726 hide: function(){
\r
35731 destroy : function(){
\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
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
35745 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
\r
35747 baseCls : 'x-progress',
\r
35753 waitTimer : null,
\r
35756 initComponent : function(){
\r
35757 Ext.ProgressBar.superclass.initComponent.call(this);
\r
35765 onRender : function(ct, position){
\r
35766 Ext.ProgressBar.superclass.onRender.call(this, ct, position);
\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> </div>',
\r
35776 '<div class="{cls}-text {cls}-text-back">',
\r
35777 '<div> </div>',
\r
35784 this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
\r
35786 this.el = tpl.append(ct, {cls: this.baseCls}, true);
\r
35789 this.el.dom.id = this.id;
\r
35791 var inner = this.el.dom.firstChild;
\r
35792 this.progressBar = Ext.get(inner.firstChild);
\r
35795 //use an external text el
\r
35796 this.textEl = Ext.get(this.textEl);
\r
35797 delete this.textTopEl;
\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
35806 this.progressBar.setHeight(inner.offsetHeight);
\r
35810 afterRender : function(){
\r
35811 Ext.ProgressBar.superclass.afterRender.call(this);
\r
35813 this.updateProgress(this.value, this.text);
\r
35815 this.updateText(this.text);
\r
35820 updateProgress : function(value, text, animate){
\r
35821 this.value = value || 0;
\r
35823 this.updateText(text);
\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
35833 this.fireEvent('update', this, value, text);
\r
35838 wait : function(o){
\r
35839 if(!this.waitTimer){
\r
35840 var scope = this;
\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
35848 interval: o.interval || 1000,
\r
35849 duration: o.duration,
\r
35850 onStop: function(){
\r
35852 o.fn.apply(o.scope || this);
\r
35863 isWaiting : function(){
\r
35864 return this.waitTimer != null;
\r
35868 updateText : function(text){
\r
35869 this.text = text || ' ';
\r
35870 if(this.rendered){
\r
35871 this.textEl.update(this.text);
\r
35877 syncProgressBar : function(){
\r
35879 this.updateProgress(this.value, this.text);
\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
35891 this.syncProgressBar();
\r
35896 reset : function(hide){
\r
35897 this.updateProgress(0);
\r
35898 if(this.textTopEl){
\r
35899 this.textTopEl.addClass('x-hidden');
\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
35906 if(hide === true){
\r
35912 Ext.reg('progress', Ext.ProgressBar);
\r
35914 Ext.Slider = Ext.extend(Ext.BoxComponent, {
\r
35927 clickRange: [5,15],
\r
35929 clickToChange : true,
\r
35936 // private override
\r
35937 initComponent : function(){
\r
35938 if(this.value === undefined){
\r
35939 this.value = this.minValue;
\r
35941 Ext.Slider.superclass.initComponent.call(this);
\r
35942 this.keyIncrement = Math.max(this.increment, this.keyIncrement);
\r
35949 'changecomplete',
\r
35958 if(this.vertical){
\r
35959 Ext.apply(this, Ext.Slider.Vertical);
\r
35963 // private override
\r
35964 onRender : function(){
\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
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
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
35984 this.focusEl.swallowEvent("click", true);
\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
35994 this.tracker.initEl(this.thumb);
\r
35995 this.on('beforedestroy', this.tracker.destroy, this.tracker);
\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
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
36016 onKeyDown : function(e){
\r
36017 if(this.disabled){e.preventDefault();return;}
\r
36018 var k = e.getKey();
\r
36024 this.setValue(this.maxValue, undefined, true);
\r
36026 this.setValue(this.value+this.keyIncrement, undefined, true);
\r
36033 this.setValue(this.minValue, undefined, true);
\r
36035 this.setValue(this.value-this.keyIncrement, undefined, true);
\r
36039 e.preventDefault();
\r
36044 doSnap : function(value){
\r
36045 if(!this.increment || this.increment == 1 || !value) {
\r
36048 var newValue = value, inc = this.increment;
\r
36049 var m = value % inc;
\r
36052 newValue = value + (inc-m);
\r
36054 newValue = value - m;
\r
36057 return newValue.constrain(this.minValue, this.maxValue);
\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
36069 this.moveThumb(this.translateValue(v), false);
\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
36082 normalizeValue : function(v){
\r
36083 if(typeof v != 'number'){
\r
36086 v = Math.round(v);
\r
36087 v = this.doSnap(v);
\r
36088 v = v.constrain(this.minValue, this.maxValue);
\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
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
36106 translateValue : function(v){
\r
36107 var ratio = this.getRatio();
\r
36108 return (v * ratio)-(this.minValue * ratio)-this.halfThumb;
\r
36111 reverseValue : function(pos){
\r
36112 var ratio = this.getRatio();
\r
36113 return (pos+this.halfThumb+(this.minValue * ratio))/ratio;
\r
36117 moveThumb: function(v, animate){
\r
36118 if(!animate || this.animate === false){
\r
36119 this.thumb.setLeft(v);
\r
36121 this.thumb.shift({left: v, stopFx: true, duration:.35});
\r
36126 focus : function(){
\r
36127 this.focusEl.focus(10);
\r
36131 onBeforeDragStart : function(e){
\r
36132 return !this.disabled;
\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
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
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
36161 onDisable: function(){
\r
36162 Ext.Slider.superclass.onDisable.call(this);
\r
36163 this.thumb.addClass(this.disabledClass);
\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
36173 this.thumbHolder.show().setXY(xy);
\r
36178 onEnable: function(){
\r
36179 Ext.Slider.superclass.onEnable.call(this);
\r
36180 this.thumb.removeClass(this.disabledClass);
\r
36182 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
\r
36183 if (this.thumbHolder){
\r
36184 this.thumbHolder.hide();
\r
36186 this.thumb.show();
\r
36187 this.syncThumb();
\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
36198 syncThumb : function(){
\r
36199 if(this.rendered){
\r
36200 this.moveThumb(this.translateValue(this.value));
\r
36205 getValue : function(){
\r
36206 return this.value;
\r
36209 Ext.reg('slider', Ext.Slider);
\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
36218 getRatio : function(){
\r
36219 var h = this.innerEl.getHeight();
\r
36220 var v = this.maxValue - this.minValue;
\r
36224 moveThumb: function(v, animate){
\r
36225 if(!animate || this.animate === false){
\r
36226 this.thumb.setBottom(v);
\r
36228 this.thumb.shift({bottom: v, stopFx: true, duration:.35});
\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
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
36247 Ext.StatusBar = Ext.extend(Ext.Toolbar, {
\r
36255 cls : 'x-statusbar',
\r
36257 busyIconCls : 'x-status-busy',
\r
36259 busyText : 'Loading...',
\r
36261 autoClear : 5000,
\r
36264 activeThreadId : 0,
\r
36267 initComponent : function(){
\r
36268 if(this.statusAlign=='right'){
\r
36269 this.cls += ' x-status-right';
\r
36271 Ext.StatusBar.superclass.initComponent.call(this);
\r
36275 afterRender : function(){
\r
36276 Ext.StatusBar.superclass.afterRender.call(this);
\r
36278 var right = this.statusAlign=='right',
\r
36279 td = Ext.get(this.nextBlock());
\r
36282 this.tr.appendChild(td.dom);
\r
36284 td.insertBefore(this.tr.firstChild);
\r
36287 this.statusEl = td.createChild({
\r
36288 cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''),
\r
36289 html: this.text || this.defaultText || ''
\r
36291 this.statusEl.unselectable();
\r
36293 this.spacerEl = td.insertSibling({
\r
36295 style: 'width:100%',
\r
36296 cn: [{cls:'ytb-spacer'}]
\r
36297 }, right ? 'before' : 'after');
\r
36301 setStatus : function(o){
\r
36304 if(typeof o == 'string'){
\r
36307 if(o.text !== undefined){
\r
36308 this.setText(o.text);
\r
36310 if(o.iconCls !== undefined){
\r
36311 this.setIcon(o.iconCls);
\r
36316 wait = this.autoClear,
\r
36317 defaults = {useDefaults: true, anim: true};
\r
36319 if(typeof c == 'object'){
\r
36320 c = Ext.applyIf(c, defaults);
\r
36324 }else if(typeof c == 'number'){
\r
36327 }else if(typeof c == 'boolean'){
\r
36331 c.threadId = this.activeThreadId;
\r
36332 this.clearStatus.defer(wait, this, [c]);
\r
36338 clearStatus : function(o){
\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
36348 var text = o.useDefaults ? this.defaultText : '',
\r
36349 iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';
\r
36352 this.statusEl.fadeOut({
\r
36354 useDisplay: true,
\r
36356 callback: function(){
\r
36361 this.statusEl.show();
\r
36365 // hide/show the el to avoid jumpy text or icon
\r
36366 this.statusEl.hide();
\r
36371 this.statusEl.show();
\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
36387 getText : function(){
\r
36388 return this.text;
\r
36392 setIcon : function(cls){
\r
36393 this.activeThreadId++;
\r
36396 if(this.rendered){
\r
36397 if(this.currIconCls){
\r
36398 this.statusEl.removeClass(this.currIconCls);
\r
36399 this.currIconCls = null;
\r
36401 if(cls.length > 0){
\r
36402 this.statusEl.addClass(cls);
\r
36403 this.currIconCls = cls;
\r
36406 this.currIconCls = cls;
\r
36412 showBusy : function(o){
\r
36413 if(typeof o == 'string'){
\r
36416 o = Ext.applyIf(o || {}, {
\r
36417 text: this.busyText,
\r
36418 iconCls: this.busyIconCls
\r
36420 return this.setStatus(o);
\r
36423 Ext.reg('statusbar', Ext.StatusBar);
\r
36426 Ext.History = (function () {
\r
36427 var iframe, hiddenField;
\r
36428 var ready = false;
\r
36429 var currentToken;
\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
36436 function doSave() {
\r
36437 hiddenField.value = currentToken;
\r
36440 function handleStateChange(token) {
\r
36441 currentToken = token;
\r
36442 Ext.History.fireEvent('change', token);
\r
36445 function updateIFrame (token) {
\r
36446 var html = ['<html><body><div id="state">',token,'</div></body></html>'].join('');
\r
36448 var doc = iframe.contentWindow.document;
\r
36458 function checkIFrame() {
\r
36459 if (!iframe.contentWindow || !iframe.contentWindow.document) {
\r
36460 setTimeout(checkIFrame, 10);
\r
36464 var doc = iframe.contentWindow.document;
\r
36465 var elem = doc.getElementById("state");
\r
36466 var token = elem ? elem.innerText : null;
\r
36468 var hash = getHash();
\r
36470 setInterval(function () {
\r
36472 doc = iframe.contentWindow.document;
\r
36473 elem = doc.getElementById("state");
\r
36475 var newtoken = elem ? elem.innerText : null;
\r
36477 var newHash = getHash();
\r
36479 if (newtoken !== token) {
\r
36480 token = newtoken;
\r
36481 handleStateChange(token);
\r
36482 top.location.hash = token;
\r
36485 } else if (newHash !== hash) {
\r
36487 updateIFrame(newHash);
\r
36494 Ext.History.fireEvent('ready', Ext.History);
\r
36497 function startUp() {
\r
36498 currentToken = hiddenField.value ? hiddenField.value : getHash();
\r
36503 var hash = getHash();
\r
36504 setInterval(function () {
\r
36505 var newHash = getHash();
\r
36506 if (newHash !== hash) {
\r
36508 handleStateChange(hash);
\r
36513 Ext.History.fireEvent('ready', Ext.History);
\r
36519 fieldId: 'x-history-field',
\r
36521 iframeId: 'x-history-frame',
\r
36526 init: function (onReady, scope) {
\r
36528 Ext.callback(onReady, scope, [this]);
\r
36531 if(!Ext.isReady){
\r
36532 Ext.onReady(function(){
\r
36533 Ext.History.init(onReady, scope);
\r
36537 hiddenField = Ext.getDom(Ext.History.fieldId);
\r
36539 iframe = Ext.getDom(Ext.History.iframeId);
\r
36541 this.addEvents('ready', 'change');
\r
36543 this.on('ready', onReady, scope, {single:true});
\r
36549 add: function (token, preventDup) {
\r
36550 if(preventDup !== false){
\r
36551 if(this.getToken() == token){
\r
36556 return updateIFrame(token);
\r
36558 top.location.hash = token;
\r
36564 back: function(){
\r
36569 forward: function(){
\r
36574 getToken: function() {
\r
36575 return ready ? currentToken : getHash();
\r
36579 Ext.apply(Ext.History, new Ext.util.Observable());
\r
36586 function createConsole(){
\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
36592 var tabs = new Ext.TabPanel({
\r
36595 tabPosition: 'bottom',
\r
36597 title: 'Debug Console',
\r
36599 items: [logView, scriptPanel]
\r
36601 title: 'DOM Inspector',
\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
36614 logView: logView,
\r
36619 handler: function(){
\r
36622 Ext.EventManager.removeResizeListener(handleResize);
\r
36629 cp.render(document.body);
\r
36631 cp.resizer = new Ext.Resizable(cp.el, {
\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
36644 function handleResize(){
\r
36645 cp.setWidth(Ext.getBody().getViewSize().width);
\r
36647 Ext.EventManager.onWindowResize(handleResize);
\r
36654 log : function(){
\r
36658 cp.logView.log.apply(cp.logView, arguments);
\r
36661 logf : function(format, arg1, arg2, etc){
\r
36662 Ext.log(String.format.apply(String, arguments));
\r
36665 dump : function(o){
\r
36666 if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){
\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
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
36682 var s = b.join("");
\r
36683 if(s.length > 3){
\r
36684 s = s.substr(0, s.length-2);
\r
36686 Ext.log(s + "\n}");
\r
36692 time : function(name){
\r
36693 name = name || "def";
\r
36694 Ext._timers[name] = new Date().getTime();
\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
36712 Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
\r
36713 id:'x-debug-scripts',
\r
36720 style:'border-width:0 0 0 1px;',
\r
36722 initComponent : function(){
\r
36724 this.scriptField = new Ext.form.TextArea({
\r
36725 anchor: '100% -26',
\r
36726 style:'border-width:0;'
\r
36729 this.trapBox = new Ext.form.Checkbox({
\r
36730 id: 'console-trap',
\r
36731 boxLabel: 'Trap Errors',
\r
36735 this.toolbar = new Ext.Toolbar([{
\r
36738 handler: this.evalScript
\r
36742 handler: this.clear
\r
36749 this.items = [this.toolbar, this.scriptField];
\r
36751 Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
\r
36754 evalScript : function(){
\r
36755 var s = this.scriptField.getValue();
\r
36756 if(this.trapBox.getValue()){
\r
36758 var rt = eval(s);
\r
36759 Ext.dump(rt === undefined? '(no return)' : rt);
\r
36761 Ext.log(e.message || e.descript);
\r
36764 var rt = eval(s);
\r
36765 Ext.dump(rt === undefined? '(no return)' : rt);
\r
36769 clear : function(){
\r
36770 this.scriptField.setValue('');
\r
36771 this.scriptField.focus();
\r
36776 Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
\r
36777 autoScroll: true,
\r
36778 region: 'center',
\r
36780 style:'border-width:0 1px 0 0',
\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, ' '),
\r
36785 '</div>'].join('');
\r
36787 this.body.insertHtml('beforeend', markup);
\r
36788 this.body.scrollTo('top', 100000);
\r
36791 clear : function(){
\r
36792 this.body.update('');
\r
36793 this.body.dom.scrollTop = 0;
\r
36797 Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
\r
36800 rootVisible:false,
\r
36802 hlColor:'ffff9c',
\r
36803 autoScroll: true,
\r
36807 initComponent : function(){
\r
36810 Ext.debug.DomTree.superclass.initComponent.call(this);
\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
36819 function findNode(n){
\r
36820 if(!n || n.nodeType != 1 || n == document.body || n == document){
\r
36823 var pn = [n], p = n;
\r
36824 while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){
\r
36828 for(var i = 0, len = pn.length; i < len; i++){
\r
36830 cn = cn.findChild('htmlNode', pn[i]);
\r
36831 if(!cn){ // in this dialog?
\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
36843 function nodeTitle(n){
\r
36844 var s = n.tagName;
\r
36847 }else if(n.className){
\r
36848 s += '.'+n.className;
\r
36853 function onNodeSelect(t, n, last){
\r
36855 if(last && last.unframe){
\r
36859 if(n && n.htmlNode){
\r
36860 if(frameEl.pressed){
\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
36874 while ((m = styleRe.exec(s)) != null){
\r
36875 props[m[1].toLowerCase()] = m[2];
\r
36878 }else if(styles){
\r
36879 var cl = Ext.debug.cssList;
\r
36880 var s = dom.style, fly = Ext.fly(dom);
\r
36882 for(var i = 0, len = cl.length; i<len; i++){
\r
36884 var v = s[st] || fly.getStyle(st);
\r
36885 if(v != undefined && v !== null && v !== ''){
\r
36891 for(var a in dom){
\r
36893 if((isNaN(a+10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())){
\r
36902 addStyle.disable();
\r
36903 reload.disabled();
\r
36905 stylesGrid.setSource(props);
\r
36906 stylesGrid.treeNode = n;
\r
36907 stylesGrid.view.fitColumns();
\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
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
36930 //tree.getSelectionModel().on('selectionchange', onNodeSelect, null, {buffer:250});
\r
36932 this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));
\r
36934 hnode = this.root.appendChild(new Ext.debug.HtmlNode(
\r
36935 document.getElementsByTagName('html')[0]
\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
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
36957 function hasChild(n){
\r
36958 for(var i = 0, c; c = n.childNodes[i]; i++){
\r
36959 if(c.nodeType == 1){
\r
36966 function renderNode(n, leaf){
\r
36967 var tag = n.tagName.toLowerCase();
\r
36968 var s = '<' + tag;
\r
36969 for(var i = 0, len = attrs.length; i < len; i++){
\r
36970 var a = attrs[i];
\r
36972 if(v && !nonSpace.test(v)){
\r
36973 s += ' ' + a.v + '="<i>' + html(v) +'</i>"';
\r
36976 var style = n.style ? n.style.cssText : '';
\r
36978 s += ' style="<i>' + html(style.toLowerCase()) +'</i>"';
\r
36980 if(leaf && n.childNodes.length > 0){
\r
36981 s+='><em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em></'+tag+'>';
\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
36995 text : renderNode(n, leaf),
\r
36997 cls: 'x-tree-noicon'
\r
36999 HtmlNode.superclass.constructor.call(this, attr);
\r
37000 this.attributes.htmlNode = n; // for searching
\r
37002 this.on('expand', this.onExpand, this);
\r
37003 this.on('collapse', this.onCollapse, this);
\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
37015 Ext.fly(this.ui.textNode).highlight();
\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:'</' + this.tagName + '>',
\r
37023 cls: 'x-tree-noicon'
\r
37024 }), this.nextSibling);
\r
37025 }else if(this.closeNode){
\r
37026 this.closeNode.ui.show();
\r
37030 onCollapse : function(){
\r
37031 if(this.closeNode){
\r
37032 this.closeNode.ui.hide();
\r
37036 render : function(bulkRender){
\r
37037 HtmlNode.superclass.render.call(this, bulkRender);
\r
37040 highlightNode : function(){
\r
37041 //Ext.fly(this.htmlNode).highlight();
\r
37044 highlight : function(){
\r
37045 //Ext.fly(this.ui.textNode).highlight();
\r
37048 frame : function(){
\r
37049 this.htmlNode.style.border = '1px solid #0000ff';
\r
37050 //this.highlightNode();
\r
37053 unframe : function(){
\r
37054 //Ext.fly(this.htmlNode).removeClass('x-debug-frame');
\r
37055 this.htmlNode.style.border = '';
\r