debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:27k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.0.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. Ext.debug = {};
  8. (function(){
  9. var cp;
  10. function createConsole(){
  11.     var scriptPanel = new Ext.debug.ScriptsPanel();
  12.     var logView = new Ext.debug.LogPanel();
  13.     var tree = new Ext.debug.DomTree();
  14.     var compInspector = new Ext.debug.ComponentInspector();
  15.     var compInfoPanel = new Ext.debug.ComponentInfoPanel();
  16.     var storeInspector = new Ext.debug.StoreInspector();
  17.     var objInspector = new Ext.debug.ObjectInspector();
  18.     var tabs = new Ext.TabPanel({
  19.         activeTab: 0,
  20.         border: false,
  21.         tabPosition: 'bottom',
  22.         items: [{
  23.             title: 'Debug Console',
  24.             layout:'border',
  25.             items: [logView, scriptPanel]
  26.         },{
  27.             title: 'HTML Inspector',
  28.             layout:'border',
  29.             items: [tree]
  30.         },{
  31.             title: 'Component Inspector',
  32.             layout: 'border',
  33.             items: [compInspector,compInfoPanel]
  34.         },{
  35.             title: 'Object Inspector',
  36.             layout: 'border',
  37.             items: [objInspector]
  38.         },{
  39.             title: 'Data Stores',
  40.             layout: 'border',
  41.             items: [storeInspector]
  42.         }]
  43.     });
  44.     cp = new Ext.Panel({
  45.         id: 'x-debug-browser',
  46.         title: 'Console',
  47.         collapsible: true,
  48.         animCollapse: false,
  49.         style: 'position:absolute;left:0;bottom:0;z-index:101',
  50.         height:200,
  51.         logView: logView,
  52.         layout: 'fit',
  53.         tools:[{
  54.             id: 'close',
  55.             handler: function(){
  56.                 cp.destroy();
  57.                 cp = null;
  58.                 Ext.EventManager.removeResizeListener(handleResize);
  59.             }
  60.         }],
  61.         items: tabs
  62.     });
  63.     cp.render(Ext.getBody());
  64.     cp.resizer = new Ext.Resizable(cp.el, {
  65.         minHeight:50,
  66.         handles: "n",
  67.         pinned: true,
  68.         transparent:true,
  69.         resizeElement : function(){
  70.             var box = this.proxy.getBox();
  71.             this.proxy.hide();
  72.             cp.setHeight(box.height);
  73.             return box;
  74.         }
  75.     });
  76. //     function handleResize(){
  77. //         cp.setWidth(Ext.getBody().getViewSize().width);
  78. //     }
  79. //     Ext.EventManager.onWindowResize(handleResize);
  80. //
  81. //     handleResize();
  82.     function handleResize(){
  83.         var b = Ext.getBody()
  84.         var size = b.getViewSize();
  85.         if(size.height < b.dom.scrollHeight) {
  86.             size.width -= 18;
  87.         }
  88.         cp.setWidth(size.width);
  89.     }
  90.     Ext.EventManager.onWindowResize(handleResize);
  91.     handleResize();
  92. }
  93. Ext.apply(Ext, {
  94.     log : function(){
  95.         if(!cp){
  96.             createConsole();
  97.         }
  98.         cp.logView.log.apply(cp.logView, arguments);
  99.     },
  100.     logf : function(format, arg1, arg2, etc){
  101.         Ext.log(String.format.apply(String, arguments));
  102.     },
  103.     dump : function(o){
  104.         if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){
  105.             Ext.log(o);
  106.         }else if(!o){
  107.             Ext.log("null");
  108.         }else if(typeof o != "object"){
  109.             Ext.log('Unknown return type');
  110.         }else if(Ext.isArray(o)){
  111.             Ext.log('['+o.join(',')+']');
  112.         }else{
  113.             var b = ["{n"];
  114.             for(var key in o){
  115.                 var to = typeof o[key];
  116.                 if(to != "function" && to != "object"){
  117.                     b.push(String.format("  {0}: {1},n", key, o[key]));
  118.                 }
  119.             }
  120.             var s = b.join("");
  121.             if(s.length > 3){
  122.                 s = s.substr(0, s.length-2);
  123.             }
  124.             Ext.log(s + "n}");
  125.         }
  126.     },
  127.     _timers : {},
  128.     time : function(name){
  129.         name = name || "def";
  130.         Ext._timers[name] = new Date().getTime();
  131.     },
  132.     timeEnd : function(name, printResults){
  133.         var t = new Date().getTime();
  134.         name = name || "def";
  135.         var v = String.format("{0} ms", t-Ext._timers[name]);
  136.         Ext._timers[name] = new Date().getTime();
  137.         if(printResults !== false){
  138.             Ext.log('Timer ' + (name == "def" ? v : name + ": " + v));
  139.         }
  140.         return v;
  141.     }
  142. });
  143. })();
  144. Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
  145.     id:'x-debug-scripts',
  146.     region: 'east',
  147.     minWidth: 200,
  148.     split: true,
  149.     width: 350,
  150.     border: false,
  151.     layout:'anchor',
  152.     style:'border-width:0 0 0 1px;',
  153.     initComponent : function(){
  154.         this.scriptField = new Ext.form.TextArea({
  155.             anchor: '100% -26',
  156.             style:'border-width:0;'
  157.         });
  158.         this.trapBox = new Ext.form.Checkbox({
  159.             id: 'console-trap',
  160.             boxLabel: 'Trap Errors',
  161.             checked: true
  162.         });
  163.         this.toolbar = new Ext.Toolbar([{
  164.                 text: 'Run',
  165.                 scope: this,
  166.                 handler: this.evalScript
  167.             },{
  168.                 text: 'Clear',
  169.                 scope: this,
  170.                 handler: this.clear
  171.             },
  172.             '->',
  173.             this.trapBox,
  174.             ' ', ' '
  175.         ]);
  176.         this.items = [this.toolbar, this.scriptField];
  177.         Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
  178.     },
  179.     evalScript : function(){
  180.         var s = this.scriptField.getValue();
  181.         if(this.trapBox.getValue()){
  182.             try{
  183.                 var rt = eval(s);
  184.                 Ext.dump(rt === undefined? '(no return)' : rt);
  185.             }catch(e){
  186.                 Ext.log(e.message || e.descript);
  187.             }
  188.         }else{
  189.             var rt = eval(s);
  190.             Ext.dump(rt === undefined? '(no return)' : rt);
  191.         }
  192.     },
  193.     clear : function(){
  194.         this.scriptField.setValue('');
  195.         this.scriptField.focus();
  196.     }
  197. });
  198. Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
  199.     autoScroll: true,
  200.     region: 'center',
  201.     border: false,
  202.     style:'border-width:0 1px 0 0',
  203.     log : function(){
  204.         var markup = [  '<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
  205.                     Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/n/g, '<br />').replace(/s/g, '&#160;'),
  206.                     '</div>'].join('');
  207.         this.body.insertHtml('beforeend', markup);
  208.         this.body.scrollTo('top', 100000);
  209.     },
  210.     clear : function(){
  211.         this.body.update('');
  212.         this.body.dom.scrollTop = 0;
  213.     }
  214. });
  215. Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
  216.     enableDD:false ,
  217.     lines:false,
  218.     rootVisible:false,
  219.     animate:false,
  220.     hlColor:'ffff9c',
  221.     autoScroll: true,
  222.     region:'center',
  223.     border:false,
  224.     initComponent : function(){
  225.         Ext.debug.DomTree.superclass.initComponent.call(this);
  226.         // tree related stuff
  227.         var styles = false, hnode;
  228.         var nonSpace = /^s*$/;
  229.         var html = Ext.util.Format.htmlEncode;
  230.         var ellipsis = Ext.util.Format.ellipsis;
  231.         var styleRe = /s?([a-z-]*):([^;]*)(?:[;snr]*)/gi;
  232.         function findNode(n){
  233.             if(!n || n.nodeType != 1 || n == document.body || n == document){
  234.                 return false;
  235.             }
  236.             var pn = [n], p = n;
  237.             while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){
  238.                 pn.unshift(p);
  239.             }
  240.             var cn = hnode;
  241.             for(var i = 0, len = pn.length; i < len; i++){
  242.                 cn.expand();
  243.                 cn = cn.findChild('htmlNode', pn[i]);
  244.                 if(!cn){ // in this dialog?
  245.                     return false;
  246.                 }
  247.             }
  248.             cn.select();
  249.             var a = cn.ui.anchor;
  250.             treeEl.dom.scrollTop = Math.max(0 ,a.offsetTop-10);
  251.             //treeEl.dom.scrollLeft = Math.max(0 ,a.offsetLeft-10); no likey
  252.             cn.highlight();
  253.             return true;
  254.         }
  255.         function nodeTitle(n){
  256.             var s = n.tagName;
  257.             if(n.id){
  258.                 s += '#'+n.id;
  259.             }else if(n.className){
  260.                 s += '.'+n.className;
  261.             }
  262.             return s;
  263.         }
  264.         function onNodeSelect(t, n, last){
  265.             return;
  266.             if(last && last.unframe){
  267.                 last.unframe();
  268.             }
  269.             var props = {};
  270.             if(n && n.htmlNode){
  271.                 if(frameEl.pressed){
  272.                     n.frame();
  273.                 }
  274.                 if(inspecting){
  275.                     return;
  276.                 }
  277.                 addStyle.enable();
  278.                 reload.setDisabled(n.leaf);
  279.                 var dom = n.htmlNode;
  280.                 stylePanel.setTitle(nodeTitle(dom));
  281.                 if(styles && !showAll.pressed){
  282.                     var s = dom.style ? dom.style.cssText : '';
  283.                     if(s){
  284.                         var m;
  285.                         while ((m = styleRe.exec(s)) != null){
  286.                             props[m[1].toLowerCase()] = m[2];
  287.                         }
  288.                     }
  289.                 }else if(styles){
  290.                     var cl = Ext.debug.cssList;
  291.                     var s = dom.style, fly = Ext.fly(dom);
  292.                     if(s){
  293.                         for(var i = 0, len = cl.length; i<len; i++){
  294.                             var st = cl[i];
  295.                             var v = s[st] || fly.getStyle(st);
  296.                             if(v != undefined && v !== null && v !== ''){
  297.                                 props[st] = v;
  298.                             }
  299.                         }
  300.                     }
  301.                 }else{
  302.                     for(var a in dom){
  303.                         var v = dom[a];
  304.                         if((isNaN(a+10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())){
  305.                             props[a] = v;
  306.                         }
  307.                     }
  308.                 }
  309.             }else{
  310.                 if(inspecting){
  311.                     return;
  312.                 }
  313.                 addStyle.disable();
  314.                 reload.disabled();
  315.             }
  316.             stylesGrid.setSource(props);
  317.             stylesGrid.treeNode = n;
  318.             stylesGrid.view.fitColumns();
  319.         }
  320.         this.loader = new Ext.tree.TreeLoader();
  321.         this.loader.load = function(n, cb){
  322.             var isBody = n.htmlNode == document.body;
  323.             var cn = n.htmlNode.childNodes;
  324.             for(var i = 0, c; c = cn[i]; i++){
  325.                 if(isBody && c.id == 'x-debug-browser'){
  326.                     continue;
  327.                 }
  328.                 if(c.nodeType == 1){
  329.                     n.appendChild(new Ext.debug.HtmlNode(c));
  330.                 }else if(c.nodeType == 3 && !nonSpace.test(c.nodeValue)){
  331.                     n.appendChild(new Ext.tree.TreeNode({
  332.                         text:'<em>' + ellipsis(html(String(c.nodeValue)), 35) + '</em>',
  333.                         cls: 'x-tree-noicon'
  334.                     }));
  335.                 }
  336.             }
  337.             cb();
  338.         };
  339.         //tree.getSelectionModel().on('selectionchange', onNodeSelect, null, {buffer:250});
  340.         this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));
  341.         hnode = this.root.appendChild(new Ext.debug.HtmlNode(
  342.                 document.getElementsByTagName('html')[0]
  343.         ));
  344.     }
  345. });
  346. Ext.debug.ComponentNodeUI = Ext.extend(Ext.tree.TreeNodeUI,{
  347.     onOver : function(e){
  348.         Ext.debug.ComponentNodeUI.superclass.onOver.call(this);
  349.         var cmp = this.node.attributes.component;
  350.         if (cmp.el && cmp.el.mask && cmp.id !='x-debug-browser') {
  351.             try { // Oddly bombs on some elements in IE, gets any we care about though
  352.                 cmp.el.mask();
  353.             } catch(e) {}
  354.         }
  355.     },
  356.     onOut : function(e){
  357.         Ext.debug.ComponentNodeUI.superclass.onOut.call(this);
  358.         var cmp = this.node.attributes.component;
  359.         if (cmp.el && cmp.el.unmask && cmp.id !='x-debug-browser') {
  360.             try {
  361.                 cmp.el.unmask();
  362.             } catch(e) {}
  363.         }
  364.     }
  365. });
  366. Ext.debug.ComponentInspector = Ext.extend(Ext.tree.TreePanel, {
  367.     enableDD:false ,
  368.     lines:false,
  369.     rootVisible:false,
  370.     animate:false,
  371.     hlColor:'ffff9c',
  372.     autoScroll: true,
  373.     region:'center',
  374.     border:false,
  375.     initComponent : function(){
  376.         this.loader = new Ext.tree.TreeLoader();
  377.         this.bbar = new Ext.Toolbar([{
  378.             text: 'Refresh',
  379.             handler: this.refresh,
  380.             scope: this
  381.         }]);
  382.         Ext.debug.ComponentInspector.superclass.initComponent.call(this);
  383.         this.root = this.setRootNode(new Ext.tree.TreeNode({
  384.             text: 'Ext Components',
  385.             component: Ext.ComponentMgr.all,
  386.             leaf: false
  387.         }));
  388.         this.parseRootNode();
  389.         this.on('click', this.onClick, this);
  390.     },
  391.     createNode: function(n,c) {
  392.         var leaf = (c.items && c.items.length > 0);
  393.         return n.appendChild(new Ext.tree.TreeNode({
  394.             text: c.id + (c.getXType() ? ' [ ' + c.getXType() + ' ]': '' ),
  395.             component: c,
  396.             uiProvider:Ext.debug.ComponentNodeUI,
  397.             leaf: !leaf
  398.         }));
  399.     },
  400.     parseChildItems: function(n) {
  401.         var cn = n.attributes.component.items;
  402.         if (cn) {
  403.             for (var i = 0;i < cn.length; i++) {
  404.                 var c = cn.get(i);
  405.                 if (c.id != this.id && c.id != this.bottomToolbar.id) {
  406.                     var newNode = this.createNode(n,c);
  407.                     if (!newNode.leaf) {
  408.                         this.parseChildItems(newNode)
  409.                     }
  410.                 }
  411.             }
  412.         }
  413.     },
  414.     parseRootNode: function() {
  415.         var n = this.root;
  416.         var cn = n.attributes.component.items;
  417.         for (var i = 0,c;c = cn[i];i++) {
  418.             if (c.id != this.id && c.id != this.bottomToolbar.id) {
  419.                 if (!c.ownerCt) {
  420.                     var newNode = this.createNode(n,c);
  421.                     if (!newNode.leaf) {
  422.                         this.parseChildItems(newNode);
  423.                     }
  424.                 }
  425.             }
  426.         }
  427.     },
  428.     onClick: function(node, e) {
  429.         var oi = Ext.getCmp('x-debug-objinspector');
  430.         oi.refreshNodes(node.attributes.component);
  431.         oi.ownerCt.show();
  432.     },
  433.     refresh: function() {
  434.         while (this.root.firstChild) {
  435.             this.root.removeChild(this.root.firstChild);
  436.         }
  437.         this.parseRootNode();
  438.         var ci = Ext.getCmp('x-debug-compinfo');
  439.         if (ci) {
  440.             ci.message('refreshed component tree - '+Ext.ComponentMgr.all.length)
  441.         }
  442.     }
  443. });
  444. Ext.debug.ComponentInfoPanel = Ext.extend(Ext.Panel,{
  445.     id:'x-debug-compinfo',
  446.     region: 'east',
  447.     minWidth: 200,
  448.     split: true,
  449.     width: 350,
  450.     border: false,
  451.     autoScroll: true,
  452.     layout:'anchor',
  453.     style:'border-width:0 0 0 1px;',
  454.     initComponent: function() {
  455.         this.watchBox = new Ext.form.Checkbox({
  456.             id: 'x-debug-watchcomp',
  457.             boxLabel: 'Watch ComponentMgr',
  458.             listeners: {
  459.                 check: function(cb, val) {
  460.                     if (val) {
  461.                         Ext.ComponentMgr.all.on('add', this.onAdd, this);
  462.                         Ext.ComponentMgr.all.on('remove', this.onRemove, this);
  463.                     } else {
  464.                         Ext.ComponentMgr.all.un('add', this.onAdd, this);
  465.                         Ext.ComponentMgr.all.un('remove', this.onRemove, this);
  466.                     }
  467.                 },
  468.                 scope: this
  469.             }
  470.         });
  471.         this.tbar = new Ext.Toolbar([{
  472.             text: 'Clear',
  473.             handler: this.clear,
  474.             scope: this
  475.         },'->',this.watchBox
  476.         ]);
  477.         Ext.debug.ComponentInfoPanel.superclass.initComponent.call(this);
  478.     },
  479.     onAdd: function(i, o, key) {
  480.         var markup = ['<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
  481.                     'Added: '+o.id,
  482.                     '</div>'].join('');
  483.         this.insertMarkup(markup);
  484.     },
  485.     onRemove: function(o, key) {
  486.         var markup = ['<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
  487.                     'Removed: '+o.id,
  488.                     '</div>'].join('');
  489.         this.insertMarkup(markup);
  490.     },
  491.     message: function(msg) {
  492.         var markup = ['<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
  493.                     msg,
  494.                     '</div>'].join('');
  495.         this.insertMarkup(markup);
  496.     },
  497.     insertMarkup: function(markup) {
  498.         this.body.insertHtml('beforeend', markup);
  499.         this.body.scrollTo('top', 100000);
  500.     },
  501.     clear : function(){
  502.         this.body.update('');
  503.         this.body.dom.scrollTop = 0;
  504.     }
  505. });
  506. Ext.debug.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
  507.     focus: Ext.emptyFn, // prevent odd scrolling behavior
  508.     renderElements : function(n, a, targetNode, bulkRender){
  509.         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
  510.         var t = n.getOwnerTree();
  511.         var cols = t.columns;
  512.         var bw = t.borderWidth;
  513.         var c = cols[0];
  514.         var buf = [
  515.              '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
  516.                 '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
  517.                     '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
  518.                     '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
  519.                     '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
  520.                     '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
  521.                     a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
  522.                     '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
  523.                 "</div>"];
  524.          for(var i = 1, len = cols.length; i < len; i++){
  525.              c = cols[i];
  526.              buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
  527.                         '<div class="x-tree-col-text">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
  528.                       "</div>");
  529.          }
  530.          buf.push(
  531.             '<div class="x-clear"></div></div>',
  532.             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
  533.             "</li>");
  534.         if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
  535.             this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
  536.                                 n.nextSibling.ui.getEl(), buf.join(""));
  537.         }else{
  538.             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
  539.         }
  540.         this.elNode = this.wrap.childNodes[0];
  541.         this.ctNode = this.wrap.childNodes[1];
  542.         var cs = this.elNode.firstChild.childNodes;
  543.         this.indentNode = cs[0];
  544.         this.ecNode = cs[1];
  545.         this.iconNode = cs[2];
  546.         this.anchor = cs[3];
  547.         this.textNode = cs[3].firstChild;
  548.     }
  549. });
  550. Ext.debug.ObjectInspector = Ext.extend(Ext.tree.TreePanel, {
  551.     id: 'x-debug-objinspector',
  552.     enableDD:false ,
  553.     lines:false,
  554.     rootVisible:false,
  555.     animate:false,
  556.     hlColor:'ffff9c',
  557.     autoScroll: true,
  558.     region:'center',
  559.     border:false,
  560.     lines:false,
  561.     borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
  562.     cls:'x-column-tree',
  563.     initComponent : function(){
  564.         this.showFunc = false;
  565.         this.toggleFunc = function() {
  566.             this.showFunc = !this.showFunc;
  567.             this.refreshNodes(this.currentObject);
  568.         }
  569.         this.bbar = new Ext.Toolbar([{
  570.             text: 'Show Functions',
  571.             enableToggle: true,
  572.             pressed: false,
  573.             handler: this.toggleFunc,
  574.             scope: this
  575.         }]);
  576.         Ext.apply(this,{
  577.             title: ' ',
  578.             loader: new Ext.tree.TreeLoader(),
  579.             columns:[{
  580.                 header:'Property',
  581.                 width: 300,
  582.                 dataIndex:'name'
  583.             },{
  584.                 header:'Value',
  585.                 width: 900,
  586.                 dataIndex:'value'
  587.             }]
  588.         });
  589.         Ext.debug.ObjectInspector.superclass.initComponent.call(this);
  590.         this.root = this.setRootNode(new Ext.tree.TreeNode({
  591.             text: 'Dummy Node',
  592.             leaf: false
  593.         }));
  594.         if (this.currentObject) {
  595.             this.parseNodes();
  596.         }
  597.     },
  598.     refreshNodes: function(newObj) {
  599.         this.currentObject = newObj;
  600.         var node = this.root;
  601.         while(node.firstChild){
  602.             node.removeChild(node.firstChild);
  603.         }
  604.         this.parseNodes();
  605.     },
  606.     parseNodes: function() {
  607.         for (var o in this.currentObject) {
  608.             if (!this.showFunc) {
  609.                 if (Ext.isFunction(this.currentObject[o])) {
  610.                     continue;
  611.                 }
  612.             }
  613.             this.createNode(o);
  614.         }
  615.     },
  616.     createNode: function(o) {
  617.         return this.root.appendChild(new Ext.tree.TreeNode({
  618.             name: o,
  619.             value: this.currentObject[o],
  620.             uiProvider:Ext.debug.ColumnNodeUI,
  621.             iconCls: 'x-debug-node',
  622.             leaf: true
  623.         }));
  624.     },
  625.     onRender : function(){
  626.         Ext.debug.ObjectInspector.superclass.onRender.apply(this, arguments);
  627.         this.headers = this.header.createChild({cls:'x-tree-headers'});
  628.         var cols = this.columns, c;
  629.         var totalWidth = 0;
  630.         for(var i = 0, len = cols.length; i < len; i++){
  631.              c = cols[i];
  632.              totalWidth += c.width;
  633.              this.headers.createChild({
  634.                  cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
  635.                  cn: {
  636.                      cls:'x-tree-hd-text',
  637.                      html: c.header
  638.                  },
  639.                  style:'width:'+(c.width-this.borderWidth)+'px;'
  640.              });
  641.         }
  642.         this.headers.createChild({cls:'x-clear'});
  643.         // prevent floats from wrapping when clipped
  644.         this.headers.setWidth(totalWidth);
  645.         this.innerCt.setWidth(totalWidth);
  646.     }
  647. });
  648. Ext.debug.StoreInspector = Ext.extend(Ext.tree.TreePanel, {
  649.     enableDD:false ,
  650.     lines:false,
  651.     rootVisible:false,
  652.     animate:false,
  653.     hlColor:'ffff9c',
  654.     autoScroll: true,
  655.     region:'center',
  656.     border:false,
  657.     initComponent: function() {
  658.         this.bbar = new Ext.Toolbar([{
  659.             text: 'Refresh',
  660.             handler: this.refresh,
  661.             scope: this
  662.         }]);
  663.         Ext.debug.StoreInspector.superclass.initComponent.call(this);
  664.         this.root = this.setRootNode(new Ext.tree.TreeNode({
  665.             text: 'Data Stores',
  666.             leaf: false
  667.         }));
  668.         this.on('click', this.onClick, this);
  669.         this.parseStores();
  670.     },
  671.     parseStores: function() {
  672.         var cn = Ext.StoreMgr.items;
  673.         for (var i = 0,c;c = cn[i];i++) {
  674.             this.root.appendChild({
  675.                 text: c.storeId + ' - ' + c.totalLength + ' records',
  676.                 component: c,
  677.                 leaf: true
  678.             });
  679.         }
  680.     },
  681.     onClick: function(node, e) {
  682.         var oi = Ext.getCmp('x-debug-objinspector');
  683.         oi.refreshNodes(node.attributes.component);
  684.         oi.ownerCt.show();
  685.     },
  686.     refresh: function() {
  687.         while (this.root.firstChild) {
  688.             this.root.removeChild(this.root.firstChild);
  689.         }
  690.         this.parseStores();
  691.     }
  692. });
  693. // highly unusual class declaration
  694. Ext.debug.HtmlNode = function(){
  695.     var html = Ext.util.Format.htmlEncode;
  696.     var ellipsis = Ext.util.Format.ellipsis;
  697.     var nonSpace = /^s*$/;
  698.     var attrs = [
  699.         {n: 'id', v: 'id'},
  700.         {n: 'className', v: 'class'},
  701.         {n: 'name', v: 'name'},
  702.         {n: 'type', v: 'type'},
  703.         {n: 'src', v: 'src'},
  704.         {n: 'href', v: 'href'}
  705.     ];
  706.     function hasChild(n){
  707.         for(var i = 0, c; c = n.childNodes[i]; i++){
  708.             if(c.nodeType == 1){
  709.                 return true;
  710.             }
  711.         }
  712.         return false;
  713.     }
  714.     function renderNode(n, leaf){
  715.         var tag = n.tagName.toLowerCase();
  716.         var s = '&lt;' + tag;
  717.         for(var i = 0, len = attrs.length; i < len; i++){
  718.             var a = attrs[i];
  719.             var v = n[a.n];
  720.             if(v && !nonSpace.test(v)){
  721.                 s += ' ' + a.v + '=&quot;<i>' + html(v) +'</i>&quot;';
  722.             }
  723.         }
  724.         var style = n.style ? n.style.cssText : '';
  725.         if(style){
  726.             s += ' style=&quot;<i>' + html(style.toLowerCase()) +'</i>&quot;';
  727.         }
  728.         if(leaf && n.childNodes.length > 0){
  729.             s+='&gt;<em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em>&lt;/'+tag+'&gt;';
  730.         }else if(leaf){
  731.             s += ' /&gt;';
  732.         }else{
  733.             s += '&gt;';
  734.         }
  735.         return s;
  736.     }
  737.     var HtmlNode = function(n){
  738.         var leaf = !hasChild(n);
  739.         this.htmlNode = n;
  740.         this.tagName = n.tagName.toLowerCase();
  741.         var attr = {
  742.             text : renderNode(n, leaf),
  743.             leaf : leaf,
  744.             cls: 'x-tree-noicon'
  745.         };
  746.         HtmlNode.superclass.constructor.call(this, attr);
  747.         this.attributes.htmlNode = n; // for searching
  748.         if(!leaf){
  749.             this.on('expand', this.onExpand,  this);
  750.             this.on('collapse', this.onCollapse,  this);
  751.         }
  752.     };
  753.     Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {
  754.         cls: 'x-tree-noicon',
  755.         preventHScroll: true,
  756.         refresh : function(highlight){
  757.             var leaf = !hasChild(this.htmlNode);
  758.             this.setText(renderNode(this.htmlNode, leaf));
  759.             if(highlight){
  760.                 Ext.fly(this.ui.textNode).highlight();
  761.             }
  762.         },
  763.         onExpand : function(){
  764.             if(!this.closeNode && this.parentNode){
  765.                 this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({
  766.                     text:'&lt;/' + this.tagName + '&gt;',
  767.                     cls: 'x-tree-noicon'
  768.                 }), this.nextSibling);
  769.             }else if(this.closeNode){
  770.                 this.closeNode.ui.show();
  771.             }
  772.         },
  773.         onCollapse : function(){
  774.             if(this.closeNode){
  775.                 this.closeNode.ui.hide();
  776.             }
  777.         },
  778.         render : function(bulkRender){
  779.             HtmlNode.superclass.render.call(this, bulkRender);
  780.         },
  781.         highlightNode : function(){
  782.             //Ext.fly(this.htmlNode).highlight();
  783.         },
  784.         highlight : function(){
  785.             //Ext.fly(this.ui.textNode).highlight();
  786.         },
  787.         frame : function(){
  788.             this.htmlNode.style.border = '1px solid #0000ff';
  789.             //this.highlightNode();
  790.         },
  791.         unframe : function(){
  792.             //Ext.fly(this.htmlNode).removeClass('x-debug-frame');
  793.             this.htmlNode.style.border = '';
  794.         }
  795.     });
  796.     return HtmlNode;
  797. }();